AVR SDCard FAT support with FatFS

You’ve probably seen or done lots of cool microcontroller projects already, but did you ever consider adding permanent data storage to your projects? I did, and there are numerous advantages: saving data from sensors (data logger), saving configuration files, reading external content like images or songs, and so on!
One thing is to connect an SD Card to an AVR microcontroller via SPI (relatively easy), a completely different thing is to be able to manipulate files that are later compatible with your PC (if you take the card from your microcontroller project and connect it to your PC).
This is because PC data storage uses a file system, which needs to be implemented in order to achieve compatibility. There are several file systems currently in use, keeping up with constantly evolving hardware: FAT, FAT32, NTFS, EXT, etc. A file system is a way of organizing the data in the entities we are all used with: files, folders, but there is much more than that. One of the simplest file systems, yet compatible with most Operating systems available today is the FAT (older and with reduced capabilities) or the FAT32 (acceptable for the needs of most microcontroller projects). Even so, implementing the FAT32 logic is a considerable effort, taking a lot of time to do from scratch. Here is where FatFS comes to help!
ATmega128_SDCARD_FAT32

About FatFS

FatFs is a generic FAT file system. Intended as a module for small embedded systems, the FatFs is written in compliance with ANSI C and separated from the disk I/O layer completely. This makes it independent of the hardware architecture. It can be incorporated into low cost microcontrollers, such as AVR, 8051, PIC, ARM, Z80, 68k and etc…, without any change. Just perfect for this purpose!

Basic circuit diagram

I opted using SDCard modules available on Ebay. They come with a nice quality SDCard holder, a few resistors and capacitors, a LM1117 3.3V regulator, exposing the relevant data pins for easy connection via SPI to the microcontroller: CS, MOSI, MISO, SCK, VCC and GND.
sdcard_module_1 sdcard_module_2
sdcard_diagram_avr
Connecting it to the AVR is simple. Just connect the header pins to the corresponding SPI pins on the microcontroller. You have: MISO, MOSI, SCK. For CS Choose any available IO pin. VCC must be connected to the 3.3V. Let me know in case you need any help doing this. You can also connect an SDCard (or mini/micro sd) to the AVR directly, just match the pins correctly, according to the table in the picture above, and make sure you are using a 3V supply for the Card. The AVR can be connected to 5V (I am using it this way in this example).

The software

As I already told you, I’ll be using the FatFS code here. FatFS also has a minimization level function, see _FS_MINIMIZE in ffconf.h :


#define _FS_MINIMIZE	2	/* 0 to 3 */
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/   0: Full function.
/   1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
/      are removed.
/   2: f_opendir and f_readdir are removed in addition to 1.
/   3: f_lseek is removed in addition to 2. */

There are also other macros for disabling the code that you need and save on the output hex size (see _USE_LABEL, etc).
My sample mounts the SDCard, and creates a file. Then it appends some additional content. Finally it shows file size, the volume string and the serial number, and tries to read the data from the file and displays it on the 5110 LCD.

// init sdcard
UINT bw;
f_mount(0, &FatFs);		// Give a work area to the FatFs module 
// open file
fp = (FIL *)malloc(sizeof (FIL));
if (f_open(fp, "file.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {	// Create a file 
	char *text = "Hello World! SDCard support up and running!\r\n";
	f_write(fp, text, strlen(text), &bw);	// Write data to the file 
	f_close(fp);// Close the file 
	if (bw == strlen(text)) { //we wrote the entire string
		led1.Set(1); // Lights LED if data written well (D4 led on atmega128 board)
		lcd.goto_xy(0,0); lcd.send_format_string("Created:%dB\n", f_size(fp));
	}
	//else led2.Set(1);
}
// test append
if (f_open(fp, "file.txt", FA_WRITE | FA_OPEN_ALWAYS) == FR_OK) {	// Open existing or create new file
	if (f_lseek(fp, f_size(fp)) == FR_OK) 
		{
		char *text2 = "This is a new line, appended to existing file!\r\n";
		f_write(fp, text2, strlen(text2), &bw);	// Write data to the file
		if (bw == strlen(text2)) { //we wrote the entire string
			lcd.send_format_string("Appended:%dB\n", f_size(fp));
		}
			
	}	
	f_close(fp);// Close the file		
}	
	char str[12];

	
// get card volume
char szCardLabel[12] = {0};
DWORD sn = 0;
if (f_getlabel("", szCardLabel, &sn) == FR_OK) {
	lcd.send_format_string("%s SN:%X\n", szCardLabel, sn);
}			
	
// read from file
if (f_open(fp, "file.txt", FA_READ ) == FR_OK) {	// Create a file
	char text[255]; 
	UINT br;
	f_read(fp, text, 255, &br); 
	f_close(fp);// Close the file
	// cut text the easy way
	text[10] = 0;
	lcd.send_format_string("Read:%s", text);
}	

The result:
atmega128_sdcard_fat32_fatfs sdcard_pc_view

The sample code, compilable with AVR Studio is available here:
test_sdcard_avr128

This article has 8 Comments

  1. Hello Radu,
    another time: thanks a lot for your great contribution!

    As far as I understand, you say that the 5V-powered microcontroller can interface the SD card directly, without using level converter (e.g. voltage divider) circuits between both of them? [As long as the SD card is powered with 3.3V] Or does this only work with the mentioned modules?

    We used voltage dividers (but not the module) but now the SD card has become unreadable on every PC we tried. No device is recognized, so no possibility to reformat the card to get back to a plain file system.

    Two questions about that:
    1) Assumed that the hardware is built up correctly, is it possible to destroy a SD card just with the wrong software? We are a bit afraid that we will crash other cards too.. Or on the other side, is their a high probability that we have a hardware misconfiguration?

    2) Do you know a way to restore a file system on a card that absolutely does not respond to Windows PC card readers or Smartphone Card Slot anymore?

    Thank you,
    katze

  2. katze, if you’ve connected the sdcard to 5V you probably burned its controller, and there is nothing to do to revive it.

    As shown in the article , you should have connected the entire system mcu+sdcard to 3.3V, the text says : ” VCC must be connected to the 3.3V.”

    To answer your questions:
    1. No, software cannot destroy the hardware in this case. But over-voltage can.
    2. I assume you’ve damaged the SDCard physically, so if this is the case , there is no way to repair it. For software defects, re-formatting the SDCard is usually enough.

    I am curios, what are you working on, given all your previous questions?

  3. Hi Radu, thank you for your fast feedback.

    AFAIK the card was never connected to any voltage higher then 3.3V, but since you state that software alone cannot destroy the hardware, there must be an error in our connections. We’ll check that as soon as possible.

    To answer your question, a friend of mine builds some smaller µC projects, first the ENC28J60 project(s), now he turned over to a simple temperature logging on SD card. His english is not very good (even worse than mine, that is), so I try to help him as much as i can. It’s a pleasent coincidence to see that your work covers a lot of the small projects we are tinkering with.

    I am more into Geiger Counters and Scintillation Gammaspectroscopy (as I’ve seen you also did some work with these, another great coincidence) and ATM I try to get or build a smooth negative voltage supply (-1200V) for my Bicron Scintillator (Any ideas about that?^^). In the future, I’m planning to follow my friends steps and will try to build another radiation detector, this time logging data into the webs using the ENC28J60 module.

    Yours, katze

  4. according to datasheet sd card only accept 3.3v, so what if i connected the sd card and paralleled with avr isp programmer that used same miso, mosi and sck on microcontroller pin, will it burn the sd card, so i must to remove the sd card first to program the microcontroller, (i’m afraid this case can be an issue when i pair with another devices that shared the SPI pin)

  5. i’m sorry Radu, my first comment was a question not the answer from katze question, i’m forget to put the “?”

  6. Hi. I am logging data in a SD with STM32. I want to write a int with F_write function but it only work with string. Do u have any idea how can i log int on my SD?
    Thanks

Leave a Reply