前情提要
因为要使用IMU采集惯性数据,然后导入PC端中进行机械编排推导,先前使用ROCK5A的板子发现SPI不奏效(可能因为不够了解),索性使用STM32来采集数据,在这之中需到了许多麻烦,这里就简要总结一下。
配置过程
使能SDIO
Mode选择4bits wide bus
在下面的参数部分使能Hardware flow control,如果不使能会出现FIFO溢出问题
SDIOCLK根据MCU主频选择,这里的计算原则是:SDIO_CK = SDIOCLK / [CLKDIV + 2]
其中SDIOCLK为AHB系统时钟分频独立值,一般为为48MHz
分频系数CLKDIV的选择原则是SD卡的时钟(SDIO_CK)最大不要超过25MHz,这里选择0,即拉满最大频率即可:48/(0+2)=24MHz的SDIO的频率
稳妥起见:建议配置为2,即48/(2+2)=12MHz即可
频率过高的时钟会导致版本过低或老一点的SD卡不能正常工作,会造成信息丢失,进而会出现CRC校验错误!
配置FATS
配置选项默认即可,如果不使用中文文件名就不用修改
在生成的代码上修改
打开SDIO.文件,在MX_SDIO_SD_Init()函数中添加
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
因为在初始化时,需要使用1bit带宽;
初始化完成后,在使用4bit带宽实现全速传输。
通过阅读HALO库源码发现,即使前面配置了SDIO_BUS_WIDE_1B
,在初始化SD完成时,将自动把SDIO转化成4Bits带宽
但是如果在开始SDIO配置为4bit模式,SD卡在初始化阶段会卡住!
所以要添加hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
编写挂载FATS文件系统
/**
* @brief Initial SD card
* @param None
* @retval None
*/
extern Disk_drvTypeDef disk;
void init_sd(){
//IMPORTANT! Reinitialize the tag!
disk.is_initialized[SDFatFS.drv] = 0;
uint8_t ret = f_mount(&SDFatFS, "0:", 1);
for (uint8_t i = 0; i < 5; i++) { // retry when mount error;
if(ret == FR_OK) {
printf("sd_mount success!\r\n");
break;
}
else if (ret == FR_NO_FILESYSTEM) { // No FATF file system format SD;
printf("No Detect FATFS! Would Format Disk?(y/[n])");
if (WaitForUsartInput(1, 5) && (!strncmp((const char*)g_usart_rx_buf, "y\r\n", 3))) {
printf("Formating\n");
/*
* as for STM32F4 Using standard FAT32 system
* "0:" --- disk drive number,
* FM_FAT32 --- type of file system,
* 0 -- auto-selection cluster size,
* pSDWorkBuffer --- buffer using when formating,
* 512 --- buffer size
*/
if(!f_mkfs("0:", FM_FAT32, 0, pSDWorkBuffer, 512)) {
printf("Formating Successful!\n");
f_setlabel((const TCHAR*)"0:SD");
printf_sdcard_info();
}
else printf("Formating Error!\n");
break;
}
else {
printf("SD Not Formating!\n");
break;
}
}
else {
printf("Fat System Mount ERROR\n");
f_mount(NULL, "0:", 1);
ret = f_mount(&SDFatFS, "0:", 1);;
}
}
// f_setlabel((const TCHAR*)"0:SD");
}
编写安全退出SD卡程序段
if(!strncmp((const char*)g_usart_rx_buf, "unmount\r\n", 9)){
f_mount(NULL, "0:", 1);
if(HAL_SD_DeInit(&hsd) == HAL_OK) printf("sd unmount success\r\n");
}
使用 HAL_SD_DeInit(&hsd)
来实现SD卡安全拔出