实现STM32使用全速USB接口的自定义HID与PC通讯的功能
1 STM32CubeMX配置
1.1 配置时钟
先设置好时钟,我用的外部8M晶振,但USB接口要使用48MHz时钟,所以主频只能到168Mhz
1.2 配置SD card
参数页如下配置,时钟分频比选择0,实际为2分频
配置DMA,给SDIO分配两个DMA通道,注意数据宽度选择Byte
打开SDIO和DMA的中断使能
另外GPIO要注意,如果硬件上这几个端口没有上拉电阻,这里开启内部上拉就好了
1.3 配置USB接口
模式选择Device_Only,下面的参数保持默认即可,其它页的参数不需要修改,中断已默认打开
1.4 设置中断优先级
注意中断优先级,SDIO的优先级要高一些,SDIO>DMA>USB
1.4 配置FATFS
上面模式页勾选SD Card,下面只需要修改长文件名的设置,使用动态堆
高级设置页,注意选择使用DMA
最后一页中,需要选择一下SD信号的引脚
1.5 配置USB设备
IP选择MSC,参数页不需要修改,MSC_MEDIA_PACKET需要跟SD卡的扇区大小一致,一般是512字节
这里可以设置自己的VID、PID等产品信息
配置完成,可以生成代码了
2 修改代码
找到《sd_diskio.h》文件,添加一个头文件的引用:#include “ff_gen_drv.h”
找到《usbd_storage_if.c》文件,添加一个头文件的引用:#include “sd_diskio.h”
接下来还是这个文件,添加SD卡对象的声明:
/* USER CODE BEGIN EXPORTED_VARIABLES */
extern SD_HandleTypeDef hsd;
/* USER CODE END EXPORTED_VARIABLES */
然后再修改几个函数,首先在初始化函数中添加一条初始化语句:
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
SD_Driver.disk_initialize(1);
return (USBD_OK);
/* USER CODE END 2 */
}
修改获取容量的函数:
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
// *block_num = STORAGE_BLK_NBR;
// *block_size = STORAGE_BLK_SIZ;
*block_num = hsd.SdCard.BlockNbr;
*block_size = hsd.SdCard.BlockSize;
return (USBD_OK);
/* USER CODE END 3 */
}
修改获取卡状态的函数:
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
return (SD_Driver.disk_status(lun));
/* USER CODE END 4 */
}
修改读卡函数:
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
return (SD_Driver.disk_read(lun, buf, blk_addr, blk_len));
/* USER CODE END 6 */
}
修改读卡、写卡函数:
/**
* @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 */
return (SD_Driver.disk_read(lun, buf, blk_addr, blk_len));
/* 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 */
return (SD_Driver.disk_write(lun, buf, blk_addr, blk_len));
/* USER CODE END 7 */
}
其它就不需要改了,也不需要自己写程序,作为USB Device单片机是被动的,所有的工作都在中断中执行。
3 测试
编译下载,可以看到电脑上出现了一个U盘盘符,用一个400多M的压缩包测试了存取速度,写入:355KB/s,读取:710KB/s。