CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SPI not working

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tongbram



Joined: 27 Nov 2008
Posts: 11

View user's profile Send private message AIM Address ICQ Number

SPI not working
PostPosted: Wed Dec 03, 2008 2:12 am     Reply with quote

Can anybody tell what's wrong in my code ? I'm trying to simply use spi hardware routine. I'm not getting data at SDO neither CLK.

Code:

//#include "C:\CCS_prog\xxx\xx.h"
#include <18F2550.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES NOSTVREN                 //Stack full/underflow will not cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1                     //No PLL PreScaler

#use delay(clock=8000000)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#use spi(FORCE_HW, BITS=8)
#use fast_io(c)

#define  Led1            PIN_B0
#define  Led2            PIN_B2
#define  Push_Button     PIN_A5

void main()
{
   int8 i,j,Ok_Data,count;

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_low_volt_detect(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_31250|OSC_PLL_OFF);

   set_tris_c(0x40);
   while(1)
   {
      spi_write(0xAA);
      OUTPUT_HIGH(Led1);
      delay_ms(100);
      OUTPUT_LOW(Led1);
      delay_ms(100);

   }

}

_________________
manibabu
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 2:50 am     Reply with quote

Quote:
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

The SDO pin is on C7 in this PIC. You can't use the hardware UART
and the hardware SPI at the same time. Comment out the line above.


Quote:
#use spi(FORCE_HW, BITS=8)

setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);

These are two different methods of setting up the SPI. They are not
compatible. Use one or the other, but don't use both. I suggest that
you delete the #use spi() statement.


Quote:
#use fast_io(c)

set_tris_c(0x40);

I suggest that you let the compiler handle the TRIS. It will handle it
properly if you delete those two lines.


Quote:
while(1)
{
spi_write(0xAA);
OUTPUT_HIGH(Led1);
delay_ms(100);
OUTPUT_LOW(Led1);
delay_ms(100);
}

How do you propose to see the SPI pulses, given the large delays in
this loop ? The SCLK pulses will just be one little blip on the scope.
You probably won't see it. Use a much tighter loop. Example:
Code:
while(1)
  {
   spi_write(0x55);
   delay_us(100);
  }


Quote:
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);

It's easier if you use the following SPI mode constants instead of the
CCS constants:
Code:
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)


Then it looks like this:
Code:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);

It's now obvious that you're using mode 0. The code becomes self-
documenting. If you come back to it months later, you will immediately
understand what you had written.
tongbram



Joined: 27 Nov 2008
Posts: 11

View user's profile Send private message AIM Address ICQ Number

working fine
PostPosted: Wed Dec 03, 2008 3:34 am     Reply with quote

Thank you sir ...now its working....
_________________
manibabu
tongbram



Joined: 27 Nov 2008
Posts: 11

View user's profile Send private message AIM Address ICQ Number

SD initialization
PostPosted: Thu Dec 04, 2008 2:36 am     Reply with quote

sir now my SPI is working fine.....i m trying to initialize SD card(2GB) using driver mmc.c but it always fail. can u see the code and please tell whats wrong in it..



Code:
//#include "C:\CCS_prog\xxx\xx.h"
#include <18F2550.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES NOSTVREN                 //Stack full/underflow will not cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1                     //No PLL PreScaler

#include "mmc.c"
#use delay(clock=8000000)
#use fast_io(c)
//#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

//#use spi(DI=PIN_C4, DO=PIN_C2, CLK =PIN_C1, MODE=0, BITS=8)
// uses software

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#define  Led1            PIN_B7
#define  Led2            PIN_B6
#define  Push_Button     PIN_A5

int8 Rec_Data,Rmc_Data[70];

void main()
{
   int8 i,j,Ok_Data,count;
   int error;

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
//   setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);
   SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_low_volt_detect(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_31250|OSC_PLL_OFF);
   set_tris_c(0x90);

   error = mmc_init();
   if(error > 0)
   {
      OUTPUT_HIGH(Led2);
      delay_ms(200);
      OUTPUT_LOW(Led2);
   }

   while(1)
   {
  //    spi_xfer(0xAA);
  //    delay_us(200);
        OUTPUT_HIGH(Led1);
        delay_ms(200);
        OUTPUT_LOW(Led1);
        delay_ms(100);

   }
}



and the driver is
Code:

// Written by Ed Waugh 2004, www.edwaugh.co.uk

// for the original source, and hundreds more examples of PIC C code, see:
// http://www.microchipc.com/sourcecode/#mmc

int mmc_init();
int mmc_response(unsigned char response);
int mmc_read_block(unsigned long block_number);
int mmc_write_block(unsigned long block_number);
int mmc_get_status();

int8 HIGH(long data)
{
   int8 modi;
   modi = data>>8;
   return(modi);
}

int8 LOW(long data)
{
   int8 modi;
   modi = data;
   return(modi);
}


/************************** MMC Init **************************************/
/* Initialises the MMC into SPI mode and sets block size, returns 0 on success */

int mmc_init()
{
int i;

SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);

*0x94 |= 0x40;                          // set CKE = 1 - clock idle low
*0x14 &= 0xEF;                          // set CKP = 0 - data valid on rising edge

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)

for(i=0;i<10;i++)                       // initialise the MMC card into SPI mode by sending clks on
{
        SPI_WRITE(0xFF);
}

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on) tells card to go to spi mode when it receives reset

SPI_WRITE(0x40);                        // send reset command
SPI_WRITE(0x00);                        // all the arguments are 0x00 for the reset command
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95);                        // precalculated checksum as we are still in MMC mode

//puts("Sent go to SPI\n\r");

if(mmc_response(0x01)==1) return 1;     // if = 1 then there was a timeout waiting for 0x01 from the mmc

//puts("Got response from MMC\n\r");

i = 0;

while((i < 255) && (mmc_response(0x00)==1))     // must keep sending command if response
{
        SPI_WRITE(0x41);                // send mmc command one to bring out of idle state
        SPI_WRITE(0x00);                // all the arguments are 0x00 for command one
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
        i++;
}
if(i >= 254) return 1;                   // if >= 254 then there was a timeout waiting for 0x00 from the mmc

//puts("Got out of idle response from MMC\n\r");

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)

SPI_WRITE(0xFF);                        // extra clocks to allow mmc to finish off what it is doing

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x50);                // send mmc command one to bring out of idle state
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0x02);                // high block length bits - 512 bytes
        SPI_WRITE(0x00);                // low block length bits
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;
OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
//puts("Got set block length response from MMC\n\r");
return 0;
}

/************************** MMC Get Status **************************************/
/* Get the status register of the MMC, for debugging purposes */

int mmc_get_status()
{

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x58);                // send mmc command one to bring out of idle state
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);                //
        SPI_WRITE(0x00);                // always zero as mulitples of 512
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
return 0;
}

/************************** MMC Write Block **************************************/

int mmc_write_block(unsigned long block_number)
{
unsigned long i;
unsigned long varh,varl;

varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);

//puts("Write block\n\r");                // block size has been set in mmc_init()

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x58);                // send mmc write block
        SPI_WRITE(HIGH(varh));
        SPI_WRITE(LOW(varh));
        SPI_WRITE(HIGH(varl));
        SPI_WRITE(0x00);                // always zero as mulitples of 512
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;
//puts("Got response to write block\n\r");

SPI_WRITE(0xFE);                        // send data token

for(i=0;i<512;i++)
{

//SPI_WRITE(i2c_eeprom_read(HIGH(i),LOW(i)));     // send data

}

SPI_WRITE(0xFF);                        // dummy CRC
SPI_WRITE(0xFF);

if((SPI_READ(0xFF)&0x0F)!=0x05) return 1;

//puts("Got data response to write block\n\r");

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
return 0;
}



/************************** MMC Read Block **************************************/
/**** Reads a 512 Byte block from the MMC and outputs each byte to RS232 ****/

int mmc_read_block(unsigned long block_number)
{
unsigned long i;
unsigned long varh,varl;

varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x51);                // send mmc read single block command
        SPI_WRITE(HIGH(varh));      // arguments are address
        SPI_WRITE(LOW(varh));
        SPI_WRITE(HIGH(varl));
        SPI_WRITE(0x00);
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;   // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)

//puts("Got response to read block command\n\r");

if((mmc_response(0xFE))==1) return 1;   // wait for data token

//puts("Got data token\n\r");

        for(i=0;i<512;i++)
        {
               // putc(SPI_READ(0xFF));               // we should now receive 512 bytes
        }

SPI_READ(0xFF);                 // CRC bytes that are not needed
SPI_READ(0xFF);

OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
SPI_WRITE(0xFF);                // give mmc the clocks it needs to finish off

//puts("\n\rEnd of read block\n\r");

return 0;
}

/************************** MMC get response **************************************/
/**** Repeatedly reads the MMC until we get the response we want or timeout ****/

int mmc_response(unsigned char response)
{
        unsigned long count = 0xFFFF;           // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point

        while(SPI_READ(0xFF) != response && --count > 0);

        if(count==0) return 1;                  // loop was exited due to timeout
        else return 0;                          // loop was exited before timeout
}

_________________
manibabu
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Dec 04, 2008 4:59 pm     Reply with quote

Code:
   SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);
I didn't look at the rest of the code but some comments on this line:
- Why don't you use the nice SPI_MODE defines from earlier in this thread?
- SD & MMC cards are designed to work in SPI mode 0 or 3. You have configured it for mode 2.
- NEVER use SPI_SS_DISABLED in a SPI master! This is a 'slave only' option and messes up your SPI configuration.

In the driver you have:
Code:
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);
Here the same comments apply.

And you also have:
Code:
*0x94 |= 0x40;                          // set CKE = 1 - clock idle low
*0x14 &= 0xEF;                          // set CKP = 0 - data valid on rising edge
You really like SPI don't you? Confused
Problem with this last configuration is that it is for a PIC16 processor. In the PIC18 these registers are at other locations and you are now corrupting data in RAM.

Most likely there are more errors but start fixing the above errors first.
Other things to check:
Do you have the 100k pull ups on the SPI data lines?
Have you made sure to cross the SPI data lines? That is, the Data Out of the PIC to the Data In of the SD and vice versa?
Skirmitt



Joined: 19 May 2009
Posts: 60

View user's profile Send private message

PostPosted: Mon Oct 04, 2010 5:51 am     Reply with quote

I also looked at this sample code. Have been able to integrate it succesfully in your code ?
I want to use the same code but I have no knowledge of setting up the SPI parameters for PIC18. I only need to handle RAW data.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group