本章不打算详细讲解USB的协议,本章只是介绍如何通过STM32CubeMX软件生成应用程序。

在看本教程之前建议先看ST官方关于USB的培训视频,示例

一、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文件,找到虚拟串口接收函数。

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

{

/* USER CODE BEGIN 6 */

USBD_CDC_SetRxBuffer(hUsbDevice_0, &Buf[0]);

USBD_CDC_ReceivePacket(hUsbDevice_0);

return (USBD_OK);

/* USER CODE END 6 */

}

修改接收处理函数,接收到的字符打印输出在LCD屏幕上。

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

{

/* USER CODE BEGIN 6 */

uint8_t result = USBD_OK;

uint8_t msg[Len[0]+1];

uint32_t i;

result = USBD_CDC_ReceivePacket(&hUsbDeviceFS);

for(i=0;i

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

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)

{

uint8_t result = USBD_OK;

/* USER CODE BEGIN 7 */

USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);

result = USBD_CDC_TransmitPacket(hUsbDevice_0);

/* USER CODE END 7 */

return result;

}

本教程不调用这个发送函数。在main函数中while循环中添加语法每秒发送一次字符串。

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

USBD_CDC_SetTxBuffer(&hUsbDeviceFS, (uint8_t*)&UserTxBuffer, sizeof(UserTxBuffer));

USBD_CDC_TransmitPacket(&hUsbDeviceFS);

HAL_Delay(1000);

}

/* USER CODE END 3 */

在前面声明发送字符串。

/* USER CODE BEGIN 1 */

uint8_t UserTxBuffer[] = "WaveShare Open7XXI-C Board STM32 Virtual COM Port Driver \r\n";

/* USER CODE END 1 */

在main函数中,while循环前面添加程式初始化LCD。

/* USER CODE BEGIN 2 */

/* Initialize the SDRAM */

BSP_SDRAM_Init();

/* Initialize the LCD */

BSP_LCD_Init();

BSP_LCD_SetLayerVisible(1, DISABLE);

BSP_LCD_SelectLayer(0);

/* Initialize LCD Log module */

LCD_LOG_Init();

/* Show Header and Footer texts */

LCD_LOG_SetHeader((uint8_t *)"Waveshare Electronics");

LCD_LOG_SetFooter((uint8_t *)"WaveShare Open7XXI-C board");

/* USER CODE END 2 */最后添加usbd_cdc.h头文件。

/* USER CODE BEGIN Includes */

#include "stm32746g_sdram.h"

#include "stm32746g_LCD.h"

#include "lcd_log.h"

#include "usbd_cdc.h"

/* 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为每次移动的步长,输入参数为当前的坐标位置。

/* USER CODE BEGIN 4 */

/**

* @brief Gets Pointer Data.

* @param pbuf: Pointer to report

* @retval None

*/

static void GetPointerData(uint8_t *pbuf)

{

int8_t x = 0, y = 0 ;

switch(BSP_JOY_GetState())

{

case JOY_LEFT:

x -= CURSOR_STEP;

break;

case JOY_RIGHT:

x += CURSOR_STEP;

break;

case JOY_UP:

y -= CURSOR_STEP;

break;

case JOY_DOWN:

y += CURSOR_STEP;

break;

default:

break;

}

pbuf[0] = 0;

pbuf[1] = x;

pbuf[2] = y;

pbuf[3] = 0;

}

/**

* @brief SYSTICK callback.

* @retval None

*/

void HAL_SYSTICK_Callback(void)

{

/* NOTE : This function Should not be modified, when the callback is needed,

the HAL_SYSTICK_Callback could be implemented in the user file

*/

static __IO uint32_t counter=0;

/* check Joystick state every polling interval (10ms) */

if (counter++ == USBD_HID_GetPollingInterval(&hUsbDeviceFS))

{

GetPointerData(HID_Buffer);

/* send data though IN endpoint*/

if((HID_Buffer[1] != 0) || (HID_Buffer[2] != 0))

{

USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 4);

}

counter =0;

}

BSP_LED_Toggle(LED1);

}

/* USER CODE END 4 */

HAL_SYSTICK_Callback()为SysTick定时器中断回调函数,时间为1ms。程序中先调用USBD_HID_GetPollingInterval函数读取HID轮询间隔。每隔10MS根据五向摇杆按键更新坐标,并通过USB发到电脑。

添加变量声明

/* USER CODE BEGIN PV */

/* Private variables ---------------------------------------------------------*/

#define CURSOR_STEP 5

uint8_t HID_Buffer[4];

/* USER CODE END PV */添加usbd_hid.h头文件

/* USER CODE BEGIN Includes */

#include "stm32746g_sdram.h"

#include "stm32746g_LCD.h"

#include "lcd_log.h"

#include "usbd_hid.h"

/* 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文件,我们只需修改三个函数既可,第一个是获取存储器容量大小函数,返回块大小,已经块数目。

/*******************************************************************************

* Function Name : STORAGE_GetCapacity_FS

* Description :

* Input : None.

* Output : None.

* Return : None.

*******************************************************************************/

int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)

{

/* USER CODE BEGIN 3 */

HAL_SD_CardInfoTypedef info;

int8_t ret = USBD_FAIL;

// if(BSP_SD_IsDetected() != SD_NOT_PRESENT)

{

HAL_SD_Get_CardInfo(&hsd1, &info);

*block_num = (info.CardCapacity)/STORAGE_BLK_SIZ - 1;

*block_size = info.CardBlockSize;

ret = USBD_OK;

}

return ret;

/* USER CODE END 3 */

}

第二个是块读取函数,SD卡是通过DMA传输数据。

/*******************************************************************************

* Function Name : STORAGE_Read_FS

* Description :

* Input : None.

* Output : None.

* Return : None.

*******************************************************************************/

int8_t STORAGE_Read_FS (uint8_t lun,

uint8_t *buf,

uint32_t blk_addr,

uint16_t blk_len)

{

/* USER CODE BEGIN 6 */

int8_t ret = USBD_FAIL;

// if(BSP_SD_IsDetected() != SD_NOT_PRESENT)

{

/* Read block(s) in DMA transfer mode */

if(HAL_SD_ReadBlocks_DMA(&hsd1,(uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len) == SD_OK)

{

ret = USBD_OK;

}

/* Wait until transfer is complete */

if(ret == USBD_OK)

{

if(HAL_SD_CheckReadOperation(&hsd1, (uint32_t)100000000) != SD_OK)

{

ret = USBD_FAIL;

}

else

{

ret = USBD_OK;

}

}

ret = USBD_OK;

}

return ret;

/* USER CODE END 6 */

}

第三个是写操作函数

/*******************************************************************************

* Function Name : STORAGE_Write_FS

* Description :

* Input : None.

* Output : None.

* Return : None.

*******************************************************************************/

int8_t STORAGE_Write_FS (uint8_t lun,

uint8_t *buf,

uint32_t blk_addr,

uint16_t blk_len)

{

/* USER CODE BEGIN 7 */

int8_t ret = USBD_FAIL;

// if(BSP_SD_IsDetected() != SD_NOT_PRESENT)

{

/* Write block(s) in DMA transfer mode */

if(HAL_SD_WriteBlocks_DMA(&hsd1, (uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len) == SD_OK)

{

ret = USBD_OK;

}

/* Wait until transfer is complete */

if(ret == USBD_OK)

{

if(HAL_SD_CheckWriteOperation(&hsd1, (uint32_t)100000000) != SD_OK)

{

ret = USBD_FAIL;

}

else

{

ret = USBD_OK;

}

}

}

return ret;

/* USER CODE END 7 */

}

注意:Open746I-C中可以通过PC13管脚判断SD卡是否插入到卡槽中,这里为了方便没有用到这个功能。所以上面程序中注释掉了检测SD卡是否准备好这一步。

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

cubemx 读卡器_STM32CubeMX系列教程25:USB Device相关推荐

  1. STM32 基础系列教程 25 - USB_HID_mouse

    前言 学习stm32 USB接口使用,学会用CUBE工具快速创建USB设备工程及调试,关于usb的相关知道请读者提前准备并学习,当然如果不想深究其中原理的话,跟着本文来操作就可以实现基于USB的设备开 ...

  2. HAL库与Cubemx\rt-thread Nano系列教程-01-新建HAL工程及移植RT-Nano到Alios Developer Kit

    Part1教程计划 1第一阶段 基于Alios DevelopeKit开发板(主控STM32L496VGT6); HAL库与cubemx开发,RT_THread作为操作系统使用,仅仅是作为操作系统,目 ...

  3. cubemx 读卡器_STM32CubeMX+Keil实现 STM32F4 SDcard+SPI Flash读卡器

    STM32CubeMX+Keil实现 STM32F4 SDcard+SPI Flash读卡器 STM32CubeMX+Keil实现 STM32F4 SDcard+SPI Flash读卡器 总体流程 S ...

  4. stm32cubemx生成不了keil工程文件_STM32CubeMX系列教程03_创建并生成代码工程

    说明: 本文原创作者『strongerHuang』 首发于微信公众号『嵌入式专栏』,同时也更新在我的个人网站:EmbeddedDevelop 标签:STM32. STM32CubeMX. LL库. H ...

  5. cubemx stm32 配置两个串口_STM32CubeMX系列教程5:串行通信(USART)

    本章以串口为例讲解,HAL 库轮询,中断,DMA 三种编程模型. 1.前情回顾 在串行通信中,一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以"起始位"开 ...

  6. cubemx 读卡器_STM32CubeMX基于SD卡的FATFS文件系统测试

    1.问题描述:使用STM32CubeMX配置SD基于SD卡的FATFS文件系统,并进行测试文件的读写. 2.测试准备: (1)测试环境: 软件平台:STM32CubeMX -4.22.0;KEIL5 ...

  7. Auto.js Pro安卓免ROOT引流脚本开发系列教程25网易公开课(3)-取用户性别

    APP_取用户性别() 返回值类型 说明 整数型 返回值 性别 0 女 1 男 2 无 等待个人资料页出现(判断是否在个人资料页) 判断性别节点是否存在 在性别节点范围内取色 根据色值判断性别 开发文 ...

  8. microbit c语言编程软件,Micro:bit系列教程25:自定义Micro:bit软件包

    cpp代码:/** * 使用此文件来定义自定义函数和图形块. * 想了解更详细的信息,请前往 https://makecode.microbit.org/blocks/custom */ /** * ...

  9. Hyper-V 2016 系列教程25 配置NFS 存储服务器

    一般企业在虚拟化服务器上线后,会有一部分的物理服务器淘汰下来,而这些服务器有的性能虽然不是最好的,但是硬盘却是专业的RAID级别的,甚至还没有过厂家的保修期,所以如果能将这些资源充分利用起来,也能为企 ...

最新文章

  1. whereis php,Linux命令教程之比较搜索命令whereis与which的区别
  2. Practical Common Lisp
  3. centos修改SSH端口并禁用root远程登录
  4. The server time zone value is unrecognized or repr
  5. 51nod 1451 合法三角形 判斜率去重,时间复杂度O(n^2)
  6. 语义化版本(semantic versioning)机制里的一些范围标识符
  7. 转载 - 整数划分问题
  8. [转载] mybatis
  9. Intel OpenCL + Ubuntu安装
  10. android的actionbar及菜单机制,Android ActionBar基本使用方法
  11. CSDN第四届在线编程大赛2014初赛:带通配符的数
  12. 「thunar」给thunar增加搜索文件功能
  13. 学习苹果Swift语言的一些在线资源
  14. Hibernate一对多双向关联
  15. 张季跃 201771010139《面向对象程序设计(java)》第八周学习总结
  16. 2.70-写出具有如下原型的函数的代码:
  17. iPhone所有手机型号屏幕尺寸及H5的CSS适配
  18. openstack搭建教程
  19. webview加载html图片不显示图片,WebView加载网页不显示图片解决办法
  20. Windows下RabbitMQ安装及配置

热门文章

  1. 云计算应用现状与关键技术
  2. NB-IoT地磁双模检测,无布线,电池使用5年,带管理平台,智慧停车场解决方案
  3. 2023上半年软件设计师-试题详解与分析
  4. 大家一起来说一说自己掌握的设计模式和在工作中的应用场景,分享经验
  5. 【逆向】【Android微信】获取微信聊天记录
  6. RKMPP库快速上手--(三)MPP解码入门
  7. VMware虚拟网络编辑器配置
  8. PC使用网线上网的条件下,通过PC的Wifi共享提供手机上网教程
  9. wangeditor封装使用
  10. 智慧工地大型机械监测北斗定位工业终端解决方案