=============================================================================================================

Saturday, January 31, 2009

SD/SDHC Card Interfacing with ATmega8 /32 (FAT32 implementation)


Hi friends,
Here is my project on interfacing of SD Card (microSD). microSD cards are available very cheap nowadays, a great option for having a huge memory in any embedded system project. It is compatible with SPI bus, so the interfacing is easy. SD card adapters are also easily available in market, one can easily make a bread-board adapter by soldering few pins on it. Following figures show the SD card pin-out & the bread-board adapter design by soldering 7-pins of a breakout header on the microSD adapter (Click on images for larger view).












I had started this project with 1GB microSD card from SanDisk (later on tested with transcend cards also). The microcontroller is AVR ATmega8 or ATmega32 running at 8Mhz internal clock. MAX232 is used to interface the circuit with PC for monitoring the data. A 3.3v supply is used for powering the mega8, microSD and max232 (though the specified supply for max232 is 5v, it works comfortably at 3.3v).7 pins of the microSD are used here, shown in the figure of pin-out.

Schematic for ATmega8 is shown here (updated on 10 May 2010, SD series resistors are removed, as they were limiting the speed of SPI bus. 51k pullups are added on CMD/DAT lines. This gives better stability with different cards. Also, two 3.6v zeners are added to protect SD in case when the ISP programmer voltage levels are of 5v. these diodes are not required if your programmer has settings for 3.3v output)
(Note: VCC & GND pins of MAX232 are not shown in the schematic, but they must be connected in the actual hardware)
Following is the schematic for ATmega32, without RTC (updated on 10 May 2010):


Following is the schematic for ATmega32, with RTC (added on
17 May 2010; CS pin correction, PB4 instead of PB1, done in Mar 2014). Here two supply voltages are used, 3.3v for SD & 5v for remaining ICs.


The aim of this project was to learn interfacing of SD card and to understand the data transfer in raw format as well as in FAT32 format. I started with raw data transfer, sending some data to any block of the microSD, reading a block of it, reading and writing multiple blocks, erasing multiple blocks. All this in raw format. I used RS232 for viewing the data read by microcontroller from SD card. The uc sends the data to HyperTerminal. Similarly, to write data to card, the data was fed thru HyperTerminal, by typing some text.

Once raw data transfer achieved, I formatted the card with windowsXP (FAT32) and loaded it with some text files, directories and other files (all stored in root directory of the card). After that I wrote the FAT32 routines to read files, get file list (using HyperTerminal again), finding the total/free memory of card. All this data is sent to HyperTerminal by the uc.

Following is the HyperTerminal window showing different options:
Options 0 to 4 are low level functions dealing with raw data. If you use option 0, 1 or 3, you may have to reformat the card before using the FAT32 routines.
0: Erases selected number of blocks strating from selected block
1: Writes data to specified SD block address. Data to be entered in HyperTerminal using PC keyboard
2: Readss data of specified SD block address. Data is displayed on HyperTerminal window
3. Writes selected number of blocks strating from selected block
4. Reads selected number of blocks strating from selected block

Here, the multiple-block functions related to options 3 & 4 are disabled due to memory constraint as that time mega8 was used for testing and these functions are not required for FAT32 testing. While testing with mega32, options 3 & 4 can be enabled by removing a macro (#define FAT_TESTING_ONLY) defined in SD_routines.h.

Options 5 to 9 are related to FAT32 . Only short file names are supported right now, 8byte name+3bytes extension. If you store a long name file in SD, it will be displayed by these routines in short name format only.
For testing these options, format the card with FAT32 file system and store some directories and text files (because text files can be read & checked thru HyperTerminal).

5: Displays list of available directories and files with size (in the root directory of the card)
6: Reads a specified file and displays the file contents on HyperTerminal
7: Create/Append file with specified name, enter text from HyperTerminal
8: Deletes any existing file with specified name
9: Displays total & free memory of the card (using FSinfo sector of the SD card)

Following figures show the HyperTerminal window when options 5 & 9 are selected:
(These figures show menu from Ver2.3 or earlier. Menu style is changed from Ver_2.4 onwards, which is shown in the update history)

Note: HyperTerminal is used here at 19200 baudrate, No parity, Flow Control 'none'.

This project needs very few components and can be done easily at home. Try it out!


Download the source code files from here
:
Download here the zipped source code files modified for mega32, written in winAVR-AVRStudio.

Version 2.4.1 (RTC added for Date/Time entries) 17 May 2010/24 Apr 2011
Version 2.3 (SDHC support added) 09 May 2010
Version 2.2 (No SDHC support) 13 Sep 2009

Download EAGLE schematic file of Ver 2.4

Download/view source code files V2.1 (for ATmega8):
Following files are compiled using winAVR inside AVRStudio. This Version does not support SDHC cards. Also, append file feature is not available.
1. SD_main.c
2. SD_routines.c & SD_routines.h
3. FAT32.c & FAT32.h (Ver 2.1, last updated-13 Sep 09)
4. SPI_routines.c & SPI_routines.h
5. UART_routines.c & UART_routines.h
6. Makefile
7. HEX file (Ver 2.1, last updated-13 Sep 09)

Please put up a comment or mail me if you find a bug in the code. The updates are because of valuable suggestions & comments from the users of this code. Thanks a lot!!


Buy from Farnell (Element14): ATmega32 (India), ATmega32 (USA)


Related posts:
You can visit my post of microSD ATmega32 Data-Logger, which uses modified FAT32 library for automatically creating files without using hyper terminal.
If you want to test FAT32 functions or learn more without making the microcontroller hardware, you can visit my post here: microSD-FAT32 using Visual C++)

Update History-----------------------------------------------------------------------------
Version 2.4:

- Real Time Clock circuit support is added for time & date entries in the files. Now the current date of file creation and file update will be entered in the FAT table (can be viewed by checking file 'properties' using a PC)
(The RTC will also be useful in data-logging with time-stamp)
- Three more options added in the Hyper Terminal menu for displaying or updating RTC date & time. New menu is shown in the above figure.

Ver 2.4.1:
- Same as 2.4, with a bug fix for RTC: 'twi_init' function added to define I2C clock freq. 100K@ 16MHz (50k@8MHz). This was taking default values earlier, which was as high as 500K@8MHz, not desirable

(Note: Version 2.2, 2.3 & 2.4 are tested on ATmega32, but they can be adopted to any controller having RAM >= 1KB and Flash >= 16KB)
Current memory usage (Ver_2.4): Flash: 12908 Bytes; RAM: 700 Bytes (appx.);

Version 2.3:
- Support for SDHC cards added (tested with SanDisk & Transcend microSD and microSDHC cards). The initialization sequence and command formats are modified.
- A bug which was causing the program flow to go into infinite loop if the character number 512 in a sector was a CR (Carriage Return, '\r'), in the writeFile function. Thanks to David & Piotr M. who pointed it out in the comments.
- Code is also tested successfully at 16MHz clock (8MHz SPI clock) with for SD/SDHC cards.

Follwing are the Hyper Terminal windows showing card detection (One window shows baudrate as 38400, that was while testing for higher clock speeds, current code still uses 19200 baud and 8MHz internal clock of Mega32).








Version 2.2:
- Append file feature added. 'createFile' function replaced with writeFile, which looks for the filename first, if the given file name doesn't exist then it creates new file and writes data, but if the file already exists, then it opens it and appends the entered data.
- A bug removed which was giving error related to use of 'LONG'
- The FAT32.c & .h files are updated on 13 Sep 09 to remove a bug which was limiting file size to 32MB (Thanks to Kun-Szabo Marton who pointed it out)

Data transfer rate: 1 raw data block (512 bytes) takes 4.15ms for reading or writing (123.37 KBytes/s) at current 4 MHz SPI clock rate. If you have flash more than 8k, you can declare the SPI_receive() and SPI_transmit() functions as 'inline' functions. This will increase the transfer rate to 140 KBytes/s. These transfer rates can be further increased by using a 16MHz crystal (8 MHz SPI clock). FAT32 file reading is done at 78 to 91 KBytes/sec.

Version 2.1:
- A bug removed which stopped creating new files after 32*8 files in the root directory
- The root directory was unnecessarily getting expanded by one cluster whenever a file was created. Fixed in the new version
- Also, the fixed cluster size of 8 sectors is removed, this version will support other cluster sizes as well

Version 2.0:
- Support added for SD cards having first sector as MBR rather than the boot sector
- createFile and deleteFile functions added
- A bug fixed in reading files stord at far locations in memory also correction made to accept 8+3 char file name (by mistake, it was taking 7+3 earlier)
- FSinfo sector used for storing total free cluster count &
next free cluster number for faster file access
- Instant freeMemory display (earlier it was taking more than 30secs) using FSinfo sector. FSinfo sector is updated now whenever a file is created or deleted
- File memory size display in decimal, like windows (earlier it was in hex)
- Raw SD functions multiple block read and write, which are not required for FAT32, are disabled using FAT32_TESTING_ONLY macro for getting extra space required by createFile & deleteFile changes (you can activate it if you have more than 8k flash) Right now flash is 99.9% full
- Clock speed raised from 1Mhz to 8 MHz, new SPI speed (after SD initialization): 4MHz instead of 500K & baudrate: 19200 (for HyperTerminal) instead of 4800
-------------------------------------------------------------------------------

References:
1. Microsoft's FAT32 specification document
2. SanDisk SD mnual v1.9
3. SD-Simplified Physical Layer Spec. Ver 4.10
4. F. Foust's Application Note on SD
5. FAT32 Structure info, includes MBR details
6. Simple FAT32 Structure explanation
 
7. Chan's FAT library
8. SD Association's Website for further info

Regards,
ccd@dharmanitech.com

670 comments:

«Oldest   ‹Older   201 – 400 of 670   Newer›   Newest»
Abednorton said...

Hi...

your code is very good code.
how can i to append a file by your code?

CC Dharmani said...

To Aniket:
you can connect many peripherals on the same SPI bus, all you have to manage is the SS pin of each slave device, you need to use separate port pins of the microcontroller to control the SS pin of each slave (ofcourse, there are other configurations like daisy chain, but better you keep away from there here).
Make sure that only one slave is activated, either the LCD or the SD card, never both, then things will be fine!!

CC Dharmani said...

To Abednorton:
For appending a file you need to create a function which should first call the readFile function, get the start cluster location and file size, then go thru the cluter chain till you reach the end-of-cluster-chain (just the way the readFile does it). Using the fileSize, you can know how many bytes are there in the last cluster, which will give you the sector location also, now, switch to writing mode (the way it's done in the createFile function).
Keep writing till you need to append; then call the findFile function, get the directory location and the FAT sector address in which the file info is stored. Read the sector, modify only the fileSize and write the sector back. Done!!

(I'm shortly putting a modified library, which will make the task much easier, with inbuilt append function. Wait till this weekend!!)

Anonymous said...

No, I only have connected the 5V and ground from my USB-Programmer to the controller. The voltage gets regulated down to 3.3V. I continuously get "SD init failed!" with no card inserted. When I plug the SD card in, it is detected and everything works fine.

I'm going to comment out the functions step by step and see where the error occurs.

I'm working on a Mega8.

Anonymous said...

Hi,

I got the resetting issue fixed. The problem was some unclean code of mine.

Your code rocks! Thanks very much!

Anonymous said...

There's another problem resulting in a controller reset when plugging in the SD card while the controller is running.

When hot-plugging in the SD card, it pulls so much current, that the voltage of the whole circuit drops for the fraction of a second. In this moment, the controller turns off and gets back on again.

This is the reset I mentioned earlier. I'm powering the device from USB. I haven't tried a seperate DC supply yet.

CC Dharmani said...

I think using an electrolyte capacitor of 10 to 47uF between the VCC and GND pins of microcontroller should solve the issue.

Anonymous said...

Hi,

thanks for the help. I put it a 47 uF. That did the trick it seems. I think running on a seperate supply will be better though.

Nirmal said...

hey Dharmani,
gr8 workz congratz
m in final year....
n me need to submit my finakl yr project in a couple of months ... m totaly blank can u telme any nice innovative projects to do??? my major is ECE.... nice bt nt tooo complicated
plz help ASAp
any others too cn help me out

jus mail in @ 89nirmal@gmail.com

Awaitin ur ideas ppl!!
thx in advance

Anonymous said...

hi well done good job . i interfaced with sd card .after writting the data i am trying to read the data through pc its giving error do u want format the drive .why its giving . we can't read the data through pc what ever the data entered through hyperteminal .

CC Dharmani said...

Hi,
if you have entered data in the Sd using the writeSingleBlock or writeMultipleBlock functions, the PC won't be able to read the data, as the data is in raw format. PC can read the data if it's in the FAT format.
So, use the createFile/ writeFile options which create a file in FAT32 format. Then you'll be able to read it using PC.

maryam said...

Hi Dharma,i have many question about SD!!! i want to use SD for samplery ,samplery's rate is 5kHz.in fact i want to write in SD evry 0.2mSec.i set SD in single block and the size of a block is 1byte ,i use crystall 12MHz and ATMEGA32 in my project.i couldnot sample correctly because writing in SD was very slow . may you help me and say to me what i shoud do ?is SD slow and unsuitable for my project?please guide me.
note:my English isnot good ,Excuse me

binaural said...

Hi, just download sources and try to compile for ATMega8. And I get error: section .text will not fit in region text. Do you know something about it? I try also compile for AtMega16 and result hex has ~23k??? Thanks

CC Dharmani said...

Hi,
You might have downloaded the code which was meant for mega32, where the code size is more than the capacity of the mega8, that's why that error is coming.

Use mega16 for that code. Don't worry about the size of the hex file, it doesn't mean the size of the code, as the hex file is shown in windows as a file of ascii characters, but when you burn the code, only the hex data goes into the controller. If you want to know the real size of the code, just check the messages displayed by the compiler after you compile the code.
You can also know the size of the hex code when you burn the code using an AVR programmer into the controller. The programming software will show the size of the code which it has just dumped into the controller

CC Dharmani said...

To Maryam:
Hi, writing in SD at 5 Kbytes/sec should not be a problem at all. SD can certainly handle it. The speed of SD depends mainly on what the SPI CLK speed is.
I've mentioned the raw data transfer rate at 4KHz SPI clock, it is around 123 KBytes /sec. This can be further increased by increase in the clock speed.
You can check your clock setting. Also, rather than defining 1byte block, you can store bytes temporarily into a 512 byte buffer and when buffer is full, you can write it into the SD (with block length of 512 bytes), this will give faster results compared to small block lengths.

Anonymous said...

Hi,

can you help me to transfer data from one complete device ( Atmega32 + SD Card ) to another same device.....?

Baba

Trần Trung Hiếu said...

Dear CC Dharmani,

I tried to format my 1G SD Card with FAT32 file siystem but Hyperterminal still showing "FAT32 Option Disabled". Can you suggest me another way to solve this problem?

Thanks in advance.
PS: I use your hex file, hardware.

Mr.Grand said...

I am using SD card interface for data logger project But I am new to this so I don't know how to pump continous data from ADC to SD card.
using FAT32.

Thanks in advance.

Trần Trung Hiếu said...

I did it. Thank you very much. I'm very joyful...thank for your sharing. Have a nice day.

Anonymous said...

Hi,

I can't create files bigger than 31 MB. I was able to locate the error in the part where the FAT is updated.
But I am not able to find a fix for it.
I'm using version 2.1 on Mega8. When creating 1MB files in a loop, everything's ok until file 32.

When I dump buffer[] after
> for(sector = 0; sector < sectorPerCluster; sector++) {
> SD_readSingleBlock (firstSector + sector);

I see the contents of the file instead of the FAT structure. So something has to be wrong in adressing the sectors to be read. When dumping a correct process, is see a list of files in the root directory.

Any hints?
Do you have the same problem?

Anonymous said...

Same problem with Mega32, just tried the same code. Only takes 31MB.

Anonymous said...

As I can see, there's no detection for FAT16. You might want to add:

// check if it's FAT16
if (bpb->FATsize_F16 != 0x0000) {
return 2;
}
to your getBootSectorData() function after the

bpb = (struct BS_Structure *)buffer;

statement.

CC Dharmani said...

Thanks for the suggestion!
Though I'm mentioning at many places that the file system is FAT32, and format the card with FAT32 before trying out the FAT32 options, it would be better to check in the program for FAT16, as someone may format the card with FAT16 by mistake!
I'll include it in the next version of the code.

Ashoka said...

It is not working with Atmega8

CC Dharmani said...

Hi Ashoka, put up some more details, you'll get a better help. What exactly is the problem you faced? How did you try it?

Ashoka said...

Dear Sir,
I have tried the Hex File. I am having a dongle connected to LPT1 to ISP pins of Atmega8L. I am using Ponyprog Program to download Hex File..

If i give a simple program which initializes UART port and send a string then I am getting it on Hyperterminal.. That means my hardware should be OK.

When I dwonload your hex file I dont get anything on Hyperterminal...

Please Help.

Ashoka

CC Dharmani said...

Hi, I've sent you a mail, check it out!

Linus Casassa said...

Has anyone used this code on xmega?

Ashoka said...

Dear Sir,

I am using the program sent by you for Atmega8.
I am using Atmega8L with the Circuit as given by you.

When I download the HEX file given by you I do not get anything on Pin 3 TXD of Atmega8. Also I am not getting High at pin 4 (PD2), which means

that the Program is not working. I am using the Atmega8 at 3.3 Volts. The 3.3V is regulated.

I am using Avr Studio 4 and WinAVr. I open the project in AVR Studio and compile it. It is getting compiled properly and the Comiplation result

shows : Program 8180 Bytes ( 99.9% Full ) and Data 563 Bytes ( 55.0% Full ). I download the Hex file and still the Program does not output

anything on TXD and PD2 ( i.e Pin4).

In order to test the Hardware, now I make changes in the program : I give while(1); after 14th line the Main Program. ( to stop the Program

just after sending high to PD2 and sending strings on serial port ). I compile the program. It is getting compiled properly and the Comiplation

result shows : Program 6542 Bytes ( 79.9% Full ) and Data 563 Bytes ( 55.0% Full ). I download the new Hex file and still the Program does not

output anything on TXD and PD2 ( i.e Pin4).

Now as I am not using any fat32 subroutines I remove the FAT32.c from the project and Compile the program. It is getting compiled properly and

the Comiplation result shows : Program 1046 Bytes ( 12.8% Full ) and Data 543 Bytes ( 53.0% Full ). I download the Hex file and now the Program

works.. I get the High on Pin4 ( PD2) and I also receive the strings on the COM port of PC.

Is there any problem in the Program memeory.. I am using Atmega8L which was bought sometime back ( In Apr2008) Is it to do with the Chip..

During testing Sometimes the full Program has worked once-twice.. What could be the problem.. Or Shall I use Atmega16 only..

Also One more observation.. I am using Max232 and Atmega8 on 3.3v Power Supply. The output of the MAX232 is +-6V (RS232 requires +_12V).Is it

not better to use 5v for MAX232 so that we get +-12v pulses?

Anonymous said...

Hello All, Peter from this side :)

At the begining I say the project it`s GREAT , hats off CC Dharmani.

But like most people here I`ve got problem :)

I tried it on Atmega16,adapt your program to Atmega 128. SD card ( Medion 256 MB) working, I can read files, get card status, file list but the problem is with writinig. When I try write a file or single block - raw data, I`m typing text, end with "~" , get the message File Created!/Write successful! , but leter I check file list, connect SD card to PC by SD reader and nothing was created :( Of course SD card is fat32 formated, unlocked .

Any idea ?
killcio@o2.pl

Anonymous said...

@Ashoka:

I sometimes have the same problem running MAX232s at 3.3V. What helps many times is to start the circuit with 5V (no SD card inserted!), and then, after few seconds switch to 3.3V. Most of the time, this trick works.

CC Dharmani said...

If 3.3v gives problem, you can use 3.6v (of course, if you have adjustable voltage regulator, I use LM317). At 3.6v MAX232 won't give any problem and microSD also will be safe
If you need 5v for other chips, you can use voltage divider resistors for converting 5v into 3.3v for the SD alone.

To Peter:
Have you tried the latest version (2.2) code?

Anonymous said...

Does anyone else have the problem with a maximum file size of 31 MB?

When trying to write a formatted SD card, I can only write files up to 31 MB. After that, the FAT get's destroyed somehow.

Anonymous said...

Yes, I`m using last version (2.2) .
During compiation I get warnings :

FAT32.c: In function 'writeFile':
FAT32.c:374: warning: 'firstClusterLow' may be used uninitialized in this function
FAT32.c:374: warning: 'firstClusterHigh' may be used uninitialized in this function
FAT32.c:373: warning: 'sector' may be used uninitialized in this function

Peter

Ashoka said...

The Program you have sent for Atmega8 is not working... I have posted details..

Please tell me where am I going wrong..

CC Dharmani said...

Hi Ashoka,
from the observations you sent, it seems like the problem is in the hardware, as you are sometimes getting the messages and other times not!
Best way to solve is start again from looking at the schematic and verify every connection. Check the SD card adapter, look at the supply, verify that you have set proper clock frequency. look for loose connections in the RS232 line (cable and connectors), check the settings of the hyper terminal options.
In the schematic, I've used an LED also, which will glow as soon as the program starts. It is just to indicate whether the controller is working at the first place.

Carry out these checks!

CC Dharmani said...

Hi Peter,

those warnings are not the problem, theyt'll be there. If you want to remove them, simply assign those three variables value 0 during the initialization, but program functioning will have no effect of that.

May be you can try with another card?

Ashoka said...

I don't think the problem is in H/w. If I restrict the Program to the String Sending and Outputting High for LED then It works...

The moment I compile full program then it does not work..
I have used Atmega16 and the System works.. I can even read write blocks etc..

Have you really tried it on ATMEGA8.. I am sure there is nothing wrong in my H/w.

Ashoka

selvam said...

Hi Dharma,
I have tried SD card interface with the help of your article

For this I'm using

ATMega32 with 16MHz Crystal
Serial Baud rate: 9600
SD Card size: 1GB
source code version 2.2

After storing one MP3 file with the size of 8,075KB,
I'm trying to find the memory details (Option 9), the program implies
Total Memory: 2534,195,200 bytes and hanged here.
(Actual value: 990,576,640 bytes got from card reader)

For debugging purpose I have found the below values through serial:
Total Cluster: 125,721,651 bytes
Sector Per Cluster: 32
Unused Sector: 133
Reserved Sector: 1
Root Cluster: 1095,639,119

Kindly provide me the below details
The program get struggled in the while loop of "memoryStatistics() function.
freecluster values are also not updtaed (always shows 0 through hyper terminal I print the value)
What may be the reason for this issue?

Shall I get the steps followed in memoryStatistics() function.

These info is very helpful to me.

if any one faced same issue kindly help me on this.
my mail id: mr_selvam2020@yahoo.co.in

sahil said...

hi v r 3rd year engg students from mumbai. what is the significance of the ISP connector in the circuit?
what is the function of reset pin in it?? please mail us ur contact number at sahilramtri@gmail.com . we need ur help in getting few doubts cleared. thank you

CC Dharmani said...

This is regarding the bug which was affecting FAT32 when a file was created with size more than 32MB. One of the reader, Kun-Szabo Marton, pointed out the mistake in getFirstSector function's argument declaration (unsigned long instead of unsigned int). Thanks to him!
I've uploaded the modified code (small modification is Ver2.1 & 2.2 both)

Thanks!

Feilex said...

Using your most updated code...
Either I am screwing something up, or there is a bug.

I can not seem to create files, I get a "No free sector error".
When I query on memoryStatistics() the MCU hangs.

Chris

Anonymous said...

This is regarding the 32 MB bug:

Damn, I was so close :D.

Thank you very much!

Jonathan said...

I am having trouble getting just raw data written and read back. The CLK line seems fine as well as the MOSI. However the signal to MISO is very small. Mostly the SD_Init fails so I run it in loop till it works. Usually takes ages and I need to fiddle around with the wiring. Is wiring important? All mine are less than 10cm on the breadboard.

Jonathan said...

One more thing. I am using a ordinary sd card, not a microsd card with a sd card adapter. I have seen a few posts here of using them. I assumed they were the same.

Jonathan said...

I have fixed up the wiring but SD_Init() working is a bit of hit and miss. At the moment I run it in a loop until it returns 0. When it does writing sometimes works and reading almost never works and never with the proper data (only using writing and reading raw data at the moment).

What could be the problem? Do I need a sandisk microsd + adapter?

CC Dharmani said...

Hi Jonathan,
try using pull-up resistors (any value from 10k to 100k) on the data & clock lines as well as on the all unused pins of the SD card.

Anonymous said...

Hi CC
I used SDCard 1G connect to ATMEGA32.After boot system I got "FAT32 not found" but I can write and read from block index(RAW Data).
How to solve for creat/read/write file.?
Sorry I little english
Thank you for advantage

HS8JCV

Anonymous said...

@ HS8JCV

Did you use a pull-up resistor on the DO wire?
Blockread/write works because it's independent of FAT32. Reformat the card with FAT32 before you use it again.

Anonymous said...

hi
very thnks for this. but it has a little bug.
when i try to append a empty file, program loops in here :
while(1)
{
nextCluster = getSetNextCluster (cluster, GET, 0);
if(nextCluster == EOF) break;
cluster = nextCluster;
clusterCount++;
}

Anonymous said...

to Ashoka

can u mail me the schematic diagram using atmega16? i try it with my one adjustment n dosn't work..

affiz85@yahoo.com

Anonymous said...

can this project work as a sd card reader with rs232 interfacing and fat16 file system

CC Dharmani said...

Hi,
this code doesn't support FAT16. And it can not work as SD card reader even for FAT32 as it displays the file list or file contents on the Hyper Terminal. For SD card reader, you need to modify the code so that it can receive or transmit files to PC, rather than displaying it on the terminal.
You need to implement the file transfer protocol (like 'Xmodem') supported by the hyper terminal or other terminal programs for file transfer thru RS232.

Anonymous said...

thanks sir for ur quick reply!

i want to ask you how could i create a sd card reader with fat16 format
and the card is interfaced to PC by rs232.Is it possible?

what else i would require to make such project.(hardware and header files etc)

CC Dharmani said...

Hi, for making FAT16 SD card reader via RS232, you need to change the software routines (specially the FAT routines).
First, You need to modify the FAT32 routines so that they work with FAT16. If you read Microsoft's fatgen document given in the reference at the end of the post, it'll help you in understanding the changes required.
Second, you'll have to add the file transfer routines, which use a standard protocol supported by PC (like Xmodem, as I mentioned earlier). Google search will give you a lot of information on such protocols.
Once you implement these two, rest of the things are like cosmetics around it.

For hardware, you can use the schematic given in this post itself, no changes required.

BillH said...

Blogger BillH said...

This works Fantastic up to 2gb sd or (class 2 )!!

I am working on long term datalogger needed for days or weeks at time,so I need 8gb sd (class 4) or up to 32gb sd (class 6).
Is there someone that would help me?
Go to (class4) or (class6) sd.

October 20, 2009 10:15 AM

CC Dharmani said...

Hi BillH,
visit this post around this weekend, probably you'll find an update in this code which will support SDHC cards (tested on 8 GB, but I think it would also support higher capacity cards which come under SDHC category). It's pending for quite a long time, just little short of time to update the files.

Hellraiser said...

Hey brother ! Great work ! Thank you !
I didn't know some among us were doing such good work ;-)

I tried your code....i modified it a small bit to transmit characters over uart at various stages.....
I can initialize card,send it into idle state BUT after that,if i give it *any* command (like CMD17 for writing) i only read back "0xff". The card doesn't read or write.
I've tried this with several cards
(SD as well as MMC)

I'm using mega16 @ 5v , potential divider resistors at MOSI,SS,SCK

Any suggestions ?
God bless you !

Anonymous said...

fine work sir. this helped me a lot in solving the memory problems in one of my logger circuits.
but i just have a problem whether it can be simulated using ISIS. especially the raw data erasing function.

Hellraiser said...

Hey ! I solved the problem
turns out,when i send the read command,the card returns "0xff" -- not a valid response.
But still sends all the data !
Hope this helps someone !
Again.great work,brother !

Armen said...

Hi All,

My name is Armen Shatakhyan 25 years old. I am new to microcontroller programming. It's a very good and powerfull project. I want to ask you one question. As i see you can create file (text file) in SD card ang give him name. Can you write text, symbols, digits etc. to this cretad file so that i can read and analyse it by my created WinApplication program (When I insert SD card to PC)?. If yes, what is the name of this method in source code?

Thanks
Armen

Arf said...

Hi, great job, I am impressed with your work, and thanks for sharing it.

I have one issue, I can create and view files through Hyperterm, but I can't see them when plugged into a card reader. If I add a file via card reader, I can see it in wondows, but not hyperterminal. I am using a 64Meg MMC card, so I suspect initialisation problems may be causing the trouble. Is it possible for you to email me the mmc initialisation code? I see in older comments that you have some code for mmc.

arfdog@blueyonder.co.uk

Thanks again for sharing this!

Anonymous said...

sir,
i am very happy because of ur reply and u helped me a lot.

can u tell me that in fat16 file system for MMC or SD can have other other than root folder.

i want to kept data of diff formats in diff. folders.

what i should do or study to make a image viewer in which file will be accessed from SD memory with a condition the images may be of different resolutions.

i think u r from India.

are these IC's available in india ?

atmega128 and
vs1011 -> an mp3 decoder.

thanks

sasha said...

sir i need a header file named atmega32.h and lcd.h ...can u guide us about the codes and recommend any site where we can find them??

Jonathan said...

Is there any reason why the write and read raw format only goes from 0-9999 blocks? This equates to 4MB max for the RAW write?

Jonathan said...

Also when I write some data then reset the power then try to read it again it comes back with read failed. Reading directly after writing work.

CC Dharmani said...

To Armen:
Yes, you can write any kind of data you want in the SD card. I've given here code for writing text files as they are easier to test with the hyper terminal. If you need to store other kind of data, just dump the hex data of the file into the SD card using writeFile function. You may need to change that function a little so that it accepts data from wherever you are entering (that function accepts data from hyper terminal in this code)

To Anonymous:
You can create folders in the SD card. Please go thru the references given at the end of the post which will give you idea of how the folders are stored in the FAT format.
The ICs you mentioned are available in India. If you are staying near Mumbai or Chennai, you can try there in electronic markets. The ATmega128 is quite common to find. For VS1011, you may have to try a litle more search.

To Jonathan:
There is no reason for keeping the block length upto 9999 in raw format, I just kept it that way as I was using the raw functions for testing the card, and if I can access few blocks successfully, then the connections are verified.
You can define any block number, upto maximum capacity of the card.
Commenting on the reading problem is little difficult, as it requires to know whether the supply level, the signal levels, the clock speed are as specified. You may also try adding pull-up resistors on signal lines.

shanmu said...

Hi Dharmani
I am using your source code for buiding wav player with Atmega32..
But after all I can only intialize the card. In the Hyperterminal I am getting "FAT32 not found". I can write, But that too not on a regular patch. Now and then I can write but could not read the card contents, It is coming with some Garbage values or else read failed.
I have mailed you the Screen shots of my Hyperterminal window. looking for your valuable suggestions. I Dont get any pulse or anything in MISO Pin. I am using 5V supply for the uC and Using Voltage Divider to MOSI and CS Pins. I am using Zener Regulated 3.6V Supply for SD card. Also Whenever the card try to write the there is surge in Voltage at Vcc of SD card.

Anonymous said...

@shanmu:

Voltage divider is not a very good idea. Try running at 3V3 or get a level shifter. Put a 220uF cap between VCC and GND next to the Atmega32 and a 100nF cap directly in front of the SD card connector.

CC Dharmani said...

Hi Shanmu,
try using 50k (appx.) pull-up resistors on the data and clock lines of the SD card. This may solve the surge problem and kep the line stable so that the data doesn't get corrupted. It has solved the same problem in some cases. (If it doesn't work, try adding pull-ups on the unused pins of the SD as well).
Please do put up the results here once you are done.

CC Dharmani said...

Well, you got another suggestion by the time I was writing!! :)

CC Dharmani said...

And ya, one more try you can give by disconnecting the programmer while you are running the code, just to eliminate any effect from the programmer.

shanmu said...

thank you Guys
I will make the changes as you suggested, check and will reply you back soon.

shanmu said...

Hi dharmani

I have mailed you the results.
Looking for you valuable suggestions.
I used LM317 and adjusted the voltage to be around 3.6V and its working great.

Thanks and regards
Shanmu

basje said...

First of all, it's a nice project! But now I have a problem with initializing the card.

It gets a time-out in this part of the initialization. Any ideas?

do
{
response = SD_sendCommand(SEND_OP_COND, 0); //activate card's initialization process
response = SD_sendCommand(SEND_OP_COND, 0); //same command sent again for compatibility with some cards
retry++;
if(retry>0xfe) return 1; //time out
}while(response);

Steve said...

Hi,
First of all, thanks for the posting.
I am trying to do the same thing you're doing here except with the ATMega168 chip. When I looked at your code, my biggest problem is the 'UART_routines.c' due to many registers names/address and interrupts are different. Could you point me to the source where I can modify this file for the ATMega168?

Many thanks in advance.
Steve

Anonymous said...

Great project and the questions and answers are instructive. A reminder that many of the answers are available to you by reading Chan's website referenced at the beginning of this project's blog.
The following page is very useful
http://elm-chan.org/docs/mmc/mmc_e.html
Here you will see comments on Write speeds. Power drops on inserting the cards. Words on Pull-up and Pull-down resistors on the SD lines and much more.

Have Fun

Anonymous said...

Init errors mainly happen because of wrong circuitry. See the post above me. Check out ELM.

@Steve:
You have to remove the zeros from the registers. UDRE0 becomes UDRE for example. You'll find the rest when you compare the iom8.h with iom168.h.

Black Jack said...

awesome man..! I'm thinking of project to make pendrive to pendrive transfer possible..! this project will help my clear most of d doubts..! just in sem 5.. soo pls guide me whnvr I get stuck..
thanx a lot..! keep rocking.!

cr33pn said...

There are parts of your code that I do not understand how they work in FAT32.c

The SD_writeSingleBlock writes the 512 bytes contained in Buffer to the SD card, however (for example) in getSetFreeCluster you update FS->freeClusterCount = FSEntry;
and then without transfering this information to Buffer you write it to the SD card? How do you get the data from the FS structure to the buffer?

Patrick said...

Hello Sir Dharmani,

First of all: great project and many thanks for sharing this with all of us! I am running the code for several weeks now (changing parts in my spare time). My board will be used for data logging lots of engine information of my Hayabusa Turbo powered street-legal Mini (car) for further tuning.

The code runs on a MEGA32 @16mhz with SPI clock @8mhz in combination with TWI for displaying ADC data on an OLED display and UART @57600bps. I got it operational for data logging in FAT32 mode for a couple days now by modifying the writeFile function slightly for writing an unsigned char array with a length of 512 positions. By doing this, the moment to access the SD card is limited. Data that must be stored are 10 x 10bit ADC values, one 8bit counter (for RPM) and one 16bit for fuel injector timing.

For writing/appending one file it will be quick when the file is small in size, but when the file is getting bigger (in my example already at 500kb+ in size) the time to store data is increasing and limiting the interval data being logged and stored by the MEGA32 dramatically.

I tried many things, but it looks almost impossible to keep constant write speed with appending one file during each session/run. I have tested several SD cards in sizes of 512mb, 1gb and 2gb (all with 512byte blocksize). At this moment I lost focus on what can cause this increase of time for appending data to an existing file.

Many thanks,
Patrick (the Netherlands)

HayaMini said...

Ps: the previous post was added before I logged in. Maybe this is easier for contact if more info is needed.

Sruthi said...

Hello Sir
I am a Final year Student in Engineering. For my final year project We have planned to Do a Autonomous Robot Which will Fetch The route to navigate from the stored data in the SD card. that is its Direction will be uploaded from a remote place by transmitting the values in wireless commmn. We are using your code for SD card interfacing. The problem is we cannot initialize the Card. I have read this thread and this has been the problem for many. We are using Atmega16 uC and 5V power supply. We used Potential Divider circuit for SD card. Any suggestions will be appreciated.
Thank you for posting such a nice and inspiring work.

HayaMini said...

Just my 2 cents...

@Scruthi,

Are you sure that there is between 3.3 and 3.6v on the SD card? This makes a huge difference and using the right caps directly in front of the 3.3v power for the SD card?

What if you just read CLUSTER 0 from the card and write it to UART? And what is displayed as output? INIT failed?

I have altered the detection of the SD card because during startup when the 3.3v is not stable yet. Maybe this can be of use:


void detectSDCard(unsigned char *FAT32_active){
unsigned char error;
do{
SD_init();
_delay_ms(1); //some delay
FAT32_active[0] = 1;
error = getBootSectorData (); //read boot sector and keep necessary data in global variables
if(error){
transmitString_F (PSTR("FAT32 not found!")); //FAT32 incompatible drive
TX_NEWLINE;
FAT32_active[0] = 0;
}
}while (FAT32_active[0] == 0);
transmitString_F(PSTR("Found FAT32!"));
TX_NEWLINE;
// return FAT32_active;
}



You can call this function with:
detectSDCard( &FAT32_active );


This helped me a little bit when first powering the complete system. Without this function it does work too, but after a couple resets of the MEGA32. During this detection I am able to insert the SD card and start using it.



@Dharmani:
Maybe it is an idea to add my detectSDCard function to your next release.
The huge delay for appending a file, is generated inside function writeFile with the following code:

while(1){
nextCluster = getSetNextCluster (cluster, GET, 0);
if(nextCluster == EOF)
break;
cluster = nextCluster;
clusterCount++;
}

I just added a LED_ON and LED_OFF around this loop and this is exactly the code that is slowing the append action down then file is getting larger then 500kb.

Sruthi said...

Hello Hayamini
I am Now getting the o/p, Once again removed the connections and assembled. Its working but the voltage is not same in al the pins. Is this a right approach using voltage dividers. Does any simple logic converter needed for real time use.
Thank you for your prompt response

HayaMini said...

@Sruthi:

Currently I have the following components for its voltage divider, MEGA32 pinout to resistor 1.8k, from resistor 1.8k to SD-pin and to resistor 3k3 and from resistor 3k3 to ground.

MEGA32::SCK (PB7) -> resistor 1k8 -> CLK (PIN 5) & resistor 3.3k followed by ground.
MEGA32::SS (PB4) -> resistor 1k8 -> /CS (PIN 1) & resistor 3.3k followed by ground.
MEGA32::MOSI (PB5) -> resistor 1k8 -> DATA IN (PIN 2) & resistor 3.3k followed by ground.

MEGA32::MISO (PB6) directly connected to 'DATA OUT'(pin 7).

For voltage supply for the SD card I am using a LD1086V33 connected to SD pin 4 and grounds on SD pin 4 and 6 connected to ground.

I am not using a logic converter at all.

Sruthi said...

Hello Hayamini

Thank you for your Suggestion. Do I need any pul ups on SD card- CS, and MOSI Because in SD card manual they had suggested to use 50K pull up.
I used pull ups for other Data pins.

HayaMini said...

Hi Sruthi,

I do not think pullups are needed in this case. The Atmel is supplying +5v on its output pins which is divided with the resistors to a voltage rond 3.4v (between 3.3v and 3.6v is allowed). The input is just 3.3v and with this would be more then enough to detect a logic 1 on the line.

So in short: there is already a 1.8k resistor in the line between ATMEL::SCK to SD::CLK and a resistor 3.3k between SD:CLK and GND. Same situation for ATMEL::SS with SD::CS and ATMEL::MOSI with SD::DATA_IN.

Maybe I am able to post a layout made in eagle tonight if that will help you.

HayaMini said...

Hello Sruthi,

Displaying an image is not allower, but link to the image is http://i45.tinypic.com/246q683.jpg

Sruthi said...

thank you HayaMini
Your suggestions were more helpful.
I am able to initialize and Handle FAT32 in SD.

Khanh said...

This is absolutety great project! But i have some problems with the atmega32 when i connect all component as the schemetic of Atmega8 and use the Protues to simulate it! it don't work! Can u send me a completed schematic 4 ATMEGA32? thank u much!
My mailbox: anhduongcuocdoi111@yahoo.com
Thanks again!

Arek said...

Thank you very much for this library - it helped me a lot in my project, good job !

CC Dharmani said...

Sorry guys, as I'm on a long vacation, I'm not able to check the posts regularly.

to HayaMini:
Thanks for your suggestions and for the detectCard code. I'll check out about the delay.
to Khanh:
The mega32 schematic is similar to mega8, you have to just maintain the same port pins. The SPI and UART are only one in each of the mega32 & mega8, so no confusion. If still a problem, best to check the connections again, as that's the single most reason for most problems.
to Arek:
Thanks!!

Rosevie said...

Thank you ! :D
so few people share their knowledge :'(

MANUDADA said...

sir,
i want to create a image viewer i.e. jpeg image viewer for which i am using a color LCD (nokia) and memory card (MMC) as storage.

What should i do in algorithm to fetch jpeg file from memory and display it on LCD.

Will it need some extra hardware (specially for jpeg files).

what should I study to implement this concept.

can we make a text viewer also like we can view TXT files.

please help me out

thank you

CC Dharmani said...

You can display text files on the LCD by reading the file and sending the text directly to the LCD.
For displaying the images, you need to convert them into bitmap, as most of the LCDs take bitmap image to display it pixel-by-pixel on the screen. If you want to display jpeg file, you can parse the jpeg into bitmap using software (you may need to refer to the jpeg standard for understanging the jpeg file format). This will avoid any hardware changes.

RG said...

I am a newbie with the avr's and am using a atmel dragon in ISP mode to try to implement your software onto an atmega328p. avrstudio informs me that I am trying to download a program larger than the memory space on the chip. Can someone tell me what I am doing wrong please? I am excited to get this going for use as a remote data logger. Thanks in advance.

RG said...

I got the code to compile for the atmega328p and found the settings in avrstudio to allow me to program the chip. Still have issues, but working on them. Thanks for sharing a great project

preethi said...

Sir,

Your FAT32 implementation code is great and simple to understand.

The code is working fine, as required ... However when i view the SD card on PC an autorun.inf file is created in the SD card.

I am using it with LPC2468.
Hope you guide me to understand why this is being created.

Thanks.

Preethi

CC Dharmani said...

Hi, autorun.inf is not created by the microcontroller, it's created by your PC. It's a well-known (I think) virus which creates that file in memory-sticks and the memory-cards, whenever you connect them to the infected PC.

preethi said...

Thanks Sir for ypur immediate reply..

Anonymous said...

hi..
very good blog..
i getting pain, i try to init my SD Card (i use VGen). when i send CMD0, CMD55 and ACMD41 the response is intermitten.. sometimes OK but sometimes NOT. and now.. when only the SD Card adapter the response 0x00, but when i insert the SD Card. it's response become 0xFF????? what's wrong?? please help

acceph@yahoo.com

Richard said...

I have made great progress on my data logger using the atmega328p thanks mostly to your code. I am having a problem writing over 15895 bytes. It seems my code crashes here, and it appears to be occuring someplace within the fat32 portion of the code. I am using a 2 gig SD card formatted in fat32. Can you suggest a place to look for a possible timing issue at this point? I have only limited resources for debugging and have pulled most of my hair out looking for this bug. Thanks in advance for any help.

Anonymous said...

hi sir,,
i am really newbie..
what is the differences between using voltage divider or not?
(to interface SD Card to AVR ATmega8535)because i have check both of them with the same c code, but the card response are different.. to your experience, which one is better?
with voltage divider = 0x82
no voltage divider = 0x08
those command are from CMD10 response.. please advice..
thank you
acceph@yahoo.com

Anonymous said...

Thanks for putting up all this cool stuff... We were thinking of interfacing an SD card (SPI interface) with out PIC18 ucontroller but coding in assembly is a requirement... do you know of any resources that could guide us to what the C codes actually do(so we can do same thing in assembly).. the SD Card manual is a rather tedious read..

sri said...

Folks,

I have implemted the 2GB ,sandisk SD card interface with modem.I followed the same logic as your logic and it is working .But I am observing some times sandisk memory card is going into hang state ,after this if we sending the command to restart the SD card also,not responding.need to do manually reinsert of the sd card.Is this is memory card behaviour?

Let me know so that i can add hard reset circuit in my hardware.Please suggest.



Thanks & Regards

S.Sridharan

sri said...

Dear Dharmani ,
Wating for your information .please share your comments on this.

Thanks & Regards
S.Sridharan

CC Dharmani said...

To Richard:
Glad to know that you solved the problem soon. Thanks for mailing me the solution. I'm sharing here your reply which may be helpful to others:

"I found why I was crashing, although I have not completely found how and where it is happening. However, at one point in the fat32.c code, you have the following within the writeFile function:
transmitByte(data);
buffer[i++] = data;
fileSize++;
if(data=='\r' blah blah
and then
if(i == 512)
go save the buffer.
Somehow, this index is getting incremented past 512 before this check and I have changed the statement to if(i>511) and the software now works. However, I am still at a mystery as to what is incrementing this index. It was causing the program to overrun other variables by continueing to increment i and moving data to buffer[>512] causing corruptions of other variables. I hope this can help others as well"


I'll modify that line in my next update to make the code crash-proof, if somehow the pointer gets incremented beyond 512 at any point. (though I also need to check why this should happen ever)

Thanks for the mail.

To anonymous:
If you are operating the controlller at 5v, the voltage divider is must, if it's running around 3.3v, you don't need voltage divider

To anonymous:
You can go thru the comments written in the C code and refer to the FAT32 doc given in the reference list, that would provide great details for understanding the code

To Sridharan
Usually the SD hangs due to improper connections (like loose connection or dry soldering etc) or due to noise in the supply line, which may make the SPI bus lines noisy. You can recheck the connetions and the supply bypass capacitors. Also, safe to have the supply between SD operating range (I've used from 3.3v to 3.6v)

Richard said...

Can you offer some insight as to why one brand of 2gig sd card might work, and another not work. I have a toshiba, and a house marked micro center sd that work fine, and a lexar and a kodak that do not. Are there timing differences or voltage differences that you are aware of? Also, 2 gig is as large as i have so far found that will work. Any input appreciated.

STRTI said...

Hi , Is it possible to include wireless?
Rgds,
ST

ST920 said...

Hi, is it possible to include wireless?
Rgds,
ST920

acep said...

Hello Mr Dharmani, my hardware work now, thank's..
previously i have problem with my small internal RAM, so i change the chip with bigger RAM Size(solved). but now i have problem again, my Erase() can't work properly. it just work fine for just 1 time, after that i have to unplug and plug again the SD Card, and my ERASE() will work. why this kind problem happen? below is my function: (take a look from yours)
do
{
SPI_Sector(CMD_ERASE_WR_BLK_START, StartAddr << 9);
SPI_Sector(CMD_ERASE_WR_BLK_END, (StartAddr + Total - 1) << 9);
reply = SPI_Sector(CMD_ERASE, 0);
} while (reply != Ready);
is there any something that i missed?
thank's

jusufcorp2008 said...

do you have the source code which built with codevisionAVR ?
cuz, i'm not familiar with winavr.
thanks b4.

Anonymous said...

Thankyou for your prompt reply. I really appreciated it..I'm the anonymous who is coding in assembly. I was able to initialise the card and read and write a block (raw data). First i wrote the write function and then added to my program. Nw for some reason,my write function no longer writes..but my 'read block' works fine (simulating on ISIS only)
Do you have any ideas of any possible problem? timing issues? i dont think i changed the function at all though :(

Anonymous said...

Dear Sir,
Does Mega8 architecture is insufficient to run i2c with ds 1307 rtc?
It is very difficult to isolet the problem.
Your program sends a message Send address fail.
please comment if same code can be adapted for atmega8.
regards

Anonymous said...

Very nice project. Some times there is FAT32 Error for no reason and maximum limit of saving 128 files on the root directory.

ramya said...

hello sir,

im working on PIC18f6722 to create fat file on sdcard, using SPI .but card is not getting initialized CMD0 im not getting response back getting value 0xFF .. so plz can you help me out where would be the problem??

Anonymous said...

hi,
its a perfect thing what i need. but i have a query, can you please tell me if there is any way, to compare a particular code word for a song in sd card using micro controller, and after comparing that song starts playing?

Anonymous said...

hello sir,



im usingthe same code trying with PIC controller ,its showing FAT32 not found and FAT32 is disabled , please kindly help me how to enable and where i ahve gone wrong..

very urgent.. kindly reply to my mail id ramya_298@yahoo.co.in

sahil raina said...

Hi,
I want to do serial communication from PC to nxp8051 such that only after a specific command from keyboard of PC the data in the PC is transmitted to nxp8051.
I will be waiting for valuable suggestions.

Anonymous said...

I'm trying to compile this code with AVR Studio 4 and I get the following error:

..../SD_main.c:59: undefined reference to `spi_init'

This is followed by a bunch of errors similar to this:

..../SD_main.c:80: undefined reference to `transmitByte'

Help me! I don't know what I am doing...

Anonymous said...

can the same code be implemeted in a atmega168

Anonymous said...

can the code be used in atmega168

Anonymous said...

can the code be used in the atmega168 be used in

CC Dharmani said...

Hi Guys, sorry for delayed response..

about the problem with different cards. I've usually found the problem is mainly in the hardware. Some cards work for lower volatges, but some don't. Similarly, some cards need the pull-up resistors and some work without them. Soembody may add the experience faecd by him/her in this.
But sometimes the software is responsible. One story: when I started writing this code, I was using SanDisk 2GB card. After successfully completing the testing, I got a Transcend 2GB card. The raw data transfer worked well, but FAT32 not found! When I checked the boot-sector, there was no boot-sector in the first sector of the card! But there was the MBR instead of boot-sector. I had not included any check for MBR in my first code as the SanDisk was having first sector as boot sector and no MBR. Eventhough both the cards were formatted with the same PC, same operating system, both were formatted differently (must be due to a card property). so, the code written for SanDisk did nto work on Transcend.
Well, I updated it to include check for the MBR too, and after that it worked on both the cards and some other cards, too.

CC Dharmani said...

To the anonymous with SPI related errors in AVRStudio4: It looks like you didn't include the SPI_rouines.c & .h files in your project. That's why you are getting those errors. Include them and recompile, you may not get any error.

To the anonymous using ATmega168: To use this code on ATmega168, you may need to change a few register name declarations (like USART registers). If you have a look at the datasheets, you can easily make those changes.

MANUDADA said...

sir can u tell me which company mmc or sd i can use in my project.
and where were u ?
i was waiting for ur reply.

CC Dharmani said...

You can use any brand card you want. I mostly use SanDisk cards. Rather than SD or MMC, you can go for microSD card, as they are low-cost and more easily available nowadays. Also, with microSD, you can use the SD card adapter where you can directly solder connector or wires without spoiling the card.

MANUDADA said...

now i want to decide the card.
1. microSD sandisk -----max memory that can be used??
2.can we use the small sized card present in the market.

CC Dharmani said...

You can start with 1GB or 2GB card. The size is the same for every microSD available in the market.

MANUDADA said...

sir actually i want to create a computer system in which i can show bmp txt and mp3 files to play
and data can be transferred by rs 232 port from PC
what should i do.
plz help me.

CC Dharmani said...

If you want to transfer files on RS232, you need to understand the file transfer protocols supported by RS232. If you are using windows, check in the Hyper Terminal, under 'transfer' menu, 'send file' command. There you'll get the protocol list from the drop-down menu, like Xmodem, Ymodem etc.. You can use any of these protocols and implement it in the microcontroller routines. After that, you can transmit a file directly over the RS232 to the microcontroller (for storing it in the card).
The code given here currently does not take file, but it takes data byte-by-byte.

MANUDADA said...

but what abt rest of system

text viewer
bmp viewer
mp3 file (decode is not available)

MANUDADA said...

sir i live in bhopal
where should i go to buy mp3 decoder chip
mumbai or delhi

CC Dharmani said...

One of my friends has got the mp3 decoder VS1003 from this site: http://feemo.in/
They stock the sparkfun components, which includes the mp3 decoder. You can contact them for more info (they are based in Mumbai).

MANUDADA said...

sir,

will i require a text file format system to view and edit a txt file im Uc.

CC Dharmani said...

You can edit text file using the FAT32 format itself, you don't need any other file format. You can use the FAt32 routines for it.

Erya Fathurrahman said...

Does this library provides wear leveling? SD Card like other flash wear really quick..

Luke said...

Great SD FAT32 library! I did find a small bug that is easy to fix, but very harmful. If you call the file functions with a text string for the file name there is a chance that memory corruption will happen

e.g. writeFile("Test.txt", dataString);

This happens because the convertFileName(char *fileName) function modifies fileName to be 12 bytes regardless of its original size. Any variable that is directly behind fileName in memory will be overwritten. The solution is quite simple though.

In FAT32.c:
1. Place this code at the top of convertFileName:

int j=0, k;

// Copy the file name to a large buffer so memory isn't corrupted by the convertFileName function
while((fileName[j] != 0) && (j<16))
{
FName[j] = fileName[j];
j++;
}
FName[j] = 0;
j=0;

2. In the writeFile function change "dir->name[j] = fileName[j];" to "dir->name[j] = FName[j];"

3. In the readFile function change "dir = findFiles(GET_FILE, fileName); //get the file location" to dir = findFiles(GET_FILE, FName); //get the file location"

4. In the deleteFile function change "findFiles(DELETE, fileName);" to "findFiles(DELETE, FName);"

In FAT32.h:
1. Place this variable declaration with the other global variables:

volatile char FName[16];

Dave said...

Hi CC,

I've been trying to implement your ATMega32 code with my ATMega16 microcontroller to read/write from a microSD card. I've been having some problems, and I can't figure out what's wrong. I get the infamous 'Fat32 not found' and 'Fat32 options disable' messages. I figured you might have an idea what I might be doing wrong. Here's what I got so far:

- I'm using a development board with the AVR microcontroller. It has RS232 and ISP programmer built in. I provide a 3.3V input. I connected the circuit exactly as depicted in your schematic with the following change: I connected PORTB pins 4567 to SD pins 1275, respectively
- I can see messages coming through the terminal just fine
- I've changed the makefile to 'MCU = atmega16'
- I've programmed the fuse bits to switch the clock to 8MHz
- I've switched the macros to '#define SD_CS_ASSERT PORTB &= ~0x04' '#define SD_CS_DEASSERT PORTB |= 0x04'
- I've tried enabling/disabling FAT32_TESTING_ONLY
- I've reformatted the SD card

I noticed one issue which I have no idea why it happens. I noticed that I had to change in port_init the line "PORTB = 0xEF" to "= 0xE3" because if I leave the 2,3 pins to high, it scews up the whole program (even the LED signal on PORTD won't work).

Do you have any idea what I might be doing wrong, and how to fix it? Your help would be GREATLY appreciated! Thanks,

Dave

**I also emailed you this comment, I wasn't sure which way would be the quickest in reaching you

CC Dharmani said...

To Erya:
The wearing part is usually taken care by using the formatting software. Right now this library does not include card format function, so it can not identify worn out blocks/sectors. But once you format the card using a PC, the operating system marks the bad sectors and those sectors are not allocated during file write, that is made sure here.
(If you are are using the card for long time, formatting is the only solution here to identify bad sectors. Card format function may be included in future updates. Thnaks for reminding it!).


To Luke:
Thanks for the suggestion, Luke. I'll test it out. I've been passing the file pointer rather than directly entering the file name while calling. I'll check for this one.
Thanks!

CC Dharmani said...

To Dave:
as I understand, you have connected the mega16 with the SD card as follows:

PB4 (SS) - SD_pin1
PB5 (MOSI) - SD_pin2
PB6 (MISO) - SD_pin7
PB7 (SCK) - SD_pin5

and it is correct.

But the change in macro is incorrect, as you are using the SS (PB4) pin for enabling the card.
The macros should be:
#define SD_CS_ASSERT PORTB &= ~0x10
#define SD_CS_DEASSERT PORTB |= 0x10

these are already given in the SD_routines.h, you just need to remove the comments from them and put comments on the earlier two macros defined there (the details are given there).

I think in your development board, the pin3 interrupt (INT2) might be used for some other purpose, that's why when you make the pin high, the program may be going to interupt routine and normal execution is not taking place there. You can use PORTB = 0xE3, no problem.

(You didn't mention anything about raw data transfer, like block read or block write etc. Is raw data transfer working fine? Are you getting, "SD init fail.." message? Because, if you have those wrong macros, you should be getting that error message, too).

Chris said...

Wow, fantastic code! And that you are still supporting users in the comments section so long after the original blog post is incredible!

While trying to compile with avr-gvv 4.3.3 I get the following error:

makefile:50: *** missing separator. Stop.


Using your makefile included in the link below your post, as there wasn't one in the zip file.

Any ideas?

Chris said...

Ok so there IS a makefile in the zip, for some reason I didnt have it, not sure why not. But when I try to compile with it this is what I get:

dep/FAT32.o.d:1: *** multiple target patterns. Stop.

I'm sure I wouldnt have issues if I was on Windows, but I'm using Linux

Chris said...

Last comment, promise =]

I got this working on Linux. Step one is to delete the default/dep folder, it is full of windows specific info that we don't need. Then edit the Makefile so that the compiler is avr-gcc not avr-gcc.exe. Lastly, change sd_routines.h to SD_routines.h as Linux is case sensitive =]

CC Dharmani said...

Hi Chris, thanks a lot for sharing the solution!!

Anonymous said...

Dear Sir,
is it possible to use 89V51 instead of atmega controller for SD card interface, since 89V51 is also having SPI interface

-Ketan

CC Dharmani said...

Yes, you can use 89v51. You can use any microcontroller with SPI bus. A controller without SPI bus can also be used if one is ready to implement low level SPI routines using port pins or may be using USART.

David said...

Hi Dharmani,

Note sure if this has been mentioned, but this is in relation to Richard's comment about the writeFile curruption of data with i > 512 bytes.

The reason you could have more than 512 bytes is because if a user enters a CR for the 512th byte of data, then the code adds the LF to the 513th byte, hence corrupting the memory.

Cheers,
Dave

David said...

@HayaMini

Your detectSDCard function should have SPI_HIGH_SPEED; added after SD_init(); because SD_init uses SPI_receive.

The program can and has crashed because of this.

Cheers,
Dave

Craig said...

Hi Dharmani,

Thank you very much for posting the code for this project. getting it working with an atmega32 was easy.

I've read the posts and noticed that people have ported this to other controllers. I was wondering, if you have experience using the atmega644. If yes, would you be able to say if its possible to port this to the atmega644 and also mention anything i should watch out for in particular.

Thanks

CC Dharmani said...

To Dave:
That's correct, thanks for pointing it out. As you said, if the user enters 512th character as CR (pressing 'ENTER' key), then the if(i==512) condition will never be satisfied, as 'i' becomes 513.
This will need a small modification so that in such a case, the LF character is appended in the next sector.. I've just done it, but not tested on the card. I'll update it here after testing.

To Craig:
Yes, the code can be used on ATmega644. You will need to change names of UART registers. Also change the TIMSK and GICR register with equivalents of mega644.

Enjoy!

jadin jousche said...

dear sir cc,

i haven't tried this code yet but can you help me in making a datalogger out of atmega32+SD card. i am taking input from a power measuring kit in CSV format thru the UART of my uC. my problem is to put this in the SD card thru the atmega so i can accessed the data in the SD card on my pc.i am not a hardcore programmer but suggestions are appreciated.

my email is cheloniaq@gmail.com

thanks!

CC Dharmani said...

Hi Jadin,
check out this link:
http://www.elektroda.pl/rtvforum/topic1562905.html

It's a temperature logger using this SD libraries. It will be a useful reference for you. The code is also given. The page is not in English, but Google translator works good enough there.

MANUDADA said...

hello sir,
I want to ask how to design a battery status indicator in case of Li-ion battery if we are given a mobile battery and calculation to be done using a micro controller.

does it require comparator circuit or any ADC control system.

plz help me sir.

can u plz send me the pcb layout of 3310 back side.
i have the difficulty of making pcb behind that 3310 nokia lcd.
my mail id :
manu.oist.cse@gmail.com

Mikiii said...

Gooday Sir.

Is there a way to program using a DYI programmer (i have created DAPA) via AVRSTUDIO4? coz its to expensive to buy one.

thank you!.

michaelo.oliveros[@]gmail.com

David said...

I have started using a 16Mhz external crystal. Other than the BAUD rate and F_CPU, what else do I need to change to make it work with the 16MHz?

CC Dharmani said...

Hi David,
you don't need to change anything in the code for 16MHz crystal. You can just readjust the baud on your terminal.
Just recompile the code with new clock setting.

suraj singh said...

sir i want to interface sd card with atmega 16 using cv avr rather than winavr because i am comfortable with that can you help me

Novacaine said...

This is really some great work. If I want to interface SD card with PIC18F4550 - then what should I do?

Thanks in advance!

Anonymous said...

Thanks a lot . Your code helped me a lot . I faced some difficulties porting this code for 32 bit processor . I think it would help a lot of people like me , only if the code was platform independent.

Anonymous said...

Thanks, great code!
I'm converting it to big endian for my 8051 derivate compiler.
I am testing the "findFiles" function to list all the files. I am only getting 62 files (placed 100 files on the card). Has anyone tested with more than 62 files? Maybe the bug is in my modifications...

thanks,
Lieven.

PAF said...

Sir,

I have implemented your code, and everything seems to work on my ATmega32. I am actually sending the data from another microprocessor (ATmega1280)that is capturing data from a peripherial device. To get all of the bytes stored, I have to put a 15ms delay between sending bytes. Is there any way to speed this up?

Thanks

Ingmar Hendriks said...

Has anyone gotten this marvellous library to work with SDHC cards? Ifso then please tell me how it was done.

Arek said...

I can't delete files. I only can read memory capacity and get file list. I'm using mega162, 3,3V power supply, pull up resistors on SPI lines and current limiting resistors 100 Ohm.

JAIMIN said...

priyanka123can you send me eagle file of pcb layout mirror image as well as original?

my Email id is
jaimin_12@yahoo.com
please help me..
thanks in advance.

JAIMIN said...

hi..

can you send me eagle file of pcb layout mirror image as well as original?

my Email id is
jaimin_12@yahoo.com
please help me..
thanks in advance.

Piotr M. said...

Hi, I found possible reason why in writeFile function variable i overflows 512.

Here is part of your code:
==========================
FAT32.c
void writeFile(...)
--------------------------
buffer[i++] = data;
fileSize++;
if(data == '\r') {
transmitByte ('\n');
buffer[i++] = '\n';
fileSize++;
}
==========================
Consider situation when i=511.
If data contains Carriege Return (CR) character then we puts it into buffer and increments variable i. Now i=512.
In next IF we puts LF character into buffer and also increments variable i. Now i=513.

BTW the code is great :)

Ingmar Hendriks said...

Quote: "Hi BillH,
visit this post around this weekend, probably you'll find an update in this code which will support SDHC cards (tested on 8 GB, but I think it would also support higher capacity cards which come under SDHC category). It's pending for quite a long time, just little short of time to update the files.
"

Iam looking for the SDHC support in the code but i can't find it. Am i going blind? Ifso please tell me were to look because i need to work with sdhc. If not, than maybe is it possible to post the code?

CC Dharmani said...

To Piotr M.
Thanks for having it mentioned once more. Earlier David had found that problem. I was too busy to do any update, I'll fix that one in a week.

To Ingmar Hendriks
Sorry for that, I did mention that. I had even got the SDHC cards for testing. But I got into too hectic schedule for quite a long time. Never got that weekend when I could do the update. I even used up those cards in cellphones.
Anyways, your comment has the perfect timings, my vacation started yesterday and I've got SDHC cards today. So, this weekend I'm already up to putup the upgrades.

swati said...

hi
ur code is fantastic
but i am facing the problem.the serial window shows that SD init fail..FAT32 not found!
i check all connection, all voltages
i am doing this project using atmega32
plz help me

swati said...

hi
ur code is fantastic
but i am facing the problem.the serial window shows that SD init fail..FAT32 not found!
i check all connection, all voltages
i am doing this project using atmega32
plz help me

CC Dharmani said...

To Ingmar Hendriks:
The SDHC compatible code is uploaded, have a look!!

Swati:
as I've always said, most of the time, the reason is the connections. Check the SD adapter also.
Anyways, you can download the new version (2.3) and try it out. Also, check out the modified schematic to add two pull-up resistors, in case that's the trouble.

Ingmar Hendriks said...

Thanks CC Dharmani;
You'r a life saver. I was suppost to deliver a beta version of the sd datalogger next wednesday, now i can add sdhc compatibility to the list!

ps: the code is going to be used as a datalogger for the following a wind turbine car: http://www.spiritofamsterdam.nl/pg-23769-7-33812/pagina/english_summary.html

kdeo said...

This is a very unique piece of work. It worked in first shot with elegance. Great work.

-Kshitij
IITK

Pascal said...

Thx for the coding,
we do have a atmega128 and a atmega32 on the STK500 and 501 but we cant get the atmega128 code working.

We had some issues with the different registers and just swapped to the atmega 32, does anyone have the code for an 128?

Best regards
your
Rotesmofa

Bart said...

Hi
congratulations for your code, it's really great, i'm using it in my project. I've change a little bit writeFile function, now it's sending 64-bytes array to SD card once a second (it works with GPS module). Everything works great. Almost everything - always first 64 cycles are ok, but after that it sends rubbish. Is there any limit in number of appending file? Any idea where's problem?

CC Dharmani said...

Hi Bart,
there is no limitation on appending file. You can check the modifications you made in writeFile. You can declare the GPS string (64 bytes) as global variable, modify it in main or some other function and then call writeFile function.
Modify a part of writeFile function as shown below, keep the remaining function as it is:

k=0;
while(1)
{
if(start)
{
start = 0;
startBlock = getFirstSector(cluster) + sector;
SD_readSingleBlock (startBlock);
i = fileSize % bytesPerSector;
j = sector;
}
else
{
startBlock = getFirstSector(cluster);
i=0;
j=0;
}

while(k < 64)
{
data = gpsString[k++];
buffer[i++] = data;
fileSize++;

if(i >= 512)
{
i=0;
error = SD_writeSingleBlock(startBlock);
j++;
if(j == sectorPerCluster) {j = 0; break;}
startBlock++;
}
}

if(k == 64)
{
for(;i<512;i++)
buffer[i]= 0x00;
error = SD_writeSingleBlock(startBlock);
break;
}

Bart said...

I use it in exactly this way:) So i tried your code and it works perfectly now:)
Thanks for everything

CC Dharmani said...

Glad to know that, Bart!!
I'm sure this will help someone trying on the same lines..

Anonymous said...

Hey nice stuff
But it seems i can not make it work
i use mega16/8mhz
Terminal shows stuff like "$$%$%"
Is there anything i should do?

CC Dharmani said...

You need to recheck your clock setting as well as Terminal settings.
Clock: Recheck that the fuses are set correctly such that the controller is really operating at 8MHz and not at default 1MHz
Terminal: Select 19200 baudrate, No parity, Flow control 'None'

disney said...

Hello, thanks very much for this project! This is actually my first MCU project after one semester of "Microcontrolles for device applications". I need to play sound via AVR at correct speed. And I chose this SD project to supply the sound data from the SD card.
I have made custom PCB and was able to program ATmega32 via parallel port and ISPProg software.
I am having a small problem though.
I successfully programmed the ATmega32 with v2.3, the LED lights up, but I am not getting any text in the hyperterminal, with or without 2GB SD card inserted. Should some terminal menu be visible even without SD card in slot?
I use 16MHz crystal. I did modify that in the beginning of SD_Main, but I am not sure which terminal speed should I choose. Logic tells me that if for 8MHz it is 19200bps, for 16MHz it would be 38400bps. Right?
I can type in the terminal and I get signal transferred thru MAX232. But Mega32 is quiet, nothing comes from its TXD pin.
Do you have any idea, what could be wrong?

CC Dharmani said...

Hi Disney,
you are right about the baud: 38400 for 16MHz crystal. (Check the other terminal settings too: 'no parity', flow control 'none', 1 stop-bit).
Even though the card is not inserted, the heading and a message that "SD card not detected.." will appear on the terminal.
You said that nothing comes out of the TXD pin of mega32. I hope you are using an oscilloscope to monitor the signal at the TXD pin. Actually, only at the start-up the message is sent. After that the M32 waits for the response from the terminal. So, you need to capture the signal immediately after power-on (or reset). If there is no card detected, the M32 will not send anything after first status message.

Once more you can have a look at the max232 connections and DB9(F) connector, too!

disney said...

Thanks for the response!
Actually I have had wrong gender DB9 connector, so the TXD and RXD were swapped. So it seems that MAX232 was pulling the ATmega's output high all the time, so there was no signal detectable. Now after swapping RXD and TXD, I am getting pretty output from ATmega32 and MAX232. But actually one symbol (bit) lasts about 435us, which seems to indicate 2400bps rate.
But still I am not able to see anything in the terminal. Yet my COM port is working, just tested with other bidirectional device.
If I see some MAX232 is pushing data onto RS232, does it imply that I should see something in the terminal? Does something special needs to be set in the terminal? Is the communication unconfirmed by the target PC or is there some acknowledging PC should send?
Thanks very much in advance for your help!

disney said...

Mr. Dharmani, please disregard my last post. I had to specify CKSEL bits, to operate the MCU at 16MHz instead of 1MHz. Everything works now.
Thanks again!

raydem said...

thank you for the code.

I'm trying to adapt your code for the ATMEGA128, but the problem is that it returns in the getBootSectorData in the point if(mbr->signature != 0xaa55) return 1;. if I delete that line the program continues until if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB) return 1; and returns.

Could you help me solve this?

thank you

Anonymous said...

Cannot make it work with zener diodes
It does works though with resistors at low speed

I don't think i should speed it up for zener diodes, right?

Any thoughts?

-SSJ

Online said...

HERE IS TWO USEFUL PRODUCTS RELATED THIS PROJECTS
SD (Secure Digital) memory card Connector
[link=hyperlink url]http://onlinetps.com/shop/index.php?main_page=product_info&cPath=68_91&products_id=716[/link]


SD card breakout board
[link=hyperlink url]http://onlinetps.com/shop/index.php?main_page=product_info&cPath=66&products_id=729 [/link]

Anonymous said...

This is great work by you sir, I am doing a project which includes a SD card of 2GB and this will surely be a helpfull resource. I am using LPC2138 with sd card. I can read and write files successfully but I get error whrn I connect card to PC I get message
"The file or directory is corrupt and non-readable". can you please tell me causes of corruption.

CC Dharmani said...

To SSJ:
Even if you are using resistors, it's better to have zeners to protect the SD if your programmer has 5v level outputs.
If you don't need high speed, resistors are OK. For the problems with zener, better check the zeners!! ;)

To Anonymous:
Did you change anything in the writeFile function? Did you use the raw block write/delete option after creating the file?

jadin jousche said...

will the routines run smoothly on a atmega128 with 16 MHz crystal? what changes are usually made? by the way, im still a beginner with these things..

CC Dharmani said...

Hi Jadin,
not much of the change required for ATmega128, you'll need to change the UART register names. It'll work at 16MHz.

jadin jousche said...

Thanks a lot Mr CC Dharmani! Im gonna re-read the posts here so I can catch up with this project..

Anonymous said...

Don't know why but even with zeners i have problem at 8Mhz SPI speed
What works is 3 zeners and resistor divider at MISO line and only at 4Mhz!

But i figured it out
I use max3002 now and it recognizes SD card even with the programmer plugged(read/write everything)
I will try to program and see if it messes up the card

If anyone tries my method and has any problems my mail is dbsjro@hotmail.com

CC Dharmani i have made PCB breakout board if you want my files

-SSJ

CC Dharmani said...

Hi SSJ, I have pcb breakout with SD connector, I always need to use it with the SD card adaptor for microSD cards. It's really difficult to find here the microSD connector to mount on the PCB.

You can send me the files on ccd@dharmanitech.com, it will be helpful when I find the connector!

swati said...

hello sir,
as u guide me my project is now working well. i also playing the audio file by modifying code. and its working well now i want to interface keypad. when i press 1 then the first audio file play.but how i do .how to connect link between keypad & audio file. plz tell me.

Anonymous said...

Hi,

Too good, i have converted the code to pic and logging my vehicle readings (speed, rpm, temperature and stuff like that) on to sd card, i had to modify a tiny bit for transend card.

thanks for the code :-)

SKG

Ravindra said...

Hi Dharmani,
i used your code and found no problem, its great. in one of my requirement i need to move the data between two SD cards, in your code, i understood that only one can be connected to the micro controller.
can you explain what are all the necessary things we need to do for accessing two cards at a time.. this concept can be used to share the file system between two medias thanks in advance.

Chillance said...

Hey!

Awesome stuff!

I was just wondering what the license on this is?

«Oldest ‹Older   201 – 400 of 670   Newer› Newest»