|
|
View previous topic :: View next topic |
Author |
Message |
Markdem
Joined: 24 Jun 2005 Posts: 206
|
SD card problems |
Posted: Fri Feb 08, 2008 10:36 pm |
|
|
Hi All, I am trying to use a SD card for mass storage. I have spent all day reading the posts here, and the Sandisk datasheet, but still don't understand why this code is not working. I am using a PIC18F4550 running at 5v, so I also have the 3k3 - 1k8 resistor divider set up. SD card is been powered by 3.3v regulator. I have the Din and Dout lines pulled up with 100k resistors. When I run the code, I never get past the CMD0. I always get 0 from the card. If I take the card out, I get 255, so I think the hardware is OK.
My code is as follows
Code: |
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOBROWNOUT
#use delay(clock=48000000)
#include "lcd420.c"
#byte SSPBUF = 0xFC9
#byte SSPCON = 0xFC6
#byte SSPSTAT = 0xFC7
#bit BF = SSPSTAT.0
#bit SMP = SSPSTAT.7
#bit CKE = SSPSTAT.6
#bit CKP = SSPCON.4
#bit SSPM1 = SSPCON.1
#bit SSPEN = SSPCON.5
#define SD_CS PIN_A1
int SD_INIT()
{
int i;
setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_L_TO_H|SPI_CLK_DIV_16);
output_high(SD_CS);
for(i=0; i < 80; i++) //start and reset
{
spi_write(0xFF);
}
output_low(SD_CS);
delay_ms(5);
// spi_write(0xff);
spi_write(0x40);
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x95);
return spi_read(0xFF);
}
void main()
{
lcd_init();
printf(lcd_putc,"Ready");
while(SD_INIT() != 1)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"ERROR");
delay_ms(500);
}
while(1)
{
lcd_gotoxy(1,3);
printf(lcd_putc,"ok");
}
}
|
I have tried to setup the SSP with the following, but it does not help.
Code: |
// Init SPI
SMP=0;
CKE=0;
CKP=1;
SSPM1=1;
SSPEN=1;
|
I am guessing it has something to do with the way I setup the SPI ports. I would like to use USB in this project, so I am running the PIC at 48Mhz. I am not too sure how I am meant to use SPI_CLK_DIV. I have tried a range of values, like SPI_CLK_DIV_16, SPI_CLK_DIV_32 and SPI_CLK_DIV_64, but it does not seem to work.
Can anyone see any other problems?
Thanks, Mark |
|
|
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Sat Feb 09, 2008 5:40 am |
|
|
As far as i know... Select means output_low and deselect output_high. You should reverse that. One other thing, each time you wish to send something(cmd or data) you should call select first. In your code, CMD0 is ignored... |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Feb 09, 2008 8:05 am |
|
|
The largest problem in SD_INIT() is that after sending CMD0 you expect the card to send a response in the next few microseconds. According to the specs you should instead send 0xFF in a loop until you receive a value <> 0xFF or timeout.
Another smaller problem is your SPI clock frequency. It is specified that at startup the maximum clock frequency is maximum 400kHz. After startup (CMD0) the frequency can be increased to the SD-card's maximum. You are using a constant 48/16 = 3MHz. Depending on brand and age of your card this might work but there are no guarantees. Best is to slow down your clock during init and when successful go full speed.
Before you exit SD_INIT() add code to deselect the SD card.
Before sending a command to the SD card it is a nice addition to check the card to be ready, i.e. send 0xFF and check the response. Repeat until you receive a 0xFF or time out.
But then... why not use one of the MMC card libraries that are already present in the code section of this forum? Even CCS provides an MMC library in the Drivers directory of your compiler. After all, SD cards using SPI are backwards compatible to MMC. |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Sun Feb 10, 2008 12:02 am |
|
|
Hi ckielstra, Thank you very much for your help. I have tried to do what you suggested, but the problem still exists. I have now also slowed the pic down to 20MHz, so the spi should be working a 20/64= 312KHz, which is far below 400KHz.
When I run the code below, I get 255 as r1 when i dont have the SD card connected, then I get 0 when I connect it. Do you think that mayby I have some hardware problems? I have orded some PIC18LF's to check without having the resistor dividers, but the problem it, I need to run at 5v as i need to use USB and a LCD.
I am going to use the CCS drivers. I am only writing this code to debug why I can start the card.
Code: |
#include <18F4550.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,VREGEN,NOBROWNOUT
//#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOBROWNOUT
#use delay(clock=20000000)
#include "lcd420.c"
#define SD_CS PIN_A1
int data[514];
int r1;
void SD_INIT()
{
int i;
do
{
output_high(SD_CS);
delay_ms(20);
for(i=0; i < 20; i++)
{
spi_write(0xFF);
}
output_low(SD_CS);
delay_ms(20);
spi_write(0x40);
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x95);
do
{
r1 = spi_read(0xFF);
lcd_gotoxy(1,1);
printf(lcd_putc,"r1=%u",r1);
if (r1==1) break;
} while(r1 != 1);
} while(r1 != 1);
lcd_gotoxy(1,2);
printf(lcd_putc,"Reset OK");
output_high(SD_CS);
}
void main()
{
setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_L_TO_H|SPI_CLK_DIV_64);
lcd_init();
// printf(lcd_putc,"Ready");
SD_INIT();
while(1)
{
delay_ms(1);
}
}
|
One other thing I have found, is that some examples send 0x00 to reset the card instead of 0x40 as in the sandisk datasheet. I tried this, but it did not help. When I try this in proteous, It looks like the 0x00 command is invalid. The sd card always returns 255.
I have ran out of ideas for this one. I guess I will need to buy another brand of SD card, and see how I go. Is there anything else that you think I could try??
Thanks, Mark |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Feb 10, 2008 9:36 pm |
|
|
Quote: | When I run the code below, I get 255 as r1 when i dont have the SD card connected, then I get 0 when I connect it. Do you think that mayby I have some hardware problems? I have orded some PIC18LF's to check without having the resistor dividers, but the problem it, I need to run at 5v as i need to use USB and a LCD. | The SPI data input port SDA on pin B0 is of the Schmitt Trigger type. According to Table 28.3 of the PIC18F4550 datasheet these require a logic low of:
0.2Vdd = 0.2 * 5V = 1.0V
and a logic high of:
0.8Vdd = 0.8 * 5V = 4.0V
Running the MMC card at 3.3V you are not meeting the Voltage High level requirements...
You have the following options:
1) Use a PIC18LF processor at 3.3V
2) Add a level converter (either a cheap ic or a resistor / transistor solution).
3) Move away from the hardware SPI unit and use a software based SPI implementation on a TTL level input pin (triggers high level at 2.0V). Surprise, pin B0 when configured as digital input, is TTL level, so you can try this without modifying your current hardware.
Note: an example of a software SPI implementation for an MMC/SD card is mmc_spi.c in the CCS Drivers directory. |
|
|
andreluizeng
Joined: 04 Apr 2006 Posts: 117 Location: Brasil
|
|
Posted: Fri Mar 07, 2008 8:12 am |
|
|
had anybody used a 4gb sd card with fat32 ? _________________ Andre |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Mar 07, 2008 9:48 am |
|
|
I have tested the 4G cards with my own file system. You need to change the initialization sequence to use these cards. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
andreluizeng
Joined: 04 Apr 2006 Posts: 117 Location: Brasil
|
|
Posted: Fri Mar 07, 2008 12:20 pm |
|
|
can you tell me the sequence ?
thanks in advance. _________________ Andre |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Mar 07, 2008 12:46 pm |
|
|
Sorry but no, I sell my software. I did give you a hint where changes need to be made. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
andreluizeng
Joined: 04 Apr 2006 Posts: 117 Location: Brasil
|
|
Posted: Fri Mar 07, 2008 12:55 pm |
|
|
asmallri,
that hint i already knew, because im constantly debuggin my software. so... i dont think that you gonna lost sells telling me the sequence.
but, anyway.... thanks. _________________ Andre |
|
|
Franck26
Joined: 29 Dec 2007 Posts: 122 Location: Ireland
|
|
Posted: Sun Mar 09, 2008 3:57 pm |
|
|
Hi Markdem,
About the hardware, I have already noticed a lot of problem when you want to change the SPI voltage level by using resistors.
If you look the signal with an oscilloscope, you will see that there is a lot of distortion...
It's why it is always better to use a level translator on chip.
Good luck,
Franck. |
|
|
|
|
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
|