In this tutorial we will learn how to use an SD Card for mass data storage.
SD Cards (Secure Digital Cards) are quite popular these days for things like digital camera's, video camera's, mp3 players and mobile phones. Now you will have one in your project! The main advantages are: small size, large data storage capability, speed, cost. It has flash storage that does not require power to hold data. The current version of the sd card library that we will be using in this tutorial works with "standard capacity" sd cards up 4gb in size. I hope to find time to add "high capacity" and "extended capacity" capability to the library.
SD Card have 2 data transfer types "SD Bus" and "SPI Bus". Most PIC's have an SPI port. The "SD Bus" is faster, however uses more pins. We will be using SPI in our circuit. For more info on SPI read the tutorial in this book: SPI Introduction. The SPI mode for SD Cards is 1,1.
We are not responsible for your data or SD card. Make sure you have nothing important on your SD card before you continue.
These SD Cards are 3.3v devices, therefore a 5v to 3v conversion is needed between the PIC and the sd card. We will use resistors to do the conversion, however there are many other methods. See http://www.microchip.com/3v/ for more information. Another setup may be needed if you are putting more devices on the same SPI bus.
This circuit will use 16F877 If you are using a different PIC for your project, refer to the PIC's datasheet for pin output levels/voltage. For example, 18F452 has many pins that are 5v-input that give 3v-output. These pins show as "TTL / ST" - TTL compatible with CMOS level outputs in the datasheet and they will not require any voltage conversion resistors. If you are not sure, set a pin as an output, and make it go high then test with a volt meter.
Before we can build our circuit, we will need to find ourselves an sd card slot that can plug into our breadboard. You can find pre-made sd card slots on ebay and other places around the net. It is quite easy to make your own anyways. I took one out of a broken digital camera and placed it on some blank breadboard and soldered on some pins. Here are some images of my sd card holder:
Follow this schematic for 16f877, if you are using another PIC, check the pin-outs for the SPI bus. The pin-outs of your pic will show SDI, SDO, SCL and SS. The pin SS is the chip select pin, you can use any pin for it but the others must match.
With the use of the sd card lib (sd_card.jal) and a sample file 16f877_sd_card.jal, we can easily put one in our own circuit for mass data storage! You will find these files in the lib & sample directories of your jallib installation.
The most up to date version of the sample & library can be found at:
Sample file - http://jallib.googlecode.com/svn/trunk/sample/16f877_sd_card.jal
Library file - http://jallib.googlecode.com/svn/trunk/include/external/storage/sd_card/sd_card.jal
Now that our circuit is built, lets test it and make sure it works before we continue with more details. Compile and program your pic with 16f877_sd_card.jal from your jallib samples directory. If you are using another pic, change the "include 16f877" line in 16f877_sd_card.jal to specify your PIC before compiling.
Now that you have compiled it, burn the .hex file to your PIC
Plug your circuit into your PC for serial port communication at 38400 baud rate. Now turn it on. Press the reset button in your circuit, you should get a result similar to this:
ASCII outputHex output
As you can see from the first image, we got some actual readable data off the sd card as well as a bunch of junk. The sample file reads the first sector (512 bytes) from the sd card. My sd card is formated with fat32, this is why I can read some of the data output.
In the second image (after clearing the output and resetting the circuit), there was too much data to show it all. It only shows the last bytes received. If you get the same hex output "66 22" followed by many "00", your circuit has successfully written data and read it back again. You now have a working sd card circuit!
I'm just going to quickly go over some of the key points you need to know about sd cards. Open the sample file with an editor if you have not done so already.
The code in the sample file may change, therefore it may be different then what you see here. The sample file you have downloaded will always be tested and correct.
Include the chip
Specify the PIC you wish to use as well as your clock frequency
include 16f877a -- pragma target OSC HS -- HS crystal or resonator pragma target clock 20_000_000 -- oscillator frequency -- pragma target WDT disabled pragma target LVP disabled
Disable Analog Pins
enable_digital_io() -- disable all analog pins if any
Include other libraries required
-- include the delay library include delay
Setup serial communication and port speed
-- setup uart for communication const serial_hw_baudrate = 38400 -- set the baudrate include serial_hardware serial_hw_init()
SPI Settings
Here you may change the chip select pin "pin_SS" and "pin_SS_direction" to another pin. SDI, SDO and SCK must stay the same for the SPI hardware library.
You may notice that we are not defining/aliasing pins sdi, sdo and sck. We do not need to define them with a line like "alias pin_sdo is pin_c5" becase they are set within the PIC and cannot be changed. If we use the SPI hardware library, we must use the spi hardware pins. We only need to define there direction like this "pin_sdo_direction = output".
You may also choose the SPI rate. According to the SPI hardware library, you can use SPI_RATE_FOSC_4 SPI_RATE_FOSC_16, SPI_RATE_FOSC_64 or SPI_RATE_TMR. The fastest is FOSC_4 (oscillator frequency / 4). You may require a breadboard for the fastest speed, keep your SD Card as close to the PIC as possible.
-- setup spi include spi_master_hw -- includes the spi library -- define spi inputs/outputs pin_sdi_direction = input -- spi input pin_sdo_direction = output -- spi output pin_sck_direction = output -- spi clock -- spi chip select pin ALIAS sd_chip_select_direction is pin_SS_direction ALIAS sd_chip_select is pin_SS sd_chip_select_direction = output -- chip select/slave select pin sd_chip_select = high -- disable the sd card -- spi_init(SPI_MODE_11,SPI_RATE_FOSC_16) -- choose spi mode and speed
Include the SD card library
Select sd card settings & Include the library file, then initalize the sd card.
Some sd cards may require a 10ms delay every time you stop writing to the sd card, you can choose weater or not to have this delay. If you are doing many small writes and are worried about speed, you may set SD_DELAY_AFTER_WRITE to "FALSE".
-- setup sd card library const bit SD_DELAY_AFTER_WRITE = TRUE include sd_card -- include sd card library sd_init() -- initalize the sd card
Read the first sector from the SD card
Reading is easy, there are 3 procedures within the library that MUST be used.
sd_start_read(0) - start reading at specified sector (sector 0)
sd_read_data(byte1, byte2) - actually read data from the card (2 bytes at a time)
sd_stop_read() - stop the read process
You can also use the sd_read_pulse(number) procedure to skip past data. For every 1 value added, there will be 2 bytes skipped since this procedure simply reads data and ignores the input.
If you have more then one SPI device on the SPI bus, do not interrupt or switch devices until the complete read process has finished with sd_stop_read, do not allow the chip select pin to go high.
_usec_delay(100_000) -- wait for power to settle var byte low_byte, high_byte -- vars for sending and recieving data -- read the boot sector (sector 0) sd_start_read(0) -- get sd card ready for read at sector 0 for 256 loop -- read 1 sector (256 words) sd_read_data (low_byte, high_byte) -- read 2 bytes of data serial_hw_write (low_byte) -- send byte via serial port serial_hw_write (high_byte) -- send byte via serial port end loop sd_stop_read() -- tell sd card you are done reading
Write some data to your sd card
Writing is also easy, there are 3 procedures within the library that MUST be used.
sd_start_write(20) - start writing at specified sector (sector 20)
sd_read_data(byte1, byte2) - write to the card (2 bytes at a time)
sd_stop_write() - stop the read process
When writing to your SD card, you MUST write 512 bytes at a time. In this example, we are writing (256x2) = 512 bytes + (128x2) = 256 bytes for a total of 768 bytes. This means we have written one sector (512 bytes), as well as half of a sector (265 bytes). The half of a sector(256 bytes) that we have written, will not actually be written to the sd card until we finish the sector with data.
For this reason, you will need to use the sd_write_to_sector_end(value) procedure. This procedure will automatically finish the sector for you with the "value" data specified. In our case we are writing 0x00 till the end of the 512 bytes (end of the sector).
Just as we noted with reading data, you may not interrupt the SPI port until you have completed the write process with the sd_stop_write procedure.
Please note that we are writing to sector 20
-- write (0x66, 0x22) to sector 20 over and over.
low_byte = 0x66 -- set low byte to write
high_byte = 0x22 -- set high byte to write
sd_start_write(20) -- get sd card ready for write
for 256 + 128 loop -- write 1 sector + 1/2 sector
sd_write_data(low_byte, high_byte) -- write data to the card
end loop
sd_write_to_sector_end(0x00) -- 2nd sector is not done, so finish it
-- sectors must be completed during write
sd_stop_write() -- tell sd card you are done writing
Read back the data we have written
Now read 2 sectors (1024 bytes) from sector 20 (where we had previously written data). You will get 512 + 256 bytes of 0x66 & 0x22 as well as 256 bytes of 0x00's
-- read the data back, should get (0x66, 0x22) over and over. sd_start_read(20) -- get sd card ready for read at sector 20 for 512 loop -- read 2 sectors (512 words) sd_read_data (low_byte, high_byte) -- read 2 bytes of data serial_hw_write (low_byte) -- send byte via serial port serial_hw_write (high_byte) -- send byte via serial port end loop sd_stop_read() -- tell sd card you are done reading
Now you can put whatever you want on your SD card, or possibly read lost data off of it.
If you want to read files stored on the card by your PC, there wil soon be a FAT32 library and tutorial so you can easily browse, read and write to files and folders stored on your card.
What are you waiting for, go build something cool!
The Jallib SD Card Library - Written by Matthew Schinkel
SanDisk Secure Digital Card - http://www.cs.ucr.edu/~amitra/sdcard/ProdManualSDCardv1.9.pdf
How to use MMC/SDC - http://forums.parallax.com/forums/attach.aspx?a=32012
Contact Us | Terms of Use | Trademarks | Privacy Statement
Copyright © 2009 . All Rights Reserved.
Powered by Drupal and Drupal Theme created by vigilianty.