STM32CubeMX系列教程25:USB Device

发布者:婉如Chanel最新更新时间:2020-06-19 来源: eefocus关键字:STM32CubeMX系列  USB  Device 手机看文章 扫描二维码
随时随地手机看文章

本章不打算详细讲解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文件,找到虚拟串口接收函数。

1static 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屏幕上。

1static 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


如下为发送函数,程序中先设置发送字符,然后发送包。这里注意一点,Cube软件初始化的USB结构体是hUsbDeviceFS,这里操作的结构体是hUsbDevice_0。故这个函数不能直接调用,必须先CDC_Init_FS()函数初始化才能用这个函数,初始化中包含有这个语句hUsbDevice_0 = &hUsbDeviceFS。


1uint8_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 */
2uint8_t UserTxBuffer[] = "WaveShare Open7XXI-C Board STM32 Virtual COM Port Driver rn";
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虚拟串口驱动才能设别虚拟串口。


三、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  */
07static 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  */
42void 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
4uint8_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*******************************************************************************/
08int8_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*******************************************************************************/
08int8_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}


[1] [2]
关键字:STM32CubeMX系列  USB  Device 引用地址:STM32CubeMX系列教程25:USB Device

上一篇:STM32CubeMX系列教程26:USB HOST
下一篇:STM32CubeMX系列教程24:STemWim移植

推荐阅读最新更新时间:2024-11-21 12:58

Silicon Labs推出USB接口IC 简化触摸屏开发
Silicon Laboratories (芯科实验室有限公司, NASDAQ: SLAB)今日发表CP2501 USB触摸屏桥接器IC,该芯片可以简化大屏显示运算处理系统中触摸控制器与主机CPU之间的桥接。凡是配置触摸屏显示器的笔记本电脑、平板电脑、电子书、移动网络装置(MID)、信息站、自动柜员机,以及其它的销售时点(POS)设备,新推出的CP2501 USB触摸屏桥接器都能提供可编程且易于使用的USB接口。 CP2501为业界唯一具备预先编程触摸屏USB接口软件的桥接芯片,为大型触摸屏提供了易于使用的USB接口支持。在目前的应用处理系统中,触摸屏系统经常使用USB接口来连接触摸屏控制器与主机CPU,但现在市面上
[嵌入式]
Silicon Labs推出<font color='red'>USB</font>接口IC  简化触摸屏开发
STM32L0开发笔记8: USB驱动的移植
现在使用的STM32L053R8T6单片机带有USB接口,原先一直使用UART转USB芯片来完成USB功能的支持,现在这款单片机带了就希望使用以下。由于已经建立了自己的工程目录,再重新使用STM32CubeMX生成的工程文件,重新建立是不显示的,所以本文探索将USB驱动文件移植到自己项目中的方法,我使用的是USB的CDCD类,步骤如下: 1、使用STM32CubeMX使能USB,如下图所示: 2、设置时钟,USB需要48M时钟,使用内部和外部均可,我这里使用外部时钟。 3、生成工程文件。 4、在自己的工程目录中加入如下图所示的2个文件,如果此2个文件不存在,则从新生成的工程目录中复制即可(包含
[单片机]
独立 1.2A 锂离子电池充电器自动选择 USB 和交流适配器输入
2006 年 11 月 9 日 - 北京 - 凌力尔特公司( Linear Technology Corporation )推出独立双输入线性电池充电器 LTC4096/X 。这些器件用交流适配器或 USB 电源对单节锂离子 / 聚合物电池充电。 LTC4096/X 采用恒定电流 / 恒定电压算法充电,可编程充电电流用交流适配器电源时高达 1.2A ,而用 USB 电源时高达 1A ,同时还可自动检测每个输入端电压的存在。应用包括 PDA 、 MP3 播放器、数码相机、轻型便携式医疗和测试设备以及大彩屏蜂窝电话。
[新品]
USB 3.1芯片未战价先跌 英特尔市占急拉强袭祥硕
整合USB 3.1控制器的100系列主机板(MB)即将出货,当中不仅MB厂厮杀惨烈,英特尔(Intel)与祥硕对决的USB 3.1芯片战况也备受关注。 据了解,为拉升市占,双方报价跌速超乎预期,祥硕方案已跌破3美元,而传输速度远胜祥硕方案的英特尔芯片,由10美元一路向下,现已不到6美元,除获技嘉力挺外,也取得华硕、微星采用,使得击退威锋等台厂的祥硕,原预期可拿下USB 3.1芯片大宗版图目标恐难实现。 随着苹果(Apple)新款MacBook率先导入应用,以及英特尔Skylake平台将于8月亮相,传输效率与供电能力大幅提升的USB 3.1以及正反皆可插的Type-C关注度显著提高,市场料将掀起一波全新装置革命,新旧应用所
[手机便携]
STM32 基础系列教程 24 - USB_HID_key
前言 学习stm32 USB接口使用,学会用CUBE工具快速创建USB设备工程及调试,关于usb的相关知道请读者提前准备并学习,当然如果不想深究其中原理的话,跟着本文来操作就可以实现基于USB的设备开发了。需要提示的是,stm32在使用usb接口功能是一般需要在DP引脚上上拉一个1.5K电阻到3.3V(部分MCU内部会上拉)。 示例详解 基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。 本示例所用的最小系统板原理图: 从本节开始,关于CUBEMX工具及KEIL工具的操作将不再细讲,如
[单片机]
STM32 基础<font color='red'>系列</font>教程 24 - <font color='red'>USB</font>_HID_key
混和信号数字示波器在通用串行总线开发中的应用
  在嵌入式系统的开发过程中,串行总线的协议分析一直是一件令工程师头疼的工作。在有逻辑分析仪的情况下,工程师需要进行复杂的触发条件设定,才能捕获到需要的数据,这样既需要昂贵的设备投资也要花费大量的时间进行仪器设置;随着示波器技术的不断发展,串行总线触发和分析功能在一些高端示波器中出现,并受到嵌入式工程师的欢迎。但不同厂家的示波器在串行总线分析方面的功能和性能是有很大区别的。   使用示波器进行串行总线触发   使用普通示波器只能进行一般的边沿触发和脉宽触发,很难捕捉到复杂的串行总线波形。而使用带有串行总线触发功能的示波器可以方便地捕获到需要的串行数据。横河公司的DLM2000系列数字示波器支持多种常用串行总线的触发,包括CAN/
[测试测量]
混和信号数字示波器在<font color='red'>通用串行总线</font>开发中的应用
赛普拉斯推出汽车级USB-C控制器,用于车载快充设备
先进嵌入式系统解决方案的领导者赛普拉斯半导体公司(纳斯达克股票代码:CY)近日宣布推出支持协商供电(PD)功能的高集成度可编程汽车级USB-C控制器。这款适用于汽车的EZ-PD™CCG2控制器通过了USB-IF(USB开发者论坛)的认证,为汽车客户提供即插即用的USB-C用户体验。这款集成控制器符合PD 2.0标准,能有效地降低系统成本,提高充电速度。 赛普拉斯有线连接事业部副总裁Ajay Srikrishna表示:“市场对移动设备快速充电的需求日益增加,这带动了车内USB-C协商供电的应用。我们的汽车级EZ-PD CCG2控制器针对车内充电端口和信息娱乐端口进行了优化,并且与顶级汽车供应商一起设计,从而实现快速充电和通用连接
[汽车电子]
USB在汽车中的应用
消费电子和汽车电子的汇聚,包括作为系统内串行总线的USB协议的采用将会继续下去。USB提供了一个具有成本效益的和令人理解的接口,在消费者和汽车系统之间建立了联系。 20世纪末,毋庸置疑最成功和最广泛使用的串行接口就是通用串行总线(USB)。其成功的秘诀是其简单化、实用化及广大用户的广泛采用。表面上,设计者能选择的标准化物理连接器仅有几个。连接器本身表明了USB应用(即主机或设备)的“风格”。利用这个简单的四线接口(VCC、D+、 D-、 GND),提供了一个功率为2.5W以及串行数据时钟速率为480MBps的节点。该标准在一个总线上能支持127个设备。协议包括一个“即插即用”功能(如列举),这有利于软件和驱动器的握手和兼
[汽车电子]
<font color='red'>USB</font>在汽车中的应用
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved