SD_CS/ 连接到单片机的片选SD管脚,只有单片机设置SD_CS/为低电平时才可以操作SD卡。 MOSI连接单片机SPI总线的MOSI管脚(SPI数据 输入),单片机从这个管脚读取SD卡内的数据。
MISO连接单片机SPI总线的MISO管脚(SPI数据输出)、单片机通过这个管脚向SD卡内写 入数据。
SCK连接单片机SPI总线的SCK(SPI时钟)
SD管脚实际上在SD卡内部连接到了GND,当SD插座上没插入SD卡时,单 片机从这个管脚能读到高电平(前提是使用单片机内部上拉输入,或者外部增加一个上拉电阻),一旦插入SD卡,这个管脚就变成低电平,这个功能用来检测是否 插入SD卡。 RSV1和RSV2是保留功能管脚,不需要操作。
MicroSD卡的连接和SD卡大同小异,只是MicroSD卡比SD卡少 一个GND管脚,所以不能使用上面做的这种插入卡的检测,实际上现在很多SD卡/MicroSD卡插座都有插入检测管脚,当然,一分钱一分货,价格上当然 也要贵一些 顺便提一下,普通SD卡插座最多5块钱。
SPI命令格式
Byte 1 7 0
6 1
5 0
Command
Byte2-5
31 0
Command Argument
Byte 6 7 CRC
0 1
以下是一个简单的测试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
6
#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<
#define SD_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_L
7
SD_TEST.C
//****************************************************************************************/ //ICC-AVR 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 rate UCSR0A = 0x00;
UCSR0C = 0x06; // 00000110 UART0设置为异步模式、无奇偶校验、1位停止位、8位数据位 UBRR0L = 0x17; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi 设置UART0口通信速率9600 UCSR0B = 0x18; }
void putchar(unsigned char content) {
while(!(UCSR0A & (1 << UDRE0))); /* 判断上次发送有没有完成 */ UDR0 = content; /* 发送数据 */
8
}
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个以上的时钟
9
}
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=\//发送初始化命令 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卡
10