
2011-03-28 17:45转载自 sail_007最终编辑 sail_007 最近开始整理以前画过原理图和程序今天先整理出了SD卡的硬件和SPI方式的读写程序。今后会陆续写把DS1302时钟芯片GPRS模块CAN总线通信PWM数控电压也整理出来。一方面是想帮自己总结一下另外如果还能帮助到其他的单片机爱好者那也就更好了。当然水平有限整理出来的东西可能也有许多错误的地方也请高手能指出不胜感激。 先发张SD卡的原理图。说明我用的是5V单片机SD卡则是3.3v如果直接连接引脚长期使用会影响SD卡寿命。我一开始选用了普通的光耦触发可能是导通速率不够快无法实现SPI通信后来我就改用9013就行了。 下图上US1是SD卡壳其实1到9引脚对应了SD卡的9个引脚10号引脚是卡插入标志也就是说当有SD卡插入时10号引脚会接3.3v的地这样单片机就可以查询是否有卡了。在SPI总线模式下CS为主控制器向卡发送的片选信号SCLK为主控制器向卡发送的时钟信号INDataIn为主控制器向卡发送的单向数据信号MISODataOut为卡向主控制器发送的单向数据信号。 程序如下说明我用的是freescale的DP256单片机该单片机有SPI设备接口只要将其初始化成功便可完成通信设置。 uchar CMD0RespCMD1RespCMD59RespCMD16RespCMD9RespCMD17RespCMD24RespCMD58Resp void SD_Initializevoid uchar csdbuf16TempValue uchar cmdparam4recbuf600resp4resptype uchar sendbuf600 ulong len ulong i ulong BlockAdd SD_InsertDetect Pim.pts.bit.pts70 //cs0 SD_SPIDelay25 Pim.pts.bit.pts71 //cs1 SD_SPIDelay2 Pim.ddrs.bit.ddrs70 //pin cs direction Spi0.spicr1.bit.spe0 //spi enable Pim.ddrs.bit.ddrs71 //pin cs direction Pim.pts.bit.pts70//cs0 Spi0.spibr.byte0x02 //8MHz31.25kHz 0x07-0x00 Spi0.spicr1.bit.mstr1 //master mode Spi0.spicr1.bit.ssoe1 //ss output enable Spi0.spicr1.bit.cpol0 //cpol0 //cpol1 070215 Spi0.spicr1.bit.cpha0 //cpha0 Spi0.spicr2.byte0x18 //normal drive input pullup TempValueSpi0.spisr.byte//clear SPIF first step TempValueSpi0.spidr.byte//clear SPIF second step Spi0.spicr1.bit.spe1 //spi enable CMD0RespSD_ResetSD CMD1RespSD_ActiveInit whileCMD1Resp0x01 CMD1RespSD_ActiveInit 白开水易拉罐主页博客相册个人档案好友i贴吧看看Ta是谁吧页码1/5Ww2011/6/26http://hi.baidu.com/wolf9s/blog/item/47e2a620212d80268744f98c.htmlvoid SD_SPIDelayuint value uint i for i 0 i valuei SPI_SendByte0xFF // 发送0xFF clock out 0xFF uchar SD_ResetSDvoid uchar param4 0000resp SD_SendCmdCMD0 param SD_R1 resp return resp / 函数名称: void SPI_SendByte Name: void SPI_SendByte 功能描述: 通过SPI接口发送一个字节 Function: send a byte by SPI interface 输 入: INT8U byte: 发送的字节 Input: INT8U byte: the byte that will be send 输 出: 无 Output: NULL / void SPI_SendByteuchar byte uchar TempValue Spi0.spidr.byte byte / 发送数据放入SPI数据寄存器 / while0 Spi0.spisr.byte 0x80 / 等待SPIF置位即等待数据发送完毕 / / wait for SPIF being set that is wait for finishing of data being send / TempValue Spi0.spidr.byte / 函数名称: INT8U SPI_RecByte Name: INT8U SPI_RecByte 功能描述: 从SPI接口接收一个字节 Function: receive a byte from SPI interface 输 入: 无 Input: NULL 输 出: 收到的字节 Output: the byte that be received / uchar SPI_RecBytevoid uint ReadCounter ReadCounter0 Spi0.spidr.byte 0xFF while0 Spi0.spisr.byte 0x80 / 等待SPIF置位即等待收到数据 / ReadCounter ifReadCounter25 break / wait for SPIF being set that is wait for being received data / returnSpi0.spidr.byte / 读取收到的字节 read the byte received / / 函数名称: //INT8U SD_SendCmd Name: INT8U SD_SendCmd 功能描述: 向卡发送命令并取得响应 Function: send command to the cardand get a response 输 入: INT8U cmd : 命令字 Input: INT8U cmd : command byte INT8U param : 命令参数长度为4字节 INT8U param : command parameterlength is 4 bytes INT8U resptype : 响应类型 INT8U resptype: response type INT8U resp : 响应长度为1-5字节 INT8U resp : responselength is 1-5 bytes 输 出: 0: 正确 0: 错误码 Output: 0: right 0: error code / void SD_SendCmduchar cmd uchar paramuchar resptype uchar resp long irlen uchar tmp Pim.pts.bit.pts70//cs0 SPI_SendBytecmd 0x3F 0x40 / 发送命令头和命令字 send command header and word / for i 3 i 0 i-- SPI_SendByteparami / 发送参数 send parameters / SPI_SendByte0x95 / CRC校验码只用于第1个命令 CRConly used for the first command / rlen 0 switch resptype / 根据不同的命令得到不同的响应长度 / / according various commandget the various response length / case 1: rlen 1 break case 2: rlen 2 break case 4: rlen 5 break default: SPI_SendByte0xFF Pim.pts.bit.pts71 break i 0 do / 等待响应响应的开始位为0 / / Wait for a responsea response is a start bitzero / tmp SPI_RecByte i while tmp 0x80 0 i SD_CMD_TIMEOUT for i rlen - 1 i 0 i-- respi tmp tmp SPI_RecByte / 循环的最后发送8clock at the last recycleclock out 8 clock / Pim.pts.bit.pts71//cs1 // return SD_NO_ERR //new statement 页码2/5Ww2011/6/26http://hi.baidu.com/wolf9s/blog/item/47e2a620212d80268744f98c.html/ 函数名称: INT8U SD_ReadBlock Name: INT8U SD_ReadBlock 功能描述: 从SD卡中读一个块 Function: read a single block from sd card 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: address of block INT8U recbuf : 接收缓冲区长度512Bytes INT8U recbuf : the buffer of receivelength is 512Bytes 输 出: 0: 正确 0: 错误码 Output: 0: right 0: error code / uchar SD_ReadBlockulong blockaddr uchar recbuf uchar param4resp // if blockaddr sds.block_num // return SD_ERR_OVER_CARDRANGE / 操作超出卡容量范围 operate over the card range / SD_PackParamparam blockaddr / 将参数转化为字节形式 change the parameter to bytes form / SD_SendCmdCMD17 param SD_R1 resp SD_ReadBlockDataSD_BLOCKSIZE recbuf/ 读出数据 read data from sd card / return resp / 函数名称: INT8U SD_ReadBlockData Name: INT8U SD_ReadBlockData 功能描述: 从SD卡中读取数据块 Function: read block data from sd card 输 入: INT32U len : 长度 Input: INT32U len : length INT8U recbuf : 接收缓冲区 INT8U recbuf : the buffer of receive 输 出: 0: 正确 0: 错误码 Output: 0: right 0: error code / void SD_ReadBlockDataulong len uchar recbuf uchar tmp ulong i 0 Pim.pts.bit.pts70//cs0 do / 等待接收数据开始令牌0xFE wait for receiving data start token 0xFE / tmp SPI_RecByte i whiletmp 0xFF i SD_CMD_TIMEOUT for i 0 i len i recbufi SPI_RecByte / 接收数据 receive data / i SPI_RecByte i i 0: 错误码 Output: 0: right 0: error code uchar SD_SetBlockLenulong length uchar param4respret SD_PackParamparam length //将参数转化为字节形式 change the parameter to bytes form SD_SendCmdCMD16 param SD_R1 resp return resp / / 函数名称: void SD_PackParam Name: void SD_PackParam 功能描述: 将32位的参数转为字节形式 Function: change 32bit parameter to bytes form 输 入: INT8U parameter: 字节参数缓冲区 Input: INT8U parameter: the buffer of bytes parameter INT32U value : 32位参数 INT32U value : 32bit parameter 输 出: 无 Output: NULL / void SD_PackParamuchar parameter ulong value valuevalue512 parameter3 ucharvalue 24 parameter2 ucharvalue 16 parameter1 ucharvalue 8 parameter0 ucharvalue / 函数名称: INT8U SD_WriteBlock Name: INT8U SD_WriteBlock 功能描述: 向SD卡中写入一个块 Function: write a block to sd card 输 入: INT32U blockaddr: 块地址 Input: INT32U blockaddr: address of block INT8U sendbuf : 发送缓冲区长度512Bytes INT8U sendbuf : the buffer of sendlength is 512Bytes 输 出: 0: 正确 0: 错误码 Output: 0: right 0: error code / uchar SD_WriteBlockulong blockaddr uchar sendbuf 页码3/5Ww2011/6/26http://hi.baidu.com/wolf9s/blog/item/47e2a620212d80268744f98c.html uchar param4resprettmp2 ulong i // if blockaddr sds.block_num // return SD_ERR_OVER_CARDRANGE / 操作超出卡容量范围 operate over the card range / SD_PackParamparam blockaddr / 将参数转化为字节形式 change the parameter to bytes form / SD_SendCmdCMD24 param SD_R1 resp / 写单块命令 write single block / SD_WriteBlockData0 SD_BLOCKSIZE sendbuf / 写入数据 write data / return resp / 函数名称: INT8U SD_WriteBlockData Name: INT8U SD_WriteBlockData 功能描述: 向sd卡写数据块 Function: write block data to sd card 输 入: INT8U bmulti : 是否为多块操作1:是0:否 Input: INT8U bmulti : multi blocks operate 1:Y 0:N INT32U len : 长度 INT32U len : length INT8U sendbuf: 发送缓冲区 INT8U sendbuf : the buffer of send 输 出: 0: 正确 0: 错误码 Output: 0: right 0: error code / void SD_WriteBlockDatauchar bmulti ulong len uchar sendbuf uint i uchar tmp Pim.pts.bit.pts70//cs0 SPI_SendByte0xFF / 开始发送数据之前发送8个clock clock out 8 clk before start / if bmulti 1 SPI_SendByteSD_TOK_WRITE_STARTBLOCK_M / 写多块开始令牌 start token of write multi blocks / else SPI_SendByteSD_TOK_WRITE_STARTBLOCK / 写单块开始令牌 start token of write single block / for i 0 i len i SPI_SendBytesendbufi / 发送数据 send data / SPI_SendBytei 8 0xFF SPI_SendBytei 0xFF / 发送CRC16校验码 send CRC16 check code / tmp SPI_RecByte Pim.pts.bit.pts71//cs1 SD_WaitBusy void SD_WaitBusy uchar tmpi Pim.pts.bit.pts70//cs0 i0 do / 等待忙结束 wait for being busy end / tmp SPI_RecByte i while tmp 0xFF i 10000 / 忙时收到的值为0xFF always receive 0xFF when card is busy / Pim.pts.bit.pts71//cs1 / 函数名称: void SD_HardWareInit Name: void SD_HardWareInit 功能描述: 初始化访问SD卡的硬件条件 Function: initialize the hardware condiction that access sd card 输 入: 无 Input: NULL 输 出: 无 Output: NULL / uchar SD_InsertDetect uchar Inflag ifPim.ptp.bit.ptp30//sd insert Inflag1 else Inflag0 return Inflag 类别默认分类 添加到搜藏 分享到i贴吧 浏览57 评论 0 上一篇sd卡的读写转 下一篇一般SD卡和SDHC卡读写函数 .c -... 最近读者 网友评论发表评论姓 名哦没他发 内 容插入表情▼ 闪光字页码4/5Ww2011/6/26http://hi.baidu.com/wolf9s/blog/item/47e2a620212d80268744f98c.html 同时将此文章分享给好友验证码 请点击后输入四位验证码字母不区分大小写 发表评论 �0�82011 Baidu看看Ta是谁吧页码5/5Ww2011/6/26http://hi.baidu.com/wolf9s/blog/item/47e2a620212d80268744f98c.html
