基于Atmega128单片机SD卡读写程序实物图对照接线图以下是一个简单的测试SD卡读写的程序,程序是基于Atmega128单片机编写的,对于Atmega的其他单片机仅需要做管脚改动就可以使用,其他单片机更改要更大。
sd.h//********************************************************** ********//SPI各线所占用的端口#define SD_SS PB6#define SD_SCK PB1#define SD_MOSI PB2#define SD_MISO PB3//********************************************************** ********#define SD_DDR DDRB#define SD_PORT PORTB#define SD_PIN PINB#define SD_SS_H SD_PORT |= (1<#define SDSS_L SD_PORT &= ~(1<#define SD_SCK_H SD_PORT |= (1<#define SD_SCK_L SD_PORT &= ~(1<#define SD_MOSI_H SD_PORT |= (1<#define SD_MOSI_L SD_PORT&= ~(1<#defineSD_MISO_IN (SD_PIN&(1<//-------------------------------------------------------------// 错误号//-------------------------------------------------------------#define INIT_CMD0_ERROR 0xFF#define INIT_CMD1_ERROR 0xFE#define WRITE_BLOCK_ERROR 0xFD#define READ_BLOCK_ERROR 0xFC#define TRUE 0x01//-------------------------------------------------------------// MMC/SD 命令(命令号从40开始,只列出基本命令,并没有都使用) //-------------------------------------------------------------#define SD_RESET 0x40 + 0#define SD_INIT 0x40 + 1#define SD_READ_CSD 0x40 + 9#define SD_READ_CID 0x40 + 10#define SD_STOP_TRANSMISSION 0x40 + 12#define SD_SEND_STATUS 0x40 + 13#define SD_SET_BLOCKLEN 0x40 + 16#define SD_READ_BLOCK 0x40 + 17#define SD_READ_MULTI_BLOCK 0x40 + 18#define SD_WRITE_BLOCK 0x40 + 24#define SD_WRITE_MULTI_BLOCK 0x40 + 25//片选关(MMC/SD-Card Invalid)#define SD_Disable() SD_SS_H//片选开(MMC/SD-Card Active)#define SD_Enable() SD_SS_LSD_TEST.C//********************************************************** ******************************///ICC-A VR application builder : 03-5-20 8:39:11// Target : M128// Crystal: 3.6864Mhz#include#include#include 'sd.h'void uart0_init(void);void putchar(unsigned char content);void putstr(unsigned char *s);void SD_Port_Init(void);unsigned char SD_Init(void);unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer);unsigned char SD_read_sector(unsigned long addr,unsigned char *Buffer);unsigned char SPI_TransferByte(unsigned char byte);unsigned char Write_Command_SD(unsigned char cmd,unsigned long address);unsigned long SD_find(void);//********************************************************** ****************//串口调试程序//********************************************************** ****************void uart0_init(void){UCSR0B = 0x00; //disable while setting baud rateUCSR0A = 0x00;UCSR0C = 0x06; // 00000110 UART0设置为异步模式、无奇偶校验、1位停止位、8位数据位UBRR0L = 0x17; //set baud rate loUBRR0H = 0x00; //set baud rate hi 设置UART0口通信速率9600 UCSR0B = 0x18;}void putchar(unsigned char content){while(!(UCSR0A & (1 << UDRE0))); /* 判断上次发送有没有完成*/UDR0 = content; /* 发送数据*/}void putstr(unsigned char *s){while(*s){putchar(*s);s++;}}//********************************************************** ******************//端口初始化void SD_Port_Init(void)//********************************************************** ******************{SD_PORT |= (1< SD_DDR |= (1< SD_ DDR &= ~(1<}//********************************************************** ******************//初始化MMC/SD 卡为SPI模式unsigned char SD_Init(void)//********************************************************** ******************{unsigned char retry,temp;unsigned char i;SPCR=0x53; //设定SPI为128分频,慢速进行初始化SPSR=0x00;for (i=0;i<0x0f;i++){SPI_TransferByte(0xff); //延迟74个以上的时钟}SD_Enable(); //开片选SPI_TransferByte(SD_RESET); //发送复位命令SPI_TransferByte(0x00);SPI_TransferByte(0x00);SPI_TransferByte(0x00);SPI_TransferByte(0x00);SPI_TransferByte(0x95);SPI_TransferByte(0xff);SPI_TransferByte(0xff);retry=0;do{temp="Write"_Command_SD(SD_INIT,0); //发送初始化命令retry++;if(retry==100) //重试100次{SD_Disable(); //关片选return(INIT_CMD1_ERROR); //如果重试100次失败返回错误号}}while(temp!=0);MSD_Disable(); //关片选SPCR=0x50; //设置SPI为2分频。
进行高速读写SPSR=0x01;return(TRUE); //返回成功}//********************************************************** ******************//发送命令给MMC/SD卡//Return: 返回MMC/SD卡对命令响应的第2字节,作为命令成功判断unsigned char Write_Command_SD(unsigned char cmd,unsigned long address)//********************************************************** ******************{unsigned char tmp;unsigned char retry="0";SD_Disable();SPI_TransferByte(0xFF);SD_Enable();SPI_TransferByte(cmd); //将32位地址进行移位作为地址字节SPI_TransferByte(address>>24);SPI_TransferByte(address>>16);SPI_TransferByte(address>>8);SPI_TransferByte(address);SPI_TransferByte(0xFF);SPI_TransferByte(0xFF);do{tmp = SPI_TransferByte(0xFF); //发送8个时钟接受最后一个字节retry++;}while((tmp==0xff)&&(retry<8));return(tmp);}//********************************************************** ******************//写一个扇区(512Byte) to MMC/SD-Card//如果写完成返回TRUEunsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer)//********************************************************** ******************{unsigned char temp;unsigned int i;SPI_TransferByte(0xFF); //延迟8个时钟SD_Enable(); //开片选temp = Write_Command_MMC(MMC_WRITE_BLOCK,addr<<9); //发送写扇区命令if(temp != 0x00){SD_Disable();return(temp);}SPI_TransferByte(0xFF);SPI_TransferByte(0xFF);SPI_TransferByte(0xFE);for (i=0;i<512;i++){SPI_TransferByte(*Buffer++); //发送512字节数据}//CRC-ByteSPI_TransferByte(0xFF); //Dummy CRCSPI_TransferByte(0xFF); //CRC Codetemp = SPI_TransferByte(0xFF); //读SD卡运行响应if((temp & 0x1F)!=0x05) //如果最后4位为0101,为操作成功。