本章不打算详细讲解USB的协议,本章只是介绍如何通过STM32CubeMX软件生成应用程序。
在看本教程之前建议先看ST官方关于USB的培训视频,示例
http://www.stmcu.com.cn/videos.html
一、USB简介
stm32F746系列芯片有USB_OTG_FS和USB_OTG_HS两种接口,FS为全速,速度12M Bit/s,HS为高速,最高速度为480M Bit/s,此时需要外接USB HS PHY,例如USB3300。HS接口也可以作为FS接口使用。由于FS和HS接口使用是相同的USB设备库,只是初始化时配置的引脚不一样,本章以FS接口为例讲解USB设备库的使用。以下为USB OTG FS的电路图:
2
|
|
|
|
|
|
生成报告以及初始化代码,编译程序。工程中多出如下文件,其中最后四个为USB设备的库文件。
![]()
和前面的CDC对比一下,发现USB设备库文件中,u***d_cdc.c替换为u***d_hid.c文件。u***d_cdc_if.c为CDC应用层文件也去掉了。
|
|
|
|
|
|
|
|
删掉原来的应用程序,重新编写应用程序。在main.c文件最后面添加应用程序。程序GetPointerData()为读取五向摇杆按键状态更新坐标,CURSOR_STEP为每次移动的步长,输入参数为当前的坐标位置。
[color=rgb(160, 160, 160) !important]view source
[color=rgb(160, 160, 160) !important]print[color=rgb(160, 160, 160) !important]?
01 | /* USER CODE BEGIN 4 */ |
03 | * @brief Gets Pointer Data. |
04 | * @param pbuf: Pointer to report |
07 | static void GetPointerData(uint8_t *pbuf) |
11 | switch(BSP_JOY_GetState()) |
39 | * @brief SYSTICK callback. |
42 | void HAL_SYSTICK_Callback(void) |
44 | /* NOTE : This function Should not be modified, when the callback is needed, |
45 | the HAL_SYSTICK_Callback could be implemented in the user file |
47 | static __IO uint32_t counter=0; |
48 | /* check Joystick state every polling interval (10ms) */ |
49 | if (counter++ == USBD_HID_GetPollingInterval(&hU***DeviceFS)) |
51 | GetPointerData(HID_Buffer); |
53 | /* send data though IN endpoint*/ |
54 | if((HID_Buffer[1] != 0) || (HID_Buffer[2] != 0)) |
56 | USBD_HID_SendReport(&hU***DeviceFS, HID_Buffer, 4); |
|
|
|
|
|
|
|
|
HAL_SYSTICK_Callback()为SysTick定时器中断回调函数,时间为1ms。程序中先调用USBD_HID_GetPollingInterval函数读取HID轮询间隔。每隔10MS根据五向摇杆按键更新坐标,并通过USB发到电脑。
添加变量声明
1 | /* USER CODE BEGIN PV */ |
2 | /* Private variables ---------------------------------------------------------*/ |
添加u***d_hid.h头文件
1 | /* USER CODE BEGIN Includes */ |
2 | #include "stm32746g_sdram.h" |
3 | #include "stm32746g_LCD.h" |
6 | /* USER CODE END Includes */ |
编译程序,并下载到开发板,电脑u***线接到Open746I-C的核心板的USB接口中。按五向遥控按键电脑上的鼠标会移动。
|
|
|
|
|
|
|
|
三、USB MSC
本节介绍USB大容量存储设备类(Mass Storage Class),开发板作为U盘,用SDMMC接SD卡存储数据。
复制上一节CDC的工程文件,修改文件夹名。打开STM32cubeMX的工程文件重新配置,USB_OTG_FS选择设备,USB设备选择Mass Storage Class。
![]()
选择SDMMC接口为4线。
![]()
|
|
|
|
|
|
|
|
配置系统时钟频率为216MHZ,USB,SDMMC频率均为48MHz。
![]()
|
|
|
|
|
|
|
|
SDMMC添加收发DMA,其他为默认不作修改。
|
|
|
|
|
|
|
|
开启SDMMC中断,注意必须开启SDMMC中断,SDMMC的DMA才能正常工作,而且SDMMC中断优先级要比DMA中断要高,且比USB中断高。
![]()
|
|
|
|
|
|
|
|
增大堆栈空间的大小,否则会程序会触发硬件错误中断(HardFault)。
![]()
生成报告以及初始化代码,编译程序。工程中多出如下文件,其中最后七个为USB设备的库文件。
![]()
|
|
|
|
|
|
|
|
其中u***d_storage_if为应用层文件,里面为USB大容量存储设备类底层操作,包括获取存储器容量,块读写等操作。实际上u***d_storage_if里面这些操作都是空的,需要我们移植底层。由于SD的操作是由电脑同过USB镜像操作的,故开发板程序是不需要移植文件系统的,我们只需在u***d_storage_if文件中添加SD卡的底层操作既可。
打开u***d_storage_if文件,我们只需修改三个函数既可,第一个是获取存储器容量大小函数,返回块大小,已经块数目。
01 | /******************************************************************************* |
02 | * Function Name : STORAGE_GetCapacity_FS |
07 | *******************************************************************************/ |
08 | int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size) |
10 | /* USER CODE BEGIN 3 */ |
11 | HAL_SD_CardInfoTypedef info; |
12 | int8_t ret = USBD_FAIL; |
14 | // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) |
17 | HAL_SD_Get_CardInfo(&hsd1, &info); |
18 | *block_num = (info.CardCapacity)/STORAGE_BLK_SIZ - 1; |
19 | *block_size = info.CardBlockSize; |
|
|
|
|
|
|
|
|
第二个是块读取函数,SD卡是通过DMA传输数据。
01 | /******************************************************************************* |
02 | * Function Name : STORAGE_Read_FS |
07 | *******************************************************************************/ |
08 | int8_t STORAGE_Read_FS (uint8_t lun, |
13 | /* USER CODE BEGIN 6 */ |
14 | int8_t ret = USBD_FAIL; |
16 | // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) |
18 | /* Read block(s) in DMA transfer mode */ |
19 | if(HAL_SD_ReadBlocks_DMA(&hsd1,(uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len) == SD_OK) |
24 | /* Wait until transfer is complete */ |
27 | if(HAL_SD_CheckReadOperation(&hsd1, (uint32_t)100000000) != SD_OK) |
|
|
|
|
|
|
|
|
第三个是写操作函数
01 | /******************************************************************************* |
02 | * Function Name : STORAGE_Write_FS |
07 | *******************************************************************************/ |
08 | int8_t STORAGE_Write_FS (uint8_t lun, |
13 | /* USER CODE BEGIN 7 */ |
14 | int8_t ret = USBD_FAIL; |
16 | // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) |
18 | /* Write block(s) in DMA transfer mode */ |
19 | if(HAL_SD_WriteBlocks_DMA(&hsd1, (uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len) == SD_OK) |
24 | /* Wait until transfer is complete */ |
27 | if(HAL_SD_CheckWriteOperation(&hsd1, (uint32_t)100000000) != SD_OK) |
|
|
|
|
|
|
|
|
注意:Open746I-C中可以通过PC13管脚判断SD卡是否插入到卡槽中,这里为了方便没有用到这个功能。所以上面程序中注释掉了检测SD卡是否准备好这一步。
![]()
编译程序,并下载到开发板,电脑u***线接到Open746I-C的核心板的USB接口中。电脑会提示有U盘插入。
|
|
|
|
|
|
|
|
多谢楼主分享!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
|
|
|
|
很好的教程,现在cubemx的例程很少,特别是USB的
|
|
|
|
|
|
|
|
cubemx配置完后,看不到USB的PA11,PA12这两个脚在哪个文件里配置的,能不能打包个prj传上来
|
|
|
|
|
|
|
|