前情提要

因为要使用IMU采集惯性数据,然后导入PC端中进行机械编排推导,先前使用ROCK5A的板子发现SPI不奏效(可能因为不够了解),索性使用STM32来采集数据,在这之中需到了许多麻烦,这里就简要总结一下。

配置过程

  1. 使能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校验错误!

  1. 配置FATS

配置选项默认即可,如果不使用中文文件名就不用修改

  1. 在生成的代码上修改

打开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;

  1. 编写挂载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");
}

  1. 编写安全退出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卡安全拔出

山和山不相遇,人与人要相逢