|
|
View previous topic :: View next topic |
Author |
Message |
tongbram
Joined: 27 Nov 2008 Posts: 11
|
SPI not working |
Posted: Wed Dec 03, 2008 2:12 am |
|
|
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
|
|
Posted: Wed Dec 03, 2008 2:50 am |
|
|
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
|
working fine |
Posted: Wed Dec 03, 2008 3:34 am |
|
|
Thank you sir ...now its working.... _________________ manibabu |
|
|
tongbram
Joined: 27 Nov 2008 Posts: 11
|
SD initialization |
Posted: Thu Dec 04, 2008 2:36 am |
|
|
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
|
|
Posted: Thu Dec 04, 2008 4:59 pm |
|
|
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?
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
|
|
Posted: Mon Oct 04, 2010 5:51 am |
|
|
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. |
|
|
|
|
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
|