Open imuncle opened 5 years ago
先把读卡器功能实现,相对于真正核心的嵌入式视觉代码来说,这种如同外设一般的存在就应该尽早被攻克掉。
这里推荐看正点原子的教程,讲的很详细。这里真心给正点原子点个赞!暑假的时候突然发现正点原子入驻B站了,可以直接在线观看高清的视频教程了!去他妈的限速百度云,保存到网盘在线看也没法高清,还时不时卡顿,入驻B站这一操作简直感动到哭!
不得不说,STM32CubeMX帮我们省去了很多很多外设的操作步骤。按照正点原子的教程,我们需要首先把SD卡的时钟降下来,发送指令初始化SD卡,初始化成功之后再把时钟升上去,每次发送命令操作寄存器,处理SD卡长短响应之类的,完全不用我们去管,只管调用函数就行。
STM32CubeMX里面的配置也非常简单,直接使能,一步到位:
之后读写SD卡什么的直接调用函数就行了。
USB接口真的有好多用处啊,基本上是可以模拟出所有USB接口的设备了,之前有写过一篇USB实现虚拟串口CDC的文章,这次实现模拟大容量存储设备,前几天还模拟了一下HID人体学输入设备,后面把HID的文章补上。说一句,HID比CDC好用多了!
限于篇幅,这里直接贴上cubemx的配置过程,在后面HID的文章中再稍微讲讲USB是怎么让电脑识别为大容量存储设备的。
首先使能USB_OTG_FS,这里OTG是On-The-Go的缩写,实现了在没有Host的情况下,设备间的数据传送。FS代表全速(Full Speed),另外还要一个选项是HS(High Speed),速度比全速更快,但是需要外部高速芯片的支持,比如加一个高速PHY,这里选FS就行。
On-The-Go
然后配置为Mass Storage Class,即MSC,大容量存储设备。上图中我其实还使能了FATS,但那是方便我通过单片机操作文件,这里模拟U盘用不到。
Mass Storage Class
在Device Descriptor中可以设置自己的设备名称,但影响不大,因为Windows文件管理器里面分配的盘符和名称跟这个没啥关系。
Device Descriptor
最后要把堆栈空间给大一点:
完成这些之后直接生成代码,编译,烧写,然后把开发板USB插电脑上,就可以直接识别为U盘了,不过因为还没跟SD卡对接起来,所以电脑会提示是否格式化,而且打不开。
这一步也是非常easy!打开usbd_storage_if.c,修改以下几个函数就行:
usbd_storage_if.c
/** * @brief . * @param lun: . * @param block_num: . * @param block_size: . * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { /* USER CODE BEGIN 3 */ HAL_SD_CardInfoTypeDef SDCardInfo; HAL_SD_GetCardInfo(&hsd, &SDCardInfo); *block_num = SDCardInfo.BlockNbr; *block_size = SDCardInfo.BlockSize; return (USBD_OK); /* USER CODE END 3 */ }
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_IsReady_FS(uint8_t lun) { /* USER CODE BEGIN 4 */ if(HAL_SD_GetState(&hsd) == HAL_SD_STATE_READY) { return (USBD_OK); } else { return (USBD_FAIL); } /* USER CODE END 4 */ }
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { /* USER CODE BEGIN 6 */ if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) { if(HAL_SD_ReadBlocks(&hsd, buf, blk_addr, blk_len, SDMMC_DATATIMEOUT) == HAL_OK) { return (USBD_OK); } else { return (USBD_FAIL); } } else return (USBD_BUSY); /* USER CODE END 6 */ }
/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { /* USER CODE BEGIN 7 */ if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) { if(HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, SDMMC_DATATIMEOUT) == HAL_OK) { return (USBD_OK); } else { return (USBD_FAIL); } } else return (USBD_BUSY); /* USER CODE END 7 */ }
这里要注意,读写SD卡的函数不要用DMA方式或者IT方式,一定要用最普通的阻塞方式,不然U盘内容会加载失败。
最后,我的“读卡器”成功了!
不过我试了一下U盘的写速度,很稳定的355KB/s,速度慢到出乎我的意料,可能是没有外部高速芯片支持的缘故吧,而且耗电量贼大。
我的电路板上用的5V转3.3V的芯片是LP5907,最大电流为500mA,但我频繁读写SD卡后这个芯片就发烫了,而且F4芯片也在发烫,差TF卡资料发现原来TF卡读写真的很费电:
居然可以达到500mA!我以为我这系统上耗电大户是摄像头和LCD,没想到竟然是SD卡,失策失策!
👍
先把读卡器功能实现,相对于真正核心的嵌入式视觉代码来说,这种如同外设一般的存在就应该尽早被攻克掉。
SDIO协议及SD卡简介
这里推荐看正点原子的教程,讲的很详细。这里真心给正点原子点个赞!暑假的时候突然发现正点原子入驻B站了,可以直接在线观看高清的视频教程了!去他妈的限速百度云,保存到网盘在线看也没法高清,还时不时卡顿,入驻B站这一操作简直感动到哭!
SD卡驱动
不得不说,STM32CubeMX帮我们省去了很多很多外设的操作步骤。按照正点原子的教程,我们需要首先把SD卡的时钟降下来,发送指令初始化SD卡,初始化成功之后再把时钟升上去,每次发送命令操作寄存器,处理SD卡长短响应之类的,完全不用我们去管,只管调用函数就行。
STM32CubeMX里面的配置也非常简单,直接使能,一步到位:
之后读写SD卡什么的直接调用函数就行了。
USB接口模拟大容量存储设备
USB接口真的有好多用处啊,基本上是可以模拟出所有USB接口的设备了,之前有写过一篇USB实现虚拟串口CDC的文章,这次实现模拟大容量存储设备,前几天还模拟了一下HID人体学输入设备,后面把HID的文章补上。说一句,HID比CDC好用多了!
限于篇幅,这里直接贴上cubemx的配置过程,在后面HID的文章中再稍微讲讲USB是怎么让电脑识别为大容量存储设备的。
首先使能USB_OTG_FS,这里OTG是
On-The-Go
的缩写,实现了在没有Host的情况下,设备间的数据传送。FS代表全速(Full Speed),另外还要一个选项是HS(High Speed),速度比全速更快,但是需要外部高速芯片的支持,比如加一个高速PHY,这里选FS就行。然后配置为
Mass Storage Class
,即MSC,大容量存储设备。上图中我其实还使能了FATS,但那是方便我通过单片机操作文件,这里模拟U盘用不到。在
Device Descriptor
中可以设置自己的设备名称,但影响不大,因为Windows文件管理器里面分配的盘符和名称跟这个没啥关系。最后要把堆栈空间给大一点:
完成这些之后直接生成代码,编译,烧写,然后把开发板USB插电脑上,就可以直接识别为U盘了,不过因为还没跟SD卡对接起来,所以电脑会提示是否格式化,而且打不开。
USB与SD卡对接
这一步也是非常easy!打开
usbd_storage_if.c
,修改以下几个函数就行:这里要注意,读写SD卡的函数不要用DMA方式或者IT方式,一定要用最普通的阻塞方式,不然U盘内容会加载失败。
效果
最后,我的“读卡器”成功了!
不过我试了一下U盘的写速度,很稳定的355KB/s,速度慢到出乎我的意料,可能是没有外部高速芯片支持的缘故吧,而且耗电量贼大。
我的电路板上用的5V转3.3V的芯片是LP5907,最大电流为500mA,但我频繁读写SD卡后这个芯片就发烫了,而且F4芯片也在发烫,差TF卡资料发现原来TF卡读写真的很费电:
居然可以达到500mA!我以为我这系统上耗电大户是摄像头和LCD,没想到竟然是SD卡,失策失策!
参考