logo资料库

stm32驱动SDHC卡(SPI方式) 一.docx

第1页 / 共5页
第2页 / 共5页
第3页 / 共5页
第4页 / 共5页
第5页 / 共5页
资料共5页,全文预览结束
博客地址:http://blog.chinaaet.com/weiqi7777 stm32 驱动 SDHC 卡 (SPI 方式) 一 SD 卡是比较常见的存储设备了。SD 卡也有分类,按照容量有三类。 1、 SD 卡,小容量的卡。容量小于 2G。现在用得比较少了。 2、 SDHC 卡。中容量的卡,容量大于 2G,小于 32G。目前用得普遍。 3、 SDXC 卡。大容量的卡,容量大于 32G。 不同的卡,使用的协议标准是不一样的。小容量的 SD 卡,用的是 SD1.0 的标准。而中 容量的 SD 卡。用的是 SD2.0 的标准。至于大容量,没有研究,不清楚。 手里面有一个 8G 的 SD 卡,属于中容量。所以以下内容都是关于中容量 SD 卡,即使用 标准 SD2.0。 SD 卡的传输模式有两种,一种是 SDIO 模式,一种是 SPI 模式。两种模式区别在于协议 不一样而已。这里用的是 SPI 模式。 其实 SD 的驱动还是比较简单的。就是向 SD 卡发各种命令,然后接受命令判断。最后 在发数据,读数据。 首先说下 SD 卡命令格式。 SD 卡的指令由 6 字节(Byte)组成,如下: Byte1:0 1 x x x x x x(命令号,由指令标志定义,如 CMD39 为 100111 即 16 进制 0x27, 那么完整的 CMD39 第一字节为 01100111,即 0x27+0x40) Byte2-5:Command Arguments,命令参数,有些命令没有参数 Byte6:前 7 位为 CRC(Cyclic Redundacy Check,循环冗余校验)校验位,最后一位为停止位 0. 这里如果是用 SPI 模式的话,CRC 效验是不重要的,即什么都可以(我设置为 0xff)。除 了 CMD0.CMD0 的 CRC 是一定要正确的。 SD 卡的命令非常的多,在不同的时候就要发送不同的命令。命令是很多,但是有很多 我们都用不上,经常用的有 CMD0,CMD8,CMD55,ACMD41 和读取和写入的命令 SD 卡命令共分为 12 类,分别为 class0 到 class11 Class0 :(卡的识别、初始化等基本命令集) CMD0:复位 SD 卡.
博客地址:http://blog.chinaaet.com/weiqi7777 CMD1:读 OCR 寄存器. CMD9:读 CSD 寄存器. CMD10:读 CID 寄存器. CMD12:停止读多块时的数据传输 CMD13:读 Card_Status 寄存器 Class2 (读卡命令集): CMD16:设置块的长度 CMD17:读单块. CMD18:读多块,直至主机发送 CMD12 为止 . Class4(写卡命令集) : CMD24:写单块. CMD25:写多块. CMD27:写 CSD 寄存器 . Class5 (擦除卡命令集): CMD32:设置擦除块的起始地址. CMD33:设置擦除块的终止地址. CMD38: 擦除所选择的块. Class6(写保护命令集): CMD28:设置写保护块的起始地址. CMD29:设置写保护块的结束地址. CMD30: Ask the card for the status of the write protection bits 命令的传输过程采用发送应答机制,过程如下:
博客地址:http://blog.chinaaet.com/weiqi7777 我们就是通过响应来判断发送命令是否成功的,每个命令都有自己的响应。但是该响应 一定不是 0xff。所以我们只要判断响应不是 0xff 的话,就说明有响应了。 先来个命令的时序图。 这是复位的时序图。 前面的 74 个时钟这里不用关心。 对于发送命令。从时序图可以看出,首先拉低 CS。然后通过 SPI 发送命令,即 6 字节数 据。发送完成后,就一直接受响应。当响应为 0x01(这里的响应,不同命令响应不一样)。 就说明发送命令成功。然后在拉高 CS。注意,拉高 CS 后,要额外多发送 8 个时钟,为了通 信的可靠。也可以把这 8 个时钟放在最前面 CS 拉低之前也行。 弄清楚了时序图,那写代码就很简单了。 //向 SD 中发送一个命令 //输入参数 1 为命令 //输入参数 2 为命令的参数 //输入参数 3 为命令的 CRC //返回值是命令的响应 uint8_t { SD_write_command(uint8_t command, uint32_t uint8_t retry=0; uint8_t response; //取消上次片选 SPI_CS_HIGH(); spi_write_byte(0xff); //发送 8 个时钟脉冲 //使能片选 SPI_CS_LOW(); command = command | 0x40; //发送命令 arg, uint8_t crc)
博客地址:http://blog.chinaaet.com/weiqi7777 spi_write_byte(command); spi_write_byte((uint8_t)((arg&0xff000000)>>24)); spi_write_byte((uint8_t)((arg&0x00ff0000)>>16)); spi_write_byte((uint8_t)((arg&0x0000ff00)>>8)); spi_write_byte((uint8_t)((arg&0x000000ff))); spi_write_byte(crc); //读取响应 do { response = spi_write_byte(0xff); retry++; if(retry == 200) return RESPONSE_OVER_TIME; }while( (response == 0xff) ); return response; } 这代码一看就可以看懂了。这里要注意的是因为命令的第二位一定要为 1 ,所以对于 发送的命令需要和 0x40 或一下。保证第二位为 1。 其次为了避免一直接受不到响应信号,就死在循环里面了。所以要设置一个变量来计数, 当计数超过范围,就认为接受响应超时。就退出循环。把超时响应返回,这样调用的函数在 进行处理。当接收响应不是 0xff 时,就说明接收响应成功,然后将该响应返回即可。 spi_write_byte(byte)这个函数就是通过 SPI 协议发送一个字节数据,同时返回接收到 的一个字节数据。 这里采用的是 IO 模拟的方式。 uint8_t spi_write_byte(uint8_t byte) { uint8_t temp=0; uint8_t i; for(i=0x80; i!=0; i=i>>1) { temp <<= 1; sd_spi_clk_low(); //拉低 clk //准备好发送的数据 if((byte & i) != 0 ) sd_spi_do_high(); else sd_spi_do_low(); if(sd_reset_flag) //如果是复位,clk 时钟不能超过 400K delay_us(10); else delay_us(1); sd_spi_clk_high(); //拉高 clk __NOP(); __NOP();
博客地址:http://blog.chinaaet.com/weiqi7777 __NOP(); if(sd_spi_di() == 1) temp |= 0x01; if(sd_reset_flag) //如果是复位,clk 时钟不能超过 400K delay_us(10); else delay_us(1); } sd_spi_do_high(); return temp; } 这里就注意一下,如果是在复位的时候,SPI 的时钟不能太快,就需要延时久一点。如 果不是在复位的时候,SPI 的时钟就可以快一点,就不用延时那么久。 底层的函数就这么两个,剩下的就是利用这两个函数来完成这个 SDHC 卡的驱动程序。
分享到:
收藏