最近查了很多关于SDIO+USB MSG的文章。得到了比较浅显的配置手段,目前也是成功的单根USB线同时供电和传输数据。并简单进行了读写测试。

需要SD卡为SDHC(Secure Digital High Capacity)类型:容量范围为2GB到32GB。

下面开始一步步配置

1.开启外部高速时钟并开启SWD下载;

2.开启SDIO并启动DMA,配置默认

3.开始USB作为设备端,其他配置默认

4.启动FATFS,并设置中文和启动长文件名,开启DMA,配置SD卡插入检测引脚

5.启用USB MSG,配置默认

6.手动配置时钟

7.配置NVIC中断优先级

8.堆栈稍微拉大点,都设置成1000,然后生成代码

9.加入#include "ff_gen_drv.h"代码

10.修改usbd_storage_if.c文件(添加两个头文件,修改三个函数)

获取存储介质容量

int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */
  HAL_SD_CardInfoTypeDef cardInfo;
	//使用SDIO库函数
	HAL_StatusTypeDef res = HAL_SD_GetCardInfo(&hsd, &cardInfo);
	if(res == HAL_OK)
	{
		*block_num  = cardInfo.BlockNbr;    //块的个数
		*block_size = cardInfo.BlockSize;   //块大小=512字节
	}
	else
	{
		*block_num  = STORAGE_BLK_NBR;	    //0x10000
		*block_size = STORAGE_BLK_SIZ;      //块大小=512字节
	}
	
	return (USBD_OK);
  /* USER CODE END 3 */
}

读取存储介质

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
	//读取超时时间10000ms
	uint32_t Timeout = 10000;  
	HAL_StatusTypeDef res = HAL_OK;
	res = HAL_SD_ReadBlocks(&hsd, buf, blk_addr, blk_len, Timeout);
	HAL_SD_CardStateTypeDef status = HAL_SD_CARD_RECEIVING;
	
	if(res == HAL_OK)
	{
		//等待传输完成
		while(status != HAL_SD_CARD_TRANSFER)   
			status = HAL_SD_GetCardState(&hsd);
		return (USBD_OK);
	}
	else
		return (USBD_FAIL);
  /* USER CODE END 6 */
}

向存储介质写入数据

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
//写入超时时间10000ms
	uint32_t Timeout = 10000;   
	HAL_StatusTypeDef res = HAL_OK;
	res = HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, Timeout);
	HAL_SD_CardStateTypeDef status = HAL_SD_CARD_SENDING;
	
	if (res == HAL_OK)
	{
		//等待传输完成
		while(status != HAL_SD_CARD_TRANSFER)   
			status = HAL_SD_GetCardState(&hsd);
		return (USBD_OK);
	}
	else
		return (USBD_FAIL);
  /* USER CODE END 7 */
}

11.进行主函数读写测试

/* USER CODE BEGIN 0 */
uint8_t  readBuf[512];
uint8_t  writeBuf[512];
BYTE work[_MAX_SS];
char *fileName = "test.txt";
uint32_t writeLen;
uint32_t readLen;
/* USER CODE END 0 */
 /* USER CODE BEGIN 2 */
// 挂载
	retSD = f_mount(&SDFatFS, SDPath, 1);
	switch(retSD)
	{
		case FR_NO_FILESYSTEM:  // FM_FAT32
					{
						retSD = f_mkfs(SDPath,FM_FAT32,512,work, sizeof(work));
						if(retSD!=FR_OK)
						{
							while(1);
						}
					}
					break;
		case FR_OK:break;
		default:
			while(1);
	}
	
	// 写
	retSD = f_open(&SDFile,fileName, FA_CREATE_ALWAYS | FA_WRITE);
	if(retSD!=FR_OK)
	{
		while(1);
	}
	
	sprintf((char *)writeBuf,"%s","abc123今天天气还可以\r\n");
	retSD = f_write(&SDFile,writeBuf, strlen((const char *)writeBuf), &writeLen);
	if(retSD!=FR_OK)
	{
		while(1);
	}
	f_close(&SDFile);
	
	
	// 读
	retSD = f_open(&SDFile,fileName, FA_OPEN_EXISTING | FA_READ);
	if(retSD!=FR_OK)
	{
		while(1);
	}
	
	retSD = f_read(&SDFile,readBuf, 50, &readLen);
	if(retSD!=FR_OK)
	{
		while(1);
	}
	f_close(&SDFile);
	
	// 卸载
	f_mount(NULL, SDPath, 1);
  /* USER CODE END 2 */

12.现象

USB加载需要大概10s,很慢,

参考文献:【CubeMX+STM32】SD卡 U盘文件系统 USB+FATFS_stm32cubemx fatfs-CSDN博客

STM32CubeMX教程30 USB_DEVICE - MSC外设_读卡器_stm32cubemx配置usb读卡器-CSDN博客

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐