新发基金的好处和坏处是什么?新基金的封闭期一般是多久?
新发基金的好处和坏处是什么?新发基金的优点:1、认购费率低:一般
2023/07/06
导语“生活中我们经常使用SD卡,一般SD卡有两种接口,SDIO和SPI,SPI接口在前面的教程中已经使用过了。本教程来介绍SDIO接口CubeMx如何配置使用,将以SD卡为例来讲解SDIO接口。”
•硬件
(相关资料图)
野火指南者开发版、SD卡
•软件
CubeMx & MDK & 串口助手
(1) STM32CubeMx 2021年最新版Version 6.1.0
(2) DMK V5.15
•原理图
F103只有一个SDIO接口,野火开发板中WiFi和SD卡公用这个接口,在使用中要注意不能同时操作。
SDIO 有4根数据线:D0~D1, 一次传输4位数据,CK为时钟线,CMD为控制线(操作命令通过这条线)。
本次教程的使用同样以UART串口使用的教程项目为基础进行配置,将测试结果打印出来,串口的配置这儿就不写了,可参考相关章节。
这次配置我们只是使用SDIO接口的基本模式,通过轮询模式来操作,下一节使用DMA模式。,完成上述操作后进行代码生成。
按上述配置初始化代码生成后,使用MDK打开项目进行应用代码编写。
/*SD 操作*/typedef enum {FAILED= 0, PASSED = !FAILED} TestStatus;/* 私有宏定义 ----------------------------------------------------------------*/#define BLOCK_SIZE 512 // SD卡块大小 #define NUMBER_OF_BLOCKS 8 // 测试块数量(小于15)#define WRITE_READ_ADDRESS 0x00002000 // 测试读写地址#define SDMMC hsd/* 私有变量 ------------------------------------------------------------------*/__align(4) uint32_t Buffer_Block_Tx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 写数据缓存__align(4) uint32_t Buffer_Block_Rx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 读数据缓存HAL_StatusTypeDef sd_status; // HAL库函数操作SD卡函数返回值:操作结果TestStatus test_status; // 数据测试结果void SD_EraseTes();void SD_Write_Read_Test();HAL_StatusTypeDef Return_Status;HAL_SD_CardStateTypeDef SD_Card_Status;/*************************************/ TestStatus eBuffercmp(uint32_t* pBuffer, uint32_t BufferLength) { while (BufferLength--) { /* SD卡擦除后的可能值为0xff或0 */ if ((*pBuffer != 0xFFFFFFFF) && (*pBuffer != 0)) { return FAILED; } pBuffer++; } return PASSED; } void SD_EraseTest(void) { /* 第1个参数为SD卡句柄,第2个参数为擦除起始地址,第3个参数为擦除结束地址 */ sd_status=HAL_SD_Erase(&SDMMC,WRITE_READ_ADDRESS,WRITE_READ_ADDRESS+NUMBER_OF_BLOCKS*4); printf("《SD》""erase status:%drn",sd_status); HAL_Delay(500); if (sd_status == HAL_OK) { /* 读取刚刚擦除的区域 */ sd_status = HAL_SD_ReadBlocks(&SDMMC,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("《SD》""erase read status:%drn",sd_status); /* 把擦除区域读出来对比 */ test_status = eBuffercmp(Buffer_Block_Rx,BLOCK_SIZE*NUMBER_OF_BLOCKS); if(test_status == PASSED) printf("《SD》""除测试成功!rn" ); else printf("《SD》""擦除不成功,数据出错!rn" ); } else { printf("《SD》""擦除测试失败!部分SD不支持擦除,只要读写测试通过即可rn" ); } } void Fill_Buffer(uint32_t *pBuffer, uint32_t BufferLength, uint32_t Offset) { uint32_t index = 0; /* 填充数据 */ for(index = 0; index < BufferLength; index++ ) { pBuffer[index] = index + Offset; } } TestStatus Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint32_t BufferLength) { while (BufferLength--) { if(BufferLength%50==0) { printf("buf:0x%08X - 0x%08Xrn",*pBuffer1,*pBuffer2); } if (*pBuffer1 != *pBuffer2) { return FAILED; } pBuffer1++; pBuffer2++; } return PASSED; } void SD_Write_Read_TestA(void) { printf(" Warning: this programmay erase all the TFcard data. rn"); printf("rn Initialize SD card successfully!rnrn"); printf(" SD card information! rn"); printf(" CardCapacity : %llu rn",((unsigned long long)SDMMC.SdCard.BlockSize*hsd.SdCard.BlockNbr)); printf(" CardBlockSize : %d rn",SDMMC.SdCard.BlockSize); printf(" RCA : %d rn",SDMMC.SdCard.RelCardAdd); printf(" CardType : %d rn",SDMMC.SdCard.CardType); int i,j = 0; /* 填充数据到写缓存 */ Fill_Buffer(Buffer_Block_Tx,BLOCK_SIZE*NUMBER_OF_BLOCKS, 0x6666); /* 往SD卡写入数据 */ sd_status = HAL_SD_WriteBlocks(&SDMMC,(uint8_t *)Buffer_Block_Tx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("《SD》""write status:%drn",sd_status); HAL_Delay(600); /* 从SD卡读取数据 */ sd_status =HAL_SD_ReadBlocks(&SDMMC,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("《SD》""read status:%drn",sd_status); /* 比较数据 */ test_status = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE*NUMBER_OF_BLOCKS/4); //比较 if(test_status == PASSED) { printf("《SD》""》读写测试成功!rn" ); for(i=0;i
(1)SD卡写入前必须对块进行擦除,调用HAL库函数HALSDErase();
( 2 ) SD 卡的读调用HAL库函数HALSDReadBlocks();
( 3 ) SD 卡的写调用HAL库的HALSDWriteBlocks()。
我们先对相关块进行擦除操作,再将数据写入,重新读出来进行比较是否一致来完成SD卡读写操作。
使用了联想的32GSD卡。
micro-sd
标签: