完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
[导读]SD卡一般支持两种读写模式,SPI和SDIO模式,SD卡的引脚排序如下图所示。SPI模式下有几个重要的操作命令,分别是:SD卡R1回应的格式如下SPI模式下的典型初始化过程如下:1、初始化硬件配置,SPI配置,IO配置等。SD卡一般支持两种读写模式,SPI和SDIO模式,SD卡的引脚排序如下图所示。 SPI模式下有几个重要的操作命令,分别是: SD卡R1回应的格式如下 SPI模式下的典型初始化过程如下: 1、初始化硬件配置,SPI配置,IO配置等。SPI模式下的典型读取数据的过程(这里采用CMD17来实现)如下 1、发送CMD17。SPI模式下的典型写数据的过程(这里采用CMD24来实现)如下 1、发送CMD24。具体代码实现如下。 /******************************************************************************* * Function Name : SPI_FLASH_Init * Description : Initializes the peripherals used by the SPI FLASH driver. * Input : None * Output : None * Return : None *******************************************************************************/ void SPI_SD_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能SPI对应引脚的时钟 使能SPI1的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); /*配置SPI的时钟线SCK和SPI的MOSI线和SPI的MISO线 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能的推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); /*配置SPI的片选线:CSN */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); /* 拉高CSN引脚,停止使能SD*/ GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_8); GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); // 配置SPI,使它适合SD的特性 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主器件 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位数据长度 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟悬空时为高 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第2个时钟沿 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由外部管脚管理 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//波特率预分频值为4 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输的第一个字节为MSB SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC的多项式 SPI_Init(SPI1, &SPI_InitStructure); /* 使能SPI1 */ SPI_Cmd(SPI1, ENABLE); } /******************************************************************************* * Function Name : SPI_FLASH_SendByte * Description : 发送一个数据,同时接收从FLASH返回来的数据 * Input : byte : byte to send. * Output : None * Return : The value of the received byte. *******************************************************************************/ u8 SPIx_ReadWriteByte(u8 byte) { /* 等待数据发送寄存器清空 */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /* 通过SPI发送出去一个字节数据 */ SPI_I2S_SendData(SPI1, byte); /* 等待接收到一个数据(接收到一个数据就相当于发送一个数据完毕) */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* 返回接收到的数据 */ return SPI_I2S_ReceiveData(SPI1); } /******************************************************************************* * Function Name : SPI_FLASH_SendHalfWord * Description : 发送并接受一个半字数据(16位) * Input : Half Word : Half Word to send. * Output : None * Return : The value of the received Half Word. *******************************************************************************/ u16 SPIx_ReadWriteHalfWord(u16 HalfWord) { /* 等待数据发送寄存器清空 */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /* 通过SPI发送出去半个字的数据 */ SPI_I2S_SendData(SPI1, HalfWord); /* 等待接收到一个半字数据(接收到一个数据就相当于发送一个数据完毕) */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* 返回接收到的数据 */ return SPI_I2S_ReceiveData(SPI1); } //SPI 速度设置函数 //SpeedSet: //SPI_BaudRatePrescaler_2 2分频 (SPI36M@sys72M) //SPI_BaudRatePrescaler_8 8分频 (SPI9M@sys72M) //SPI_BaudRatePrescaler_16 16分频 (SPI4.5M@sys72M) //SPI_BaudRatePrescaler_256 256分频 (SPI281.25K@sys72M) void SPIx_SetSpeed(u8 SpeedSet) { SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1,ENABLE); } /******************************END OF INIT_SPI*****************************/ /******************************START OF SD_OPERATION***********************/ /******************************************************************************* * 函数名称 : SD_Select * 功能描述 : 选择SD卡,并等待SD卡准备好 * 进入参数 : 无. * 返回参数 : 0:成功 1:失败 * 备注说明 : SD卡准备好会返回0XFF *******************************************************************************/ u8 SD_Select(void) { uint32_t t=0; SD_CS(OFF);//片选SD,低电平使能 do { if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK t++; }while(t<0XFFFFFF);//等待 SD_DisSelect(); //释放总线 return 1;//等待失败 } /******************************************************************************* * 函数名称 : SD_RecvData * 功能描述 : 从sd卡读取一个数据包的内容 * 进入参数 : buf:数据缓存数组 len要读取的数据的长度 * 返回参数 : 0:成功 其他:失败 * 备注说明 : 读取时需要等待SD卡发送数据起始令牌0XFE *******************************************************************************/ u8 SD_RecvData(u8*buf,u16 len) { u16 Count=0xF000;//等待次数 while ((SD_SPI_ReadWriteByte(0XFF)!=0xFE)&&Count)Count--;//等待得到读取数据令牌0xfe if (Count==0) return MSD_RESPONSE_FAILURE;//获取令牌失败,返回0XFF while(len--)//开始接收数据 { *buf=SPIx_ReadWriteByte(0xFF); buf++; } //下面是2个伪CRC(dummy CRC),假装接收了2个CRC SD_SPI_ReadWriteByte(0xFF); SD_SPI_ReadWriteByte(0xFF); return 0;//读取成功 } /******************************************************************************* * 函数名称 : SD_SendBlock * 功能描述 : 向sd卡写入一个数据包的内容 512字节 * 进入参数 : buf:数据缓存区 cmd:数据发送的令牌 * 返回参数 : 0:成功 其他:失败 * 备注说明 : 写数据时需要先发送数据起始令牌0XFE/0XFC/0XFD *******************************************************************************/ u8 SD_SendBlock(u8*buf,u8 cmd) { u32 t,Count=0XFFFFFF; while ((SD_SPI_ReadWriteByte(0XFF)!=0xFF)&&Count)Count--;//等待SD卡准备好 if (Count==0) return MSD_RESPONSE_FAILURE;//SD卡未准备好,失败,返回 SD_SPI_ReadWriteByte(cmd);//发送数据起始或停止令牌 if(cmd!=0XFD)//在不是结束令牌的情况下,开始发送数据 { for(t=0;t<512;t++)SPIx_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间 SD_SPI_ReadWriteByte(0xFF);//发送2字节的CRC SD_SPI_ReadWriteByte(0xFF); t=SD_SPI_ReadWriteByte(0xFF);//紧跟在CRC之后接收数据写的状态 if((t&0x1F)!=0x05)return MSD_DATA_WRITE_ERROR;//写入错误 } return 0;//写入成功 } /******************************************************************************* * 函数名称 : SD_SendCmd * 功能描述 : 向sd卡写入一个数据包的内容 512字节 * 进入参数 : cmd:命令 arg:命令参数crc: |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
645浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
516浏览 3评论
532浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
505浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 11:29 , Processed in 0.729543 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号