完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1. SD卡介绍
1.1 SD卡简介 很多单片机系统都需要大容量存储设备,以存储数据(常用的有U盘、FLASH芯片、SD卡等),比较而言SD卡是单片机大容量外部存储的首选,只需要少数几个IO口即可外扩一个容量从几十M到几十G的,且有多种体积尺寸可选(标准SD卡、TF卡等)的外部存储器 SD卡(Secure Digital Memory Card)即:安全数码卡,它是在MMC的基础上发展而来,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。 SD卡按容量分类,可以分为3类:SD卡、SDHC卡、SDXC卡,如下表所示: SD卡和SDHC卡协议基本兼容,但是SDXC卡的区别比较大,这里仅介绍SD/SDHC卡(简称SD卡),SD卡由9个引脚与外部通讯,支持SPI和SDIO两种操作模式,不同模式下SD卡引脚功能描叙如下图表示: 1.2 SD卡的物理结构及内部框图 SD卡的物理结构一般包括以下5个部分:
SDIO由SDIO适配器和APB2接口两部分组成: [tr]名称功能[/tr]
下图是SDIO功能框图及SDIO适配器框图: 1.3 SD卡命令 SD卡命令由主机发出,命令格式固定为48位,通过CMD线连续传输,数据线不参与。SD命令结构如下图示:由6个字节组成,字节1的最高2位固定为01、低6位为命令号(比如CMD16);字节2 ~ 5为命令参数(有的命令没有参数);字节6的高7位为CRC、最低位恒定为1
1.4 SD卡响应 SD卡命令的响应由SD卡向主机发出,部分命令要求SD卡作出响应,这些响应多用于反馈SD卡的状态。基本特性如下:
SD的读写操作是以块为操作对象。先发送命令开始传输,然后传输数据块,传输完数据块紧接着传输CRC检验值。最好发送停止命令停止数据传输 1.5 SD卡的操作模式及切换 SD卡有多个版本,STM32控制器目前最高支持《Physical Layer Simplified Specification V2.0》定义的SD卡,STM32控制器对SD卡进行数据读写之前需要识别卡的种类:V1.0标准卡、V2.0标准卡、V2.0高容量卡或者不被识别卡。 SD卡系统定义了两种操作模式:卡识别模式和数据传输模式 在系统复位后,主机处于卡识别模式,寻找总线上可用的SDIO设备;同时,SD卡也处于卡识别模式,直到被主机识别到,即当SD卡接收到SEND_RCA(CMD3)命令后,SD卡就会进入数据传输模式,而主机在总线上所有卡被识别后也进入数据传输模式。 2. 硬件设计 D1指示灯用来提示系统运行状态,K_UP写入数据,K_DOWN读取数据,TFTLCD用来显示SD卡的容量、类型等信息,串口1用来打印调试信息
从以上电路图可以看出,SD卡支持SPI和SDIO模式,两种模式可以通过端子进行切换,P4端子与SD卡连接,SD端子与STM32F1的SDIO接口连接,IO端子与STM32F1的SPI2接口连接,本例程使用SDIO模式(将P4端子与SD端子短接) 3. 软件设计 3.1 STM32CubeMX设置
3.2 MDK-ARM编程
void MX_SDIO_SD_Init(void){ hsd.Instance = SDIO; hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; //上升沿 hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; //比使用bypass,直接用HCLK分配得到SDIO_CK hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; //空闲时不关闭时钟电源 hsd.Init.BusWide = SDIO_BUS_WIDE_1B; //1位数据线 hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; //开启硬件流控 hsd.Init.ClockDiv = 4; //4分频 if (HAL_SD_Init(&hsd) != HAL_OK){ Error_Handler(); } if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK){ Error_Handler(); //初始化完成后使能宽总线(4位)模式 } } //显示SD卡信息函数 void Show_SDMMC_Info(void){ HAL_SD_CardCIDTypeDef SDCard_CID; HAL_SD_CardInfoTypeDef SDCard_INFO; uint64_t CardCap; //SD卡容量 HAL_SD_GetCardCID(&hsd,&SDCard_CID); //获取CID HAL_SD_GetCardInfo(&hsd,&SDCard_INFO); //获取SD卡信息 FRONT_COLOR=BROWN; switch(SDCard_INFO.CardType) //SD卡类型 { case CARD_SDSC: if(SDCard_INFO.CardVersion == CARD_V1_X){ LCD_ShowString(120,190,50,16,16,(uint8_t *)"SDSC V1"); printf("Card Type: SDSC V1rn"); } else if(SDCard_INFO.CardVersion == CARD_V2_X){ LCD_ShowString(120,190,50,16,16,(uint8_t *)"SDSC V2"); printf("Card Type: SDSC V2rn"); } break; case CARD_SDHC_SDXC: LCD_ShowString(120,190,50,16,16,(uint8_t *)"SDHC"); printf("Card Type: SDHCrn"); break; } CardCap = (uint64_t)(SDCard_INFO.LogBlockNbr)*(uint64_t)(SDCard_INFO.LogBlockSize)/1024/1024; //计算SD卡容量 printf("Card ManufacturerID:%drn",SDCard_CID.ManufacturerID); //制造商ID printf("Card RCA:%drn",SDCard_INFO.RelCardAdd); //卡相对地址 printf("LogBlockNbr:%drn",SDCard_INFO.LogBlockNbr); //逻辑块数量 printf("LogBlockSize:%drn",SDCard_INFO.LogBlockSize); //逻辑块大小 printf("Card Capacity:%d MBrn",(uint32_t)CardCap); //显示容量 printf("Card BlockSize:%drn",SDCard_INFO.BlockSize); //块大小 LCD_ShowNum(120,210,CardCap,4,16); LCD_ShowString(160,210,50,16,16,(uint8_t *)"MB"); } uint8_t Buffer_Tx[512],Buffer_Rx[512] = {0}; uint32_t i; int main(void){ uint8_t key; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_FSMC_Init(); MX_SDIO_SD_Init(); MX_USART1_UART_Init(); MX_CRC_Init(); /* USER CODE BEGIN 2 */ TFTLCD_Init(); FRONT_COLOR=BROWN; LCD_DrawRectangle(25,25,215,135); FRONT_COLOR=RED; LCD_ShowString(30,30,200,16,16,(uint8_t *)"ANDYXI STM32"); LCD_ShowString(30,50,200,16,16,(uint8_t *)"STM32CubeMX"); LCD_ShowString(30,70,200,16,16,(uint8_t *)"SDIO TEST"); FRONT_COLOR=BLACK; LCD_ShowString(30,90,200,16,16, (uint8_t *)"K_U:ReadSD K_D:WriteSD"); LCD_ShowString(30,110,200,16,16,(uint8_t *)"K_R:EaseSD K_L:None"); FRONT_COLOR=BLUE; LCD_ShowString(30,170,200,16,16,(uint8_t *)"SD Card Information"); LCD_ShowString(30,190,80,16,16,(uint8_t *)"Card Type: "); LCD_ShowString(30,210,80,16,16,(uint8_t *)"Card Capa:"); Show_SDMMC_Info(); memset(Buffer_Tx,0x15,sizeof(Buffer_Tx)); /* USER CODE END 2 */ while (1){ key = KEY_Scan(0); switch(key) { case KEY_RIGHT_PRES: if(HAL_SD_Erase(&hsd,0,1) == HAL_OK){ while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER); printf("rnErase Block Success!rn"); LCD_ShowString(30,250,200,16,16,(uint8_t *)"Erase Block Success!"); } else{ printf("rnErase Block Failed!rn"); LCD_ShowString(30,250,200,16,16,(uint8_t *)"Erase Block Failed!"); } break; case KEY_UP_PRES: if(HAL_SD_ReadBlocks(&hsd,Buffer_Rx,0,1,0xffffffff) == HAL_OK){ while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER); printf("rnRead Block Success!rn"); for(i=0;i printf("rn"); LCD_ShowString(30,250,200,16,16,(uint8_t *)"Read Block Success!"); }else{ printf("rnRead Block Failed!rn"); LCD_ShowString(30,250,200,16,16,(uint8_t *)"Read Block Success!"); } break; case KEY_DOWN_PRES: if(HAL_SD_WriteBlocks(&hsd,Buffer_Tx,0,1,0xffffffff) == HAL_OK){ while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER); printf("rnWrite Block Success!rn"); for(i=0;i printf("rn"); LCD_ShowString(30,250,200,16,16,(uint8_t *)"Write Block Success!"); }else{ printf("rnWrite Block Failed!rn"); LCD_ShowString(30,250,200,16,16,(uint8_t *)"Write Block Failed!"); } break; } HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); HAL_Delay(200); } } 4. 下载验证 编译无误下载到开发板后,可以看到D1指示灯不断闪烁,按下KEY_UP键读取SD卡数据,按下KEY_DOWN键写入数据,按下KEY_RIGHT键擦除数据,SD卡信息以及更新的信息都会显示在LCD屏上 |
|
|
|
只有小组成员才能发言,加入小组>>
3314 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9059 浏览 16 评论
4088 浏览 18 评论
1180浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 17:25 , Processed in 1.125529 second(s), Total 79, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号