در این پروژه به شما نحوه اتصال برقرار کردن کارت حافظه SD را به میکروکنترلرهای AVR را آموزش خواهیم داد.
پایه ها و پورت های IO کارت حافظه SD
پایه | نام | عملکرد (حالت SD) | عملکرد (حالت SPI) |
1 | DAT3/CS | Data Line 3 | Chip Select/Slave (SS) |
2 | CMD/DI | Command Line | Mater Out Slave In (MOSI) |
3 | VSS1 | Ground | Ground |
4 | VDD | Supply Voltage | Supply Voltage |
5 | CLK | Clock | Clock (SCK) |
6 | VSS2 | Ground | Ground |
7 | DAT0/DO | Data Line 0 | Master In Slave Out (MISO) |
8 | DAT1/IRQ | Data Line 1 | Unused or IRQ |
9 | DAT2/NC | Data Line 2 | Unused |
مهم ترین دستورات کارت حافظه SD
دستور | Argument | نوع پاسخ به دستور | توضیحات |
CMD0 | None | R1 | کارت را به تنظیم مجدد و پیش فرض و حالت غیر فعال خود باز می گرداند. |
CMD16 | 32-bit Block Length | R1 | انتخاب طول بلوک |
CMD17 | 32-bit Block Address | R1 | خواندن یک بلوک |
CMD24 | 32-bit Block Address | R1 | نوشتن یک بلوک |
CMD55 | None | R1 | دستور بعدی مربوط به نرم افزار (ACMDXX) می باشد. |
CMD58 | None | R3 |
خواندن OCR (Operating Conditions Register) |
ACMD41 | None | R1 | مقداردهی اولیه |
مقداردهی اولیه کارت حافظه SD
این کار زمانی انجام می شود که کنترل SPI سیگنال ساعت به 400 کیلوهرتز تنظیم شود که این کار برای انجام به کارت های حافظه SD و MCC نیازمند می باشد. سپس دستور در CMD0 در زمانی که کارت وارد شده CS (در سطح L) ریست می شود. بایت CRC برای دستور CMD0 و دستور آرگیومنت صفر، به صورت 0x95 می باشد. دستور CMD58؛ برای مثال ما می خواهیم بررسی کنیم که آیا کارت حافظه می تواند از ولتاژ یکسان خود میکروکنترلر (بین 2.7 تا 3.6 ولت) استفاده کند یا نه.
بخش برنامه نویسی
ارتباط برقرار کردن کارت حافظه با میکرو
1 2 3 4 5 6 7 |
#define DI 6 // Port B bit 6 (pin7): data in (data from MMC) #define DT 5 // Port B bit 5 (pin6): data out (data to MMC) #define CLK 7 // Port B bit 7 (pin8): clock #define CS 4 // Port B bit 4 (pin5): chip select for MMC |
مقداردهی اولیه SPI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void ini_SPI(void) { DDRB &= ~(_BV(DI)); //input DDRB |= _BV(CLK); //outputs DDRB |= _BV(DT); //outputs DDRB |= _BV(CS); //outputs SPCR |= _BV(SPE); //SPI enable SPCR |= _BV(MSTR); //Master SPI mode SPCR &= ~(_BV(SPR1)); //fosc/16 SPCR |= _BV(SPR0); //fosc/16 SPSR &= ~(_BV(SPI2X)); //speed is not doubled PORTB &= ~(_BV(CS)); //Enable CS pin for the SD card } |
برنامه برای فرستادن یا دریافت کردن یک بایت از طریق SPI
1 2 3 4 5 6 7 8 9 10 11 12 13 |
char SPI_sendchar(char chr) { char receivedchar = 0; SPDR = chr; while(!(SPSR & (1<<SPIF))); receivedchar = SPDR; return (receivedchar); } |
برنامه برای فرستادن یک دستور فریم
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
char Command(char cmd, uint16_t ArgH, uint16_t ArgL, char crc ) { SPI_sendchar(0xFF); SPI_sendchar(cmd); SPI_sendchar((uint8_t)(ArgH >> 8)); SPI_sendchar((uint8_t)ArgH); SPI_sendchar((uint8_t)(ArgL >> 8)); SPI_sendchar((uint8_t)ArgL); SPI_sendchar(crc); SPI_sendchar(0xFF); return SPI_sendchar(0xFF); // Returns the last byte received } |
برنامه برای مقداردهی اولیه کارت حافظه
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
void ini_SD(void) { char i; PORTB |= _BV(CS); //disable CS for(i=0; i < 10; i++) SPI_sendchar(0xFF); // Send 10 * 8 = 80 clock pulses 400 kHz PORTB &= ~(_BV(CS)); //enable CS for(i=0; i < 2; i++) SPI_sendchar(0xFF); // Send 2 * 8 = 16 clock pulses 400 kHz Command(0x40,0,0,0x95); // reset idle_no: if (Command(0x41,0,0,0xFF) !=0) goto idle_no; //idle = L? SPCR &= ~(_BV(SPR0)); //fosc/4 } |
نوشتن بر روی کارت حافظه
در این برنامه اگر دستور به خطایی بر بخورد، به 1 و اگر به موفقیت انجام شود به 0 بر می گردد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
int write(void) { int i; uint8_t wbr; //Set write mode 512 bytes if (Command(0x58,0,512,0xFF) !=0) { //Determine value of the response byte 0 = no errors return 1; //return value 1 = error } SPI_sendchar(0xFF); SPI_sendchar(0xFF); SPI_sendchar(0xFE); //recommended by posting a terminator sequence [2] //write data from chars [512] tab uint16_t ix; char r1 = Command(0x58,0,512,0xFF); for (ix = 0; ix < 50000; ix++) { if (r1 == (char)0x00) break; r1 = SPI_sendchar(0xFF); } if (r1 != (char)0x00) { return 1; //return value 1 = error } //recommended by the control loop [2] SPI_sendchar(0xFF); SPI_sendchar(0xFF); wbr = SPI_sendchar(0xFF); //write block response and testing error wbr &= 0x1F; //zeroing top three indeterminate bits 0b.0001.1111 if (wbr != 0x05) { // 0x05 = 0b.0000.0101 //write error or CRC error return 1; } while(SPI_sendchar(0xFF) != (char)0xFF); //wait for the completion of a write operation to the card return 0; } |
خواندن از روی کارت حافظه
در این برنامه اگر دستور به خطایی بر بخورد، به 1 و اگر به موفقیت انجام شود به 0 بر می گردد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
int read(void) { int i; uint16_t ix; char r1 = Command(0x51,0,512,0xFF); for (ix = 0; ix < 50000; ix++) { if (r1 == (char)0x00) break; r1 = SPI_sendchar(0xFF); } if (r1 != (char)0x00) { return 1; } //read from the card will start after the framework while(SPI_sendchar(0xFF) != (char)0xFE); for(i=0; i < 512; i++) { while(!(SPSR & (1<<SPIF))); chars[i] = SPDR; SPDR = SPI_sendchar(0xFF); } SPI_sendchar(0xFF); SPI_sendchar(0xFF); return 0; } |
یک نمونه برنامه برای یادگیری بهتر
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <avr/io.h> #include <avr/iom16.h> #include <avr/interrupt.h> #define FOSC 6400000 char chars[512]; int main(void) { ini_SPI(); ini_SD(); sei(); write(); read(); return 0; } |
سلام
bv چیه؟؟؟؟؟؟؟؟؟