Sei sulla pagina 1di 19

Simple FAT and SD Tutorial Part 3

Finally back! Sorry for taking a while, but getting the SD cards to work required quite a bit of
research! In this part of the tutorial, we’ll start talking with the SD card. Once you get that
working, adding the FAT library developed in the previous part will be easy.
This tutorial will most likely be the most challenging covered in my blog so far, so beware:
You may need to do some troubleshooting on this one! If you encounter problems, I
recommend you to ask any questions at the AVR Freaks tutorial forum topic, so more people
might be able to help you than just me!

Basic hardware setup: ATmega88 with UART console

The 3.3V UART I covered just a while ago will form the basis for this project. Only change we
will be doing is to replace ATtiny2313 with ATmega88. This is because SPI, SD and FAT code
will eat up almost 3 kB of program memory, and the ATtiny chips with that much program
memory and separate RX/TX and SPI pins are not that common, while ATmega88 is readily
available (48 and 168 work as well, of course). To accommodate the new chip, the following
hardware changes are made to the ATtiny2313 version:
 ATmega88 will require two ground connections
 In addition to VCC, also AVCC for analog circuitry needs to be wired to VCC
 Additional capacitor between AVCC and GND is recommended (I used 10 uF)
 Programming header MOSI/MISO/SCK are also in different place
I assume you are by now capable of wiring the ATmega correctly, but just to make things
easier, I attached a pinout diagram with the RXD/TXD wires marked with green (they go to
MAX3232 or similar RS232 circuit), VCC/GND marked with red/blue, crystal pins with
yellow and SPI/programming pins with black. These are all pins that need to be connected in
this project.

Also, the UART facilities of ATmega family differ a bit from ATtiny2313, so our helper
methods needs tweaking:

void USARTInit(unsigned int ubrr_value) {


//Set Baud rate
UBRR0H = (unsigned char)(ubrr_value >> 8);
UBRR0L = (unsigned char)(ubrr_value & 255);
// Frame Format: asynchronous, no parity, 1 stop bit, char size 8
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
//Enable The receiver and transmitter
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
}

char USARTReadChar() { // blocking


while(!(UCSR0A & (1<<RXC0))) {}
return UDR0;
}

void USARTWriteChar(char data) { // blocking


while(!(UCSR0A & (1<<UDRE0))) {}
UDR0=data;
}
And of course the fuses are different for our 20 MHz clock than in ATtiny2313. I used lfuse of
FF and hfuse of DD. Before you proceed any further, I advice you to flash the ATmega88 with
the simple echo program from tutorial to see that the ATmega88 UART works as it should.
You can get that here.
Hardware note: If you don’t have a 3.3V capable MAX3232 or similar IC, but have a 3.3V
capable LCD, you could just replace the printout routines with LCD writes, and use switches as
inputs instead of a terminal program. Also, see my level shifting articleif you’d like to run
ATmega88 from 5V but SD card from 3.3V, the choice is yours!

Wiring the SD card to the project


For this project, you’ll need a empty SD card of 1 or 2 GB (smaller ones also OK) formatted to
FAT16 (Windows just says “FAT”, just do not select FAT32!). Copy a small text file
named README.TXT to the root folder. Note that the file needs to be in ALL CAPS, otherwise
it’ll not be found by our case-sensitive code later on. Also a microSD card will do, if you have
a adapter card or suitable connector (for example SparkFun sells several models). For wiring
the card to a breadboard, you have a few easy alternatives:
1. If you use a microSD card and have a spare SD adapter, just solder wires or pin header to it,
just like in this tutorial. Nice ad-hoc microSD breadboard adapter!
2. Even easier if you have a 2-row pin header, just place the SD card between the rows and tighten
with a piece of cardboard in the back, just like here
I chose option 2. I had some issues with some cards not responding to SPI, and I found out that
the code started working once I gently pushed the SD card towards the pins while the system
was operating – adding a thin paper in addition to the piece of cardboard fixed this, so if you
have communication problems, first try to add some stuffing!

Once you have means to plug the SD card to breadboard, you need to connect it to ATmega88.
You can see the pinout above. The GND and 3.3V pins are easy, just connect them to the
relevant power rails in the breadboard (remember: SD cards will likely be damaged if you
operate them at 5V). MISO, MOSI and SCK go to the matching ATmega88 pins. CS (Circuit
Select) is connected to the SS (Slave Select, essentially another name for the same thing) pin.
Unmarked pads are not connected to anything. See the full size article photo for an example SD
card wired to breadboard – white wire is MISO, yellow is SCK, green is MOSI and red is
CS/SS.
The SD card connected to ATmega88 SPI pins sometimes interferes with MCU
programming – if you get checksum errors with AVRdude, disconnect SD card, flash, and
connect the SD card again!

SPI communication with the SD card


The hardware is ready, but now we’ll need to develop some software to talk with the SD card.
If you have a Bus Pirate (I recently bought one, it’s really neat :), you could try it manually at
this point. Even if you don’t, I warmly recommend skimming through Nathan Dyer’s BusPirate
SD article, as it shows the four commands we need for talking with the SD card, as well as the
expected response. In BusPirate syntax, the commands are:
 Init and go to SPI mode: ]r:10 [0x40 0x00 0x00 0x00 0x00 0x95 r:8]
 Initialize card: [0x41 0x00 0x00 0x00 0x00 0xFF r:8]
 Set transfer size: [0x50 0x00 0x00 0x02 0x00 0xFF r:8]
 Read sector: [0x51 0x00 0x00 0x00 0x00 0xFF r:520]
The protocol used to communicate with the card is called SPI (Seriap Peripheral Interface). It’s
the same one that’s used to flash AVR chips. For our needs it’s enough to know that our
ATmega88 will be the “master” of the SPI bus, and the SD card will be the “slave”. To get the
slave to listen, we pull the Circuit Select (or Slave Select) line low, and start generating a clock
signal on the SCK line. Every clock beat, the master sends a bit using the MOSI (Master Out,
Slave In) wire, and the slave sends a bit using the MISO (Master In, Slave Out). This is
repeated eight times, after which a full byte has been transferred by both parties. When
communicating with a SD card, data that is received while sending can be ignored, and when
receiving data, the master should send all ones (0xFF as a byte).

If you want to learn more about SPI (and I recommend at least cursory look), I recommend you
to read the Wikipedia article on SPI. There’s some extra details like clock polarization and
phase that need to be the same for both master and slave, but knowing that the “out of the box”
setup of ATmega SPI hardware works with SD cards, we don’t need to consider them here.
The BusPirate syntax seen above is rather simple: “[” means that the CS line is activated
(pulled low) and “]” means the opposite (deactived / pulled high). A hex in SPI mode means
that hex is sent to the slave over SPI. “r” means a byte is read from the slave (while sending a
0xFF, because SPI operations always read and write at the same time). “:8” means the
command before it is repeated eight times, and it can be used for both read and write
operations. So the “Go to SPI mode” command actually does the following:

1. Pull CS high (deselect)


2. Read 10 bytes (basically sends CLK pulse 80 times to give SD card time to initialize)
3. Pull CS low (select)
4. Send 0x40 (“go to SPI mode” command, CMD0)
5. Send four zero bytes (SD protocol has 4-byte arguments)
6. Send 0x95, the CRC checksum of the command and argument just sent
7. Read eight bytes and print them out (while sending 0xFF to the card)
8. Pull CS high (deselect)
The steps 1-2 are unique in the start, and are not actually part of standard SD command syntax
– they just make sure the SD card receives 80 clock ticks before we send any commands. Not
so hard, wasn’t it? While the SD card is processing our command, it will reply with 0xFF and
once it’s ready, it’ll respond with 0x01. Then it’ll go back to sending 0xFF (the same byte
we’re sending to it while reading, by the way). So if you look at the BusPirate tutorial you’ll
see that a valid response of 8 bytes could be “0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF”.

If you want to learn more about the SD protocol, there’s a simplified specification
sheet available from SD Association without signing an NDA.

Utilizing the SPI hardware of ATmega88


I have some good news: The ATmega SPI hardware is very easy to use and understand.
Basically, we just need to set the MOSI, SCK and SS pins as outputs, and set some bits in SPI
control register, SPCR. See ATmega88 datasheet for details, this code is quite straight from
there (except MISO pullup, I added that just to be sure):

#define CS (1<<PB2)
#define MOSI (1<<PB3)
#define MISO (1<<PB4)
#define SCK (1<<PB5)
#define CS_DDR DDRB
#define CS_ENABLE() (PORTB &= ~CS)
#define CS_DISABLE() (PORTB |= CS)

void SPI_init() {
CS_DDR |= CS; // SD card circuit select as output
DDRB |= MOSI + SCK; // MOSI and SCK as outputs
PORTB |= MISO; // pullup in MISO, might not be needed

// Enable SPI, master, set clock rate fck/128


SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0) | (1<<SPR1);
}

unsigned char SPI_write(unsigned char ch) {


SPDR = ch;
while(!(SPSR & (1<<SPIF))) {}
return SPDR;
}
Note how I defined two macros, CS_ENABLE() and CS_DISABLE()that’ll take the CS line
low and high, respectively. Also, the SD SPI may not work on higher SPI clock frequencies so
a conservative divider of 128 is used instead of for example 16. Using the above
functions, ]r:10 becomes:
CS_DISABLE();
for(i=0; i<10; i++) // idle for 1 bytes / 80 clocks
SPI_write(0xFF);
Similarly, we can create a general function for executing a SD command like [0x40 0x00
0x00 0x00 0x00 0x95 r:8] – send a command byte, then argument dword, followed
by CRC byte and finally some reads:
void SD_command(unsigned char cmd, unsigned long arg,
unsigned char crc, unsigned char read) {
unsigned char i, buffer[8];

CS_ENABLE();
SPI_write(cmd);
SPI_write(arg>>24);
SPI_write(arg>>16);
SPI_write(arg>>8);
SPI_write(arg);
SPI_write(crc);

for(i=0; i<read; i++)


buffer[i] = SPI_write(0xFF);

CS_DISABLE();
// print out read bytes
}
Note that the “& 255” part after arg>>16 etc. can be omitted because SPI_write takes a
byte argument and any bits above the bottom 8 are truncated.
I added the above fragments of code to the USART test, and added a few printout commands
(uwrite_str for printing out strings over RS-232 and uwrite_hex for bytes in hex
format). I thought it would be nice to interact with the program manually for a change, so the
main loop just waits for “1”, “2” or “3” to be typed into terminal, and executes one of the
commands I mentioned above:
while(1) {
switch(USARTReadChar()) {
case '1':
SD_command(0x40, 0x00000000, 0x95, 8);
break;
case '2':
SD_command(0x41, 0x00000000, 0xFF, 8);
break;
case '3':
SD_command(0x50, 0x00000200, 0xFF, 8);
break;
}
}
I tried each of the commands – 1, 2, and 3 a few times. Here’s the output – if you check against
the BusPirate tutorial I linked above, we can see that it’s working! Download
the spi88.cyourself and flash it to try it out yourself:

As an excercise, you could already try adding a new function for the fourth command that will
read a sector from SD card. For this, you’ll just need to write the command 0x51 (read data)
with argument that is the data offset (start with 0 to dump the first sector) and CRC of 0xFF
(SPI mode does not check CRC so we always send 0xFF after setting the SPI mode…). After
that, instead of just reading 8 bytes, you read until you get 0x00 from SD card to indicate
command has been processed, and then wait for 0xFE to indicate data start. Then you just loop
for 512 bytes, printing them out as you go, and read additional two bytes (CRC).
In the next part of the tutorial, we’ll do this and more: Combine the FAT library to our SD
reading code to get a full-fledged SD reading library!

Finally, special thanks to Mark for his donation that I used to cover part of the BusPirate
purchase costs – this tutorial would’ve likely taken quite a while longer without the debugging
help I had from that tool!
Proceed to the next part of this tutorial

PUBLISHED BY

Joonas Pihlajamaa
Coding since 1990 in Basic, C/C++, Perl, Java, PHP, Ruby and Python, to name a few. Also
interested in math, movies, anime, and the occasional slashdot now and then. Oh, and I also
have a real life, but lets not talk about it! View all posts by Joonas Pihlajamaa
Posted onApril 25, 2012AuthorJoonas PihlajamaaCategoriesElectronicsTagsatmega88, sd, sd card,sd
pinout, spi, tutorial, uart

32 thoughts on “Simple FAT and SD Tutorial Part 3”

1. Martha Rodriguezsays:
April 27, 2012 at 16:54

Excellent tutorial. Thanks for shared it.


I just begin to follow this tutorial and I have a question. Using HxD, around address 0X1CE is
storaged the message: “remove disk or other media. Disk error. Press any key to restart”.
Can you help me to understand that?
Thanks.
REPLY
1. jokkebksays:
April 27, 2012 at 17:02

The MBR is also shared by boot code. For non-system disks, this commonly includes a short
program that displays an error if the user tries to boot from it. The message is part of that – not
that you would usually try to boot your computer from a SD card, but… :)
REPLY

1. Martha Rodriguezsays:
April 27, 2012 at 17:22

ok thanks. But, how I do view partition table entry, that is around 0x1BE if in that address show
this message. What am I doing bad?
REPLY

2. Martha Rodriguezsays:
April 27, 2012 at 17:48

Hi, My problem using HxD is that the block in my sd between 0x0000 and 0x 001FF is the
same in your file text.img between 0x10200 and 0x102FF. so I can`t partition table entry. What
can I do?
thanks.
REPLY

1. Martha Rodriguezsays:
April 27, 2012 at 18:12

ok, I just the problem, my sd doesn’t MBR, and in sector 0 I see the FAT16 for single partition.
REPLY

1. jokkebksays:
April 27, 2012 at 18:23

Yeah, some SD cards are initialized that way. You can then just skip the MBR reading
completely. :)
REPLY

3. Pingback: Simple FAT and SD Tutorial Part 4 » Code and Life


4. Pingback: Simple FAT and SD Tutorial Part 2 » Code and Life
5. Shobhitsays:
September 11, 2013 at 13:25

Great tutorial..did help me learn a lot about FAT file system. I am trying to test the SPI code
that you have provided on this page, but the result I am getting from serial port is all FF in
comparison to yours FF 01 FF. I have checked connections of my circuit but I am unable to get
my head around the response I am getting back.
REPLY

1. Joonas Pihlajamaasays:
December 9, 2013 at 23:52

I have vague recollection that sometimes when SD initialization did not “go through” it would
not return that 01 at all. Unfortunately I don’t remember what was wrong then, maybe I needed
to send some additional clocks, or acknowledge the sent bytes, or something. :-d
REPLY

6. nuttakornsays:
September 19, 2013 at 10:17

i want the code write txt. to sd card with avr(atmega128) or write pattern

best regard
REPLY

7. Ricksays:
February 6, 2014 at 06:28

I can’t get any response on USART when I tried to run

void SD_command(unsigned char cmd, unsigned long arg,


unsigned char crc, unsigned char read) {
unsigned char i, buffer[8];
usart_pstr("SD_command");
SD_CS_ASSERT;

SPI_transmit(cmd);
SPI_transmit(arg>>24);
SPI_transmit(arg>>16);
SPI_transmit(arg>>8);
SPI_transmit(arg);
SPI_transmit(crc);

for(i=0; i<read; i++)


buffer[i] = SPI_transmit(0xFF);

SD_CS_DEASSERT;

for(i=0; i<read; i++) {


usart_transmit(' ');
usart_write_hex(buffer[i]);
}
usart_pstr("\r \n");

// print out read bytes


}
REPLY

1. Joonas Pihlajamaasays:
February 6, 2014 at 10:28

Strange. Does your USART work outside of that function? You could try adding some debug
USART sends to the SD code so you can see if SD writing hangs at some point – the first thing
that popped to my mind was that maybe SD isn’t acknowledging the data and the code hangs
there.
REPLY

1. Ricksays:
February 6, 2014 at 12:45

Yes Usart is working, I tested on the first time program running, I used ATMEGA128
main :

#define SD_CS_ASSERT PORTB &= ~0x01


#define SD_CS_DEASSERT PORTB |= 0x01
#define CS (1<<PB0)
#define MOSI (1<<PB2)
#define MISO (1<<PB3)
#define SCK (1<<PB1)
#define CS_DDR DDRB
#define CS_ENABLE() (PORTB &= ~CS)
#define CS_DISABLE() (PORTB |= CS)
void port_init(void)
{
CS_DDR |= CS; // SD card circuit select as output
DDRB |= MOSI + SCK; // MOSI and SCK as outputs
PORTB |= MISO; // pullup in MISO, might not be needed

void spi_init(void)
{
SPCR = _BV(SPE)|_BV(MSTR)|_BV(SPR1)|_BV(SPR0);
SPSR &= ~_BV(SPI2X);
}

unsigned char SPI_transmit(unsigned char data)


{
// Start transmission
SPDR = data;

// Wait for transmission complete


while(!(SPSR & (1<<SPIF)));

return SPDR;
}
int main (void)
{
unsigned char option;
port_init();
spi_init();
usart_init(BAUD_PRESCALE);

usart_pstr("USART READY!");
while(1)
{
option = usart_receive();
switch(option)
{
case '1':
usart_pstr("1 command");
SD_command(0x40, 0x00000000, 0x95, 8);
break;
case '2':
SD_command(0x41, 0x00000000, 0xFF, 8);
usart_pstr("2 command");
break;
case '3':
SD_command(0x50, 0x00000200, 0xFF, 8);
usart_pstr("3 command");
break;
}

}
}

REPLY

1. Joonas Pihlajamaasays:
February 6, 2014 at 13:43

The approach sounds solid. Unfortunately I’ve forgotten most everything about SPI and SD
card communication since I wrote the tutorial two years ago, so you’ll probably have as much
luck as I with debugging the code. :( Maybe folks at AVRfreaks or similar electronics forum
might have something helpful.
REPLY

8. sergsays:
May 1, 2014 at 12:13

Hi, is it mandatory to read 8 bytes after sending SD command “r:8”? or do I just need to wait
for 0x01?
REPLY

1. Joonas Pihlajamaasays:
May 28, 2014 at 11:08

If I remember correctly, the SPI protocol works in a way that master device sends the clock, so
reading 8 bytes is required, otherwise the SD card won’t receive the clock cycles it is
expecting.
REPLY

9. Dsesesays:
August 25, 2014 at 09:55

Hi, this is a great blog. tutorial for sd.


i try your code in my atmega328 and when i run your code. i does not read the README.TXT.
rather.

CMD 40 FF 01 FF FF FF FF FF FF
CMD 41 FF 01 FF FF FF FF FF FF
CMD 41 FF 00 FF FF FF FF FF FF
CMD 50 FF 00 FF FF FF FF FF FF
FAT err: FF

i formatted my microsd to FAT which is the same to FAT16.

not sure why does not work?


REPLY

1. Joonas Pihlajamaasays:
August 25, 2014 at 13:34

Unfortunately my SD knowledge has largely evaporated in the past two years. However, I do
remember I had most problems getting the SPI to work properly, so most likely candidate
would be some problem with that (timings, levels, connections, contact with card..).

If you have a Bus pirate or similar, you could first try to get the card to respond to manual
commands, that’s what worked for me.
REPLY

1. Dsesesays:
August 25, 2014 at 18:38

Hi Joonas,

thank your for your quick response.

the atmega328 runs @16Mhz. so i adjust the F_CPU to 16000000

because i dont have 20MHz in my hand.

what do you think?


REPLY

1. Joonas Pihlajamaasays:
August 25, 2014 at 20:52

You might need to adjust the USARTinit magic value (UBRR or whatever) to match the new
baud rate too. USART is easier to debug though, as you can quickly see when you can or
cannot communicate over serial terminal with the device.
REPLY

1. Dsesesays:
August 26, 2014 at 09:52

i tried it, but it still didnt work output is still the same. do you think micro sd card will also
work on your code? i dont have SD card.

2. Joonas Pihlajamaasays:
August 26, 2014 at 11:29

MicroSD should have identical pin function, so no difference there.

10. Dsesesays:
August 26, 2014 at 15:46

Hi Joonas,

i actually do everything. such as fortmating the microsd to Fat16. and think your codes is
working. because when i remove the card. i get this “SD err”. then when put again the micro sd
card. i get it working. but it returns to Fat: err.. hmmm very confusing.
what is wrong then
REPLY

11. Pingback: Code and Life – Simple FAT and SD Tutorial Part 4 | kmestore DIY

12. QianFansays:
March 27, 2015 at 08:24

Hello:
I very like this web,it’s font,it’s color,and everything! Serials artical introduced me to learn SD
card and FAT format.
Sorry about my poor English,coming from a non-english county!
QianFan
Thank you!
REPLY

13. Julianosays:
May 3, 2015 at 18:11

Hello Friend! First I want to say thanks for the tutorial! I’m learning a lot …
I’m using an Atmega8 and a mini SD card with adapter, it will be stored some data from
sensors installed in the microcontroller to … I’m encountering an error FAT16 boot, more
precisely, the function “fat16_init ()” is launching an error: “” FAT err: FF “. I checked the
code, and in the file “fat16. c” the function “fat16_init ()” contains a sentry that keeps the
system startup file, in the following code snippet:

If (i == 4) {
None of the partitions were FAT16
return FAT16_ERR_NO_PARTITION_FOUND;
}

I did everything as you mentioned in the tutorial, I think … kkk


According to the error, my card does not contain partitions in the format “FAT16”. However, I
formatted the card and I created the image necessary. But it didn’t work! :/

The “sd_init()” performed with then!

Do you have any idea what is the problem?

Thanks buddy!
REPLY

1. Joonas Pihlajamaasays:
May 3, 2015 at 22:52

With larger cards, Windows might format them FAT32. Also, some cards have partitions and
some don’t. No concrete advice unfortunately from here, I’d look at the card data with a hex
editor like HxD and compare it against the FAT specs to see what is different.

You might also copy the raw data from SD card to disk image and run tests on the computer, so
you can separate possible SD reading issues and FAT issues from each other.
REPLY
14. Andrzejsays:
November 23, 2015 at 01:47

Hello,

Point 8 should be corrected.

8. Pull CS high (deselect)

Regards.
Andrzej
REPLY

1. Joonas Pihlajamaasays:
November 23, 2015 at 12:42

Thanks! It’s been so long since I wrote this so I’m just going to take your word for it, I don’t
know how CS became CD and high became low…
REPLY

15. Dinushasays:
January 24, 2016 at 09:55

This is great article. I am using atmega32 and rus at 8MHz . I change the code according that.
But when i input 1,2,3 to putty it doesn’t give any output. why? please help me.

#include

#define F_CPU 8000000L


#include

void USARTInit(unsigned int ubrr_value) {


//Set Baud rate
UBRRH = (unsigned char)(ubrr_value >> 8);
UBRRL = (unsigned char)(ubrr_value);
// Frame Format: asynchronous, no parity, 1 stop bit, char size 8
UCSRC = (3 << UCSZ0);
//Enable The receiver and transmitter
UCSRB = (1 << RXEN) | (1 << TXEN);
}
char USARTReadChar() { // blocking
while(!(UCSRA & (1<<RXC))) {}
return UDR;
}

void USARTWriteChar(char data) { // blocking


while(!(UCSRA & (1<>4) & 15) >4)&15));
else
USARTWriteChar(‘A’ + ((n>>4)&15) – 10);
n <>4) & 15) >4)&15));
else
USARTWriteChar(‘A’ + ((n>>4)&15) – 10);
}

void uwrite_str(char *str) {


char i;

for(i=0; str[i]; i++)


USARTWriteChar(str[i]);
}

#define CS (1<<PINB4)
#define MOSI (1<<PINB5)
#define MISO (1<<PINB6)
#define SCK (1<<PINB7)
#define CS_DDR DDRB
#define CS_ENABLE() (PORTB &= ~CS)
#define CS_DISABLE() (PORTB |= CS)

void SPI_init() {
CS_DDR |= CS; // SD card circuit select as output
DDRB |= MOSI + SCK; // MOSI and SCK as outputs
PORTB |= MISO; // pull up in MISO, might not be needed

// Enable SPI, master, set clock rate fck/128


SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0) | (1<<SPR1);
}

unsigned char SPI_write(unsigned char ch) {


SPDR = ch;
while(!(SPSR & (1<>24);
SPI_write(arg>>16);
SPI_write(arg>>8);
SPI_write(arg);
SPI_write(crc);
for(i=0; i<read; i++)
buffer[i] = SPI_write(0xFF);

CS_DISABLE();

for(i=0; i<read; i++) {


USARTWriteChar(' ');
uwrite_hex(buffer[i]);
}

uwrite_str("\r\n");
}

int main(int argc, char *argv[]) {


char i;

USARTInit(25); // 8 MHz / (16 * 19200 baud) – 1 = 25


SPI_init();

// ]r:10
CS_DISABLE();
for(i=0; i<10; i++) // idle for 1 bytes / 80 clocks
SPI_write(0xFF);

while(1) {
switch(USARTReadChar()) {
case '1':
SD_command(0x40, 0x00000000, 0x95, 8);
break;
case '2':
SD_command(0x41, 0x00000000, 0xFF, 8);
break;
case '3':
SD_command(0x50, 0x00000200, 0xFF, 8);
break;
}
}

return 0;
}
REPLY

1. Joonas Pihlajamaasays:
January 24, 2016 at 18:57
Thanks! Hard to say why the code does not work, unfortunately I cannot help in questions
(otherwise I’d be spending all my free time on that), so I suggest asking an electronics forum of
some kind.

What does the UCSRA & (1<>4) & 15) >4 type of code do? Looks really strange, or did
WordPress change something?
REPLY

Potrebbero piacerti anche