首页 > 其他分享 >stm32cubeide usb cdc hid

stm32cubeide usb cdc hid

时间:2025-01-07 11:47:13浏览次数:6  
标签:CODE usb USBD FS hid USER stm32cubeide SD USB

STM32CubeMX系列教程25:USB Device - STM32CubeMX系列教程 微雪课堂

本章不打算详细讲解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的电路图:  

  USB只要由USB_DM和USB_DP两根线差分传输。OTG_ID线用来判断为主设备或时从设备的,作为OTG设备的时候使用。MIC2025/75为USB电源管理芯片,当作为设备是,从外部取电源,VBUSEN(PE2)要设置为高。当作为主机时,要拉低,USB口输出电压给从设备。   二、USB CDC           这一节介绍usb作为通讯设备类(Communication Device Class),通过USB虚拟串口通信。程序在LCD滚动显示字符工程的基础上修改,复制工程修改文件夹名。打开STM32cubeMX的工程文件重新配置,USB_OTG_FS选择设备。  

  配置系统时钟为216MHz,USB的时钟频率为48MHz.  

  开启USB中间件,选择虚拟串口。

  USB参数配置中 VBUS  sensing 选择失能,其他为默认设置。

  中间件USB设备配置也不用修改,默认的配置。

  设备描述符设置也不需修改,为默认设置。

  软件会默认开启USB中断,此处也为默认优先级,不作修改。

  生成报告以及初始化代码,编译程序。工程中多出如下文件,其中最后四个为USB设备的库文件。  

  usb_device.c里面仅包含一个USB设备函数初始化函数 MX_USB_DEVICE_Init(),在程序开始时调用。 usbd_cdc_if.c为USB的CDC类应用层文件,里面包含虚拟串口的接收,发送和控制等函数。 usb_desc.c包含USB的描述符,以及USB枚举处理等函数。 usb_conf.com为USB管脚配置文件,包含引USB引脚初始化以及参数设置,中断回调函数等。   打开usbd_cdc_if.c文件,找到虚拟串口接收函数。  
1 static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
2 {
3   /* USER CODE BEGIN 6 */
4   USBD_CDC_SetRxBuffer(hUsbDevice_0, &Buf[0]);
5   USBD_CDC_ReceivePacket(hUsbDevice_0);
6   return (USBD_OK);
7   /* USER CODE END 6 */
8 }
  修改接收处理函数,接收到的字符打印输出在LCD屏幕上。    
1 static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
2 {
3   /* USER CODE BEGIN 6 */
4   uint8_t result = USBD_OK;
5     uint8_t msg[Len[0]+1];
6     uint32_t i;
7     result = USBD_CDC_ReceivePacket(&hUsbDeviceFS);
8     for(i=0;i<len[0];i++) {="" msg[i]="*" buf++;="" }="" ;="" printf("%s\n",msg);="" return="" result;="" *="" user="" code="" end="" 6="" }<="" pre=""></len[0];i++)>
  如下为发送函数,程序中先设置发送字符,然后发送包。这里注意一点,Cube软件初始化的USB结构体是hUsbDeviceFS,这里操作的结构体是hUsbDevice_0。故这个函数不能直接调用,必须先CDC_Init_FS()函数初始化才能用这个函数,初始化中包含有这个语句hUsbDevice_0 = &hUsbDeviceFS。    
1 uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
2 {
3   uint8_t result = USBD_OK;
4   /* USER CODE BEGIN 7 */
5   USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);  
6   result = USBD_CDC_TransmitPacket(hUsbDevice_0);
7   /* USER CODE END 7 */
8   return result;
9 }
本教程不调用这个发送函数。在main函数中while循环中添加语法每秒发送一次字符串。  
01 /* USER CODE BEGIN WHILE */
02   while (1)
03   {
04 /* USER CODE END WHILE */
05  
06 /* USER CODE BEGIN 3 */
07       USBD_CDC_SetTxBuffer(&hUsbDeviceFS, (uint8_t*)&UserTxBuffer, sizeof(UserTxBuffer));
08       USBD_CDC_TransmitPacket(&hUsbDeviceFS);
09  
10       HAL_Delay(1000);
11   }
12 /* USER CODE END 3 */
  在前面声明发送字符串。  
1 /* USER CODE BEGIN 1 */
2 uint8_t UserTxBuffer[] = "WaveShare Open7XXI-C Board STM32 Virtual COM Port Driver \r\n";
3 /* USER CODE END 1 */
  在main函数中,while循环前面添加程式初始化LCD。  
01 /* USER CODE BEGIN 2 */
02   /* Initialize the SDRAM */
03   BSP_SDRAM_Init();
04   /* Initialize the LCD */ 
05   BSP_LCD_Init();
06  
07   BSP_LCD_SetLayerVisible(1, DISABLE);
08   BSP_LCD_SelectLayer(0);
09  
10   /* Initialize LCD Log module */
11   LCD_LOG_Init();
12  
13   /* Show Header and Footer texts */
14   LCD_LOG_SetHeader((uint8_t *)"Waveshare Electronics");
15   LCD_LOG_SetFooter((uint8_t *)"WaveShare Open7XXI-C board");
16 /* USER CODE END 2 */
  最后添加usbd_cdc.h头文件。    
1 /* USER CODE BEGIN Includes */
2 #include "stm32746g_sdram.h"
3 #include "stm32746g_LCD.h"
4 #include "lcd_log.h"
5 #include "usbd_cdc.h"
6 /* USER CODE END Includes */
最后编译程序,并下载到开发板,电脑usb线接到Open746I-C的核心板的USB接口中。打开串口助手会接到开发板发送的字符串,串口助手发送的字符会在LCD上显示。设置的串口传输格式是无效的,程序中没有设置串口传输格式,可以修改usbd_cdc_if.c文件的CDC_Control_FS()函数设置。   注:电脑要安装ST虚拟串口驱动才能设别虚拟串口。如下为虚拟串口驱动:  

stsw.zip

  三、USB HID     本节介绍USB作为人机接口设备(Human Interface Device),开发板模拟鼠标设备。 复制上一节的工程文件,修改文件夹名。打开STM32cubeMX的工程文件重新配置,USB_OTG_FS选择设备,USB设备选择Human Interface Device。

 

  USB参数配置中 VBUS  sensing 选择失能,其他为默认设置。

  USB设备中间层不需要修改,为默认设置。

 

  生成报告以及初始化代码,编译程序。工程中多出如下文件,其中最后四个为USB设备的库文件。  

  和前面的CDC对比一下,发现USB设备库文件中,usbd_cdc.c替换为usbd_hid.c文件。usbd_cdc_if.c为CDC应用层文件也去掉了。 删掉原来的应用程序,重新编写应用程序。在main.c文件最后面添加应用程序。程序GetPointerData()为读取五向摇杆按键状态更新坐标,CURSOR_STEP为每次移动的步长,输入参数为当前的坐标位置。  
01 /* USER CODE BEGIN 4 */
02 /**
03   * @brief  Gets Pointer Data.
04   * @param  pbuf: Pointer to report
05   * @retval None
06   */
07 static void GetPointerData(uint8_t *pbuf)
08 {
09   int8_t  x = 0, y = 0 ;
10     
11   switch(BSP_JOY_GetState())
12   {
13     case JOY_LEFT:
14       x -= CURSOR_STEP;
15       break;
16         
17     case JOY_RIGHT:
18       x += CURSOR_STEP;
19       break;
20         
21     case JOY_UP:
22       y -= CURSOR_STEP;
23       break;
24         
25     case JOY_DOWN:
26       y += CURSOR_STEP;
27       break;
28         
29     default:
30       break;
31   }
32   pbuf[0] = 0;
33   pbuf[1] = x;
34   pbuf[2] = y;
35   pbuf[3] = 0;
36 }
37   
38 /**
39   * @brief  SYSTICK callback.
40   * @retval None
41   */
42 void HAL_SYSTICK_Callback(void)
43 {
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
46    */
47     static __IO uint32_t counter=0;
48     /* check Joystick state every polling interval (10ms) */
49   if (counter++ == USBD_HID_GetPollingInterval(&hUsbDeviceFS))
50   {
51     GetPointerData(HID_Buffer);
52       
53     /* send data though IN endpoint*/
54     if((HID_Buffer[1] != 0) || (HID_Buffer[2] != 0))
55     {
56       USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 4);
57     }
58     counter =0;
59   }
60   BSP_LED_Toggle(LED1);
61 }
62 /* USER CODE END 4 */
HAL_SYSTICK_Callback()为SysTick定时器中断回调函数,时间为1ms。程序中先调用USBD_HID_GetPollingInterval函数读取HID轮询间隔。每隔10MS根据五向摇杆按键更新坐标,并通过USB发到电脑。
  添加变量声明
1 /* USER CODE BEGIN PV */
2 /* Private variables ---------------------------------------------------------*/
3 #define CURSOR_STEP     5
4 uint8_t HID_Buffer[4];
5 /* USER CODE END PV */
  添加usbd_hid.h头文件    
1 /* USER CODE BEGIN Includes */
2 #include "stm32746g_sdram.h"
3 #include "stm32746g_LCD.h"
4 #include "lcd_log.h"
5 #include "usbd_hid.h"
6 /* USER CODE END Includes */
  编译程序,并下载到开发板,电脑usb线接到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设备的库文件。

  其中usbd_storage_if为应用层文件,里面为USB大容量存储设备类底层操作,包括获取存储器容量,块读写等操作。实际上usbd_storage_if里面这些操作都是空的,需要我们移植底层。由于SD的操作是由电脑同过USB镜像操作的,故开发板程序是不需要移植文件系统的,我们只需在usbd_storage_if文件中添加SD卡的底层操作既可。   打开usbd_storage_if文件,我们只需修改三个函数既可,第一个是获取存储器容量大小函数,返回块大小,已经块数目。  
01 /*******************************************************************************
02 * Function Name  : STORAGE_GetCapacity_FS
03 * Description    :
04 * Input          : None.
05 * Output         : None.
06 * Return         : None.
07 *******************************************************************************/
08 int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
09 {
10   /* USER CODE BEGIN 3 */  
11     HAL_SD_CardInfoTypedef info;
12     int8_t ret = USBD_FAIL; 
13       
14 //  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
15     {
16           
17         HAL_SD_Get_CardInfo(&hsd1, &info);
18         *block_num = (info.CardCapacity)/STORAGE_BLK_SIZ  - 1;
19         *block_size = info.CardBlockSize;
20         ret = USBD_OK;
21     }
22   return ret;
23   /* USER CODE END 3 */
24 }
第二个是块读取函数,SD卡是通过DMA传输数据。  
01 /*******************************************************************************
02 * Function Name  : STORAGE_Read_FS
03 * Description    :
04 * Input          : None.
05 * Output         : None.
06 * Return         : None.
07 *******************************************************************************/
08 int8_t STORAGE_Read_FS (uint8_t lun,
09                         uint8_t *buf,
10                         uint32_t blk_addr,                      
11                         uint16_t blk_len)
12 {
13   /* USER CODE BEGIN 6 */
14       int8_t ret = USBD_FAIL; 
15     
16 //  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
17   
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)
20         {
21             ret = USBD_OK;
22         }
23   
24         /* Wait until transfer is complete */
25         if(ret == USBD_OK)
26         {
27             if(HAL_SD_CheckReadOperation(&hsd1, (uint32_t)100000000) != SD_OK)
28             {
29                 ret = USBD_FAIL;
30             }
31             else
32             {
33                 ret = USBD_OK;
34             }
35         }
36         ret = USBD_OK;
37   }
38   return ret;
39   /* USER CODE END 6 */
40 }
第三个是写操作函数  
01 /*******************************************************************************
02 * Function Name  : STORAGE_Write_FS
03 * Description    :
04 * Input          : None.
05 * Output         : None.
06 * Return         : None.
07 *******************************************************************************/
08 int8_t STORAGE_Write_FS (uint8_t lun,
09                          uint8_t *buf,
10                          uint32_t blk_addr,
11                          uint16_t blk_len)
12 {
13   /* USER CODE BEGIN 7 */
14     int8_t ret = USBD_FAIL;  
15     
16 //  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
17   {
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)
20         {
21             ret = USBD_OK;
22         }
23   
24         /* Wait until transfer is complete */
25         if(ret == USBD_OK)
26         {
27             if(HAL_SD_CheckWriteOperation(&hsd1, (uint32_t)100000000) != SD_OK)
28             {
29                 ret = USBD_FAIL;
30             }
31             else
32             {
33                 ret = USBD_OK;
34             }
35         }
36   }
37   return ret;
38   /* USER CODE END 7 */
39 }
  注意:Open746I-C中可以通过PC13管脚判断SD卡是否插入到卡槽中,这里为了方便没有用到这个功能。所以上面程序中注释掉了检测SD卡是否准备好这一步。

    编译程序,并下载到开发板,电脑usb线接到Open746I-C的核心板的USB接口中。电脑会提示有U盘插入。  
   
本章不打算详细讲解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的电路图:  

  USB只要由USB_DM和USB_DP两根线差分传输。OTG_ID线用来判断为主设备或时从设备的,作为OTG设备的时候使用。MIC2025/75为USB电源管理芯片,当作为设备是,从外部取电源,VBUSEN(PE2)要设置为高。当作为主机时,要拉低,USB口输出电压给从设备。   二、USB CDC           这一节介绍usb作为通讯设备类(Communication Device Class),通过USB虚拟串口通信。程序在LCD滚动显示字符工程的基础上修改,复制工程修改文件夹名。打开STM32cubeMX的工程文件重新配置,USB_OTG_FS选择设备。  

  配置系统时钟为216MHz,USB的时钟频率为48MHz.  

  开启USB中间件,选择虚拟串口。

  USB参数配置中 VBUS  sensing 选择失能,其他为默认设置。

  中间件USB设备配置也不用修改,默认的配置。

  设备描述符设置也不需修改,为默认设置。

  软件会默认开启USB中断,此处也为默认优先级,不作修改。

  生成报告以及初始化代码,编译程序。工程中多出如下文件,其中最后四个为USB设备的库文件。  

  usb_device.c里面仅包含一个USB设备函数初始化函数 MX_USB_DEVICE_Init(),在程序开始时调用。 usbd_cdc_if.c为USB的CDC类应用层文件,里面包含虚拟串口的接收,发送和控制等函数。 usb_desc.c包含USB的描述符,以及USB枚举处理等函数。 usb_conf.com为USB管脚配置文件,包含引USB引脚初始化以及参数设置,中断回调函数等。   打开usbd_cdc_if.c文件,找到虚拟串口接收函数。  
1 static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
2 {
3   /* USER CODE BEGIN 6 */
4   USBD_CDC_SetRxBuffer(hUsbDevice_0, &Buf[0]);
5   USBD_CDC_ReceivePacket(hUsbDevice_0);
6   return (USBD_OK);
7   /* USER CODE END 6 */
8 }
  修改接收处理函数,接收到的字符打印输出在LCD屏幕上。    
1 static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
2 {
3   /* USER CODE BEGIN 6 */
4   uint8_t result = USBD_OK;
5     uint8_t msg[Len[0]+1];
6     uint32_t i;
7     result = USBD_CDC_ReceivePacket(&hUsbDeviceFS);
8     for(i=0;i<len[0];i++) {="" msg[i]="*" buf++;="" }="" ;="" printf("%s\n",msg);="" return="" result;="" *="" user="" code="" end="" 6="" }<="" pre=""></len[0];i++)>
  如下为发送函数,程序中先设置发送字符,然后发送包。这里注意一点,Cube软件初始化的USB结构体是hUsbDeviceFS,这里操作的结构体是hUsbDevice_0。故这个函数不能直接调用,必须先CDC_Init_FS()函数初始化才能用这个函数,初始化中包含有这个语句hUsbDevice_0 = &hUsbDeviceFS。    
1 uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
2 {
3   uint8_t result = USBD_OK;
4   /* USER CODE BEGIN 7 */
5   USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);  
6   result = USBD_CDC_TransmitPacket(hUsbDevice_0);
7   /* USER CODE END 7 */
8   return result;
9 }
本教程不调用这个发送函数。在main函数中while循环中添加语法每秒发送一次字符串。  
01 /* USER CODE BEGIN WHILE */
02   while (1)
03   {
04 /* USER CODE END WHILE */
05  
06 /* USER CODE BEGIN 3 */
07       USBD_CDC_SetTxBuffer(&hUsbDeviceFS, (uint8_t*)&UserTxBuffer, sizeof(UserTxBuffer));
08       USBD_CDC_TransmitPacket(&hUsbDeviceFS);
09  
10       HAL_Delay(1000);
11   }
12 /* USER CODE END 3 */
  在前面声明发送字符串。  
1 /* USER CODE BEGIN 1 */
2 uint8_t UserTxBuffer[] = "WaveShare Open7XXI-C Board STM32 Virtual COM Port Driver \r\n";
3 /* USER CODE END 1 */
  在main函数中,while循环前面添加程式初始化LCD。  
01 /* USER CODE BEGIN 2 */
02   /* Initialize the SDRAM */
03   BSP_SDRAM_Init();
04   /* Initialize the LCD */ 
05   BSP_LCD_Init();
06  
07   BSP_LCD_SetLayerVisible(1, DISABLE);
08   BSP_LCD_SelectLayer(0);
09  
10   /* Initialize LCD Log module */
11   LCD_LOG_Init();
12  
13   /* Show Header and Footer texts */
14   LCD_LOG_SetHeader((uint8_t *)"Waveshare Electronics");
15   LCD_LOG_SetFooter((uint8_t *)"WaveShare Open7XXI-C board");
16 /* USER CODE END 2 */
  最后添加usbd_cdc.h头文件。    
1 /* USER CODE BEGIN Includes */
2 #include "stm32746g_sdram.h"
3 #include "stm32746g_LCD.h"
4 #include "lcd_log.h"
5 #include "usbd_cdc.h"
6 /* USER CODE END Includes */
最后编译程序,并下载到开发板,电脑usb线接到Open746I-C的核心板的USB接口中。打开串口助手会接到开发板发送的字符串,串口助手发送的字符会在LCD上显示。设置的串口传输格式是无效的,程序中没有设置串口传输格式,可以修改usbd_cdc_if.c文件的CDC_Control_FS()函数设置。   注:电脑要安装ST虚拟串口驱动才能设别虚拟串口。如下为虚拟串口驱动:  

stsw.zip

  三、USB HID     本节介绍USB作为人机接口设备(Human Interface Device),开发板模拟鼠标设备。 复制上一节的工程文件,修改文件夹名。打开STM32cubeMX的工程文件重新配置,USB_OTG_FS选择设备,USB设备选择Human Interface Device。

 

  USB参数配置中 VBUS  sensing 选择失能,其他为默认设置。

  USB设备中间层不需要修改,为默认设置。

 

  生成报告以及初始化代码,编译程序。工程中多出如下文件,其中最后四个为USB设备的库文件。  

  和前面的CDC对比一下,发现USB设备库文件中,usbd_cdc.c替换为usbd_hid.c文件。usbd_cdc_if.c为CDC应用层文件也去掉了。 删掉原来的应用程序,重新编写应用程序。在main.c文件最后面添加应用程序。程序GetPointerData()为读取五向摇杆按键状态更新坐标,CURSOR_STEP为每次移动的步长,输入参数为当前的坐标位置。  
01 /* USER CODE BEGIN 4 */
02 /**
03   * @brief  Gets Pointer Data.
04   * @param  pbuf: Pointer to report
05   * @retval None
06   */
07 static void GetPointerData(uint8_t *pbuf)
08 {
09   int8_t  x = 0, y = 0 ;
10     
11   switch(BSP_JOY_GetState())
12   {
13     case JOY_LEFT:
14       x -= CURSOR_STEP;
15       break;
16         
17     case JOY_RIGHT:
18       x += CURSOR_STEP;
19       break;
20         
21     case JOY_UP:
22       y -= CURSOR_STEP;
23       break;
24         
25     case JOY_DOWN:
26       y += CURSOR_STEP;
27       break;
28         
29     default:
30       break;
31   }
32   pbuf[0] = 0;
33   pbuf[1] = x;
34   pbuf[2] = y;
35   pbuf[3] = 0;
36 }
37   
38 /**
39   * @brief  SYSTICK callback.
40   * @retval None
41   */
42 void HAL_SYSTICK_Callback(void)
43 {
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
46    */
47     static __IO uint32_t counter=0;
48     /* check Joystick state every polling interval (10ms) */
49   if (counter++ == USBD_HID_GetPollingInterval(&hUsbDeviceFS))
50   {
51     GetPointerData(HID_Buffer);
52       
53     /* send data though IN endpoint*/
54     if((HID_Buffer[1] != 0) || (HID_Buffer[2] != 0))
55     {
56       USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 4);
57     }
58     counter =0;
59   }
60   BSP_LED_Toggle(LED1);
61 }
62 /* USER CODE END 4 */
HAL_SYSTICK_Callback()为SysTick定时器中断回调函数,时间为1ms。程序中先调用USBD_HID_GetPollingInterval函数读取HID轮询间隔。每隔10MS根据五向摇杆按键更新坐标,并通过USB发到电脑。
  添加变量声明
1 /* USER CODE BEGIN PV */
2 /* Private variables ---------------------------------------------------------*/
3 #define CURSOR_STEP     5
4 uint8_t HID_Buffer[4];
5 /* USER CODE END PV */
  添加usbd_hid.h头文件    
1 /* USER CODE BEGIN Includes */
2 #include "stm32746g_sdram.h"
3 #include "stm32746g_LCD.h"
4 #include "lcd_log.h"
5 #include "usbd_hid.h"
6 /* USER CODE END Includes */
  编译程序,并下载到开发板,电脑usb线接到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设备的库文件。

  其中usbd_storage_if为应用层文件,里面为USB大容量存储设备类底层操作,包括获取存储器容量,块读写等操作。实际上usbd_storage_if里面这些操作都是空的,需要我们移植底层。由于SD的操作是由电脑同过USB镜像操作的,故开发板程序是不需要移植文件系统的,我们只需在usbd_storage_if文件中添加SD卡的底层操作既可。   打开usbd_storage_if文件,我们只需修改三个函数既可,第一个是获取存储器容量大小函数,返回块大小,已经块数目。  
01 /*******************************************************************************
02 * Function Name  : STORAGE_GetCapacity_FS
03 * Description    :
04 * Input          : None.
05 * Output         : None.
06 * Return         : None.
07 *******************************************************************************/
08 int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
09 {
10   /* USER CODE BEGIN 3 */  
11     HAL_SD_CardInfoTypedef info;
12     int8_t ret = USBD_FAIL; 
13       
14 //  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
15     {
16           
17         HAL_SD_Get_CardInfo(&hsd1, &info);
18         *block_num = (info.CardCapacity)/STORAGE_BLK_SIZ  - 1;
19         *block_size = info.CardBlockSize;
20         ret = USBD_OK;
21     }
22   return ret;
23   /* USER CODE END 3 */
24 }
第二个是块读取函数,SD卡是通过DMA传输数据。  
01 /*******************************************************************************
02 * Function Name  : STORAGE_Read_FS
03 * Description    :
04 * Input          : None.
05 * Output         : None.
06 * Return         : None.
07 *******************************************************************************/
08 int8_t STORAGE_Read_FS (uint8_t lun,
09                         uint8_t *buf,
10                         uint32_t blk_addr,                      
11                         uint16_t blk_len)
12 {
13   /* USER CODE BEGIN 6 */
14       int8_t ret = USBD_FAIL; 
15     
16 //  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
17   
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)
20         {
21             ret = USBD_OK;
22         }
23   
24         /* Wait until transfer is complete */
25         if(ret == USBD_OK)
26         {
27             if(HAL_SD_CheckReadOperation(&hsd1, (uint32_t)100000000) != SD_OK)
28             {
29                 ret = USBD_FAIL;
30             }
31             else
32             {
33                 ret = USBD_OK;
34             }
35         }
36         ret = USBD_OK;
37   }
38   return ret;
39   /* USER CODE END 6 */
40 }
第三个是写操作函数  
01 /*******************************************************************************
02 * Function Name  : STORAGE_Write_FS
03 * Description    :
04 * Input          : None.
05 * Output         : None.
06 * Return         : None.
07 *******************************************************************************/
08 int8_t STORAGE_Write_FS (uint8_t lun,
09                          uint8_t *buf,
10                          uint32_t blk_addr,
11                          uint16_t blk_len)
12 {
13   /* USER CODE BEGIN 7 */
14     int8_t ret = USBD_FAIL;  
15     
16 //  if(BSP_SD_IsDetected() != SD_NOT_PRESENT)
17   {
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)
20         {
21             ret = USBD_OK;
22         }
23   
24         /* Wait until transfer is complete */
25         if(ret == USBD_OK)
26         {
27             if(HAL_SD_CheckWriteOperation(&hsd1, (uint32_t)100000000) != SD_OK)
28             {
29                 ret = USBD_FAIL;
30             }
31             else
32             {
33                 ret = USBD_OK;
34             }
35         }
36   }
37   return ret;
38   /* USER CODE END 7 */
39 }
  注意:Open746I-C中可以通过PC13管脚判断SD卡是否插入到卡槽中,这里为了方便没有用到这个功能。所以上面程序中注释掉了检测SD卡是否准备好这一步。

    编译程序,并下载到开发板,电脑usb线接到Open746I-C的核心板的USB接口中。电脑会提示有U盘插入。  
   

标签:CODE,usb,USBD,FS,hid,USER,stm32cubeide,SD,USB
From: https://www.cnblogs.com/mokongking/p/18657327

相关文章

  • USB子系统驱动 USB通信协议 Type A、Type A 3.0、Type C
    目录USB硬件基础TypeA引脚说明TypeA3.0引脚说明TypeC引脚说明USB驱动你一定需要知道的事USB硬件基础在了解LINUX的USB驱动之前,我们肯定是要了解相关硬件内容的,如下给出了三种常用的USB接口。特性TypeA(2.0)TypeA3.0TypeC接口形状长方形,单向插入与TypeA2......
  • 基于Java异步处理的 USB 设备监控系统设计与实现:技术架构与业务场景分析
    1.引言随着智能设备和物联网技术的快速发展,USB设备在各行各业中的应用越来越广泛。从工业设备到个人电子产品,USB设备已经成为数据传输和设备连接的主流方式。然而,设备的动态插拔和状态变化的检测,成为了许多业务系统中的一个重要挑战。特别是在需要实时响应设备插拔事件......
  • USB tp触摸不准问题
    触摸屏显示是正常的,但是TP不准,触摸的方向也是正确的就是触摸位置不准,屏幕中央触摸位置相对还好,越往边沿越不准,需要添加idc配置文件:touch.deviceType=touchScreendevice.internal=1touch.orientationAware=1keyboard.layout=qwertykeyboard.characterMap=qwerty......
  • CH340C 请求 USB 设备描述符失败
    简短不看版如果出现上述状况,说明线有问题:线的确是数据线(不是电源线),但是不是能与CH340正常通讯的数据线(数据线的数据传输功能有问题。需要更换其它数据线. 前文    该文分享CH340驱动使用过程可能出现的问题,以下出现的问题解决方案都建立在CH340硬件正常的情况下。......
  • wx.hideHomeButton
    wx.hideHomeButton(Objectobject)基础库2.8.3开始支持,低版本需做兼容处理。以Promise风格调用:支持需要页面权限:当前是插件页面时,宿主小程序不能调用该接口,反之亦然小程序插件:不支持微信Windows版:支持微信Mac版:支持微信鸿蒙OS版:支持功能描述隐藏返回首页......
  • wx.hideNavigationBarLoading
    wx.hideNavigationBarLoading(Objectobject)以Promise风格调用:支持需要页面权限:当前是插件页面时,宿主小程序不能调用该接口,反之亦然小程序插件:支持,需要小程序基础库版本不低于2.1.0在小程序插件中使用时,只能在当前插件的页面中调用微信Windows版:支持微信Mac版:支持......
  • wx.hideLoading
    wx.hideLoading(Objectobject)基础库1.1.0开始支持,低版本需做兼容处理。以Promise风格调用:支持小程序插件:支持,需要小程序基础库版本不低于1.9.6微信Windows版:支持微信Mac版:支持微信鸿蒙OS版:支持功能描述隐藏loading提示框参数Objectobject属性......
  • Type c系列接口驱动电路·Type c系列接口驱动电路详解内置供电驱动电路使用USB2.0驱动
    目录Typec常见封装Typec不同系列Typec驱动电路Typec数据手册                                 编写不易,仅供学习,请勿搬运,感谢理解常见元器件驱动电路文章专栏连接LM7805系列降压芯片驱动电路·降压芯片驱动电路详解-CSDN博客ME......
  • 搬运优秀随笔:https://www.cnblogs.com/gaoshidong
    一、第一章:初识Java与面向对象程序设计Java简介:Java是一种面向对象的程序设计语言,具有跨平台、安全性高、可移植性强等特点。面向对象程序设计概述:面向对象是一种程序设计思想,将现实世界的事物抽象为对象,通过对象之间的交互来完成程序的功能。Java开发环境搭建:介绍了Java......
  • wx.onAppHide
    wx.onAppHide(functionlistener)基础库2.1.2开始支持,低版本需做兼容处理。小程序插件:不支持微信鸿蒙OS版:支持功能描述监听小程序切后台事件。该事件与App.onHide的回调参数一致。参数functionlistener小程序切后台事件的监听函数参数Objectoptions切后台......