STM32F4全速USB虚拟串口VCP程序裁剪教程
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
上面的 APP_RxBuffer[]是定义的全局变量,这个全局变量到底是干什么的呢, 我们进一步发现 APP_RxBuffer[]在 usbd_cdc_vcp.c 源文件中亦有出现。在 usbd_cdc_vcp.c 源文件中第 624 行到 661 行,阅读这个函数,知道这个函数主 要是将 APP_RxBuffer[]中的数据发送到主机的 IN 端点(关于端点概念不理解的 建议阅读 USB2.0 英文协议)
进一步下向下读程序,是打开了 USART2 的接收中断,通过 USART2 的接收中断接 收数据,并通过 VCP_DataTx(0,0)进行了数据处理,如下图 usbd_cdc_vcp.c 的 第 366 行到 379 行。
下面主要看看 VCP_DataTx(0,0)是怎么处理的,如下图所示是 usbd_cdc_vcp.c 的第 208 行到 228 行。是将通过 USART2 的中断接收的数据放进 APP_RxBuffer[] 中,这里的数组最大长度是 2048。
以及在 app.c 中声明,
同时修改 usbd_cdc_vcp.c 中 static uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len)函数,将 Buf 中的数据放入定义的全局数组变量 Rx_Buffer[]中, 并将长度 Len 赋值给全局变量 Rx_Length。
4>C/C++预定义: USE_STDPERIPH_DRIVER,STM32F4XX,USE_STM324xG_EVAL,USE_USB_OTG_FS 5>打开 USB_conf.h 文件,把 #define VBUS_SENSING_ENABLED 封掉,如果我们 不用 VBUS(PA9)。 否则不用封掉。 6>编译,下载,复位板子,并安装虚拟串口驱动(ST 官网上有),上面的步骤完 成后,计算机中的虚拟串口出来。如果不出来很可能是 D+和 D-的连线问题,请 检查下是否需要连接 ESD 和去耦电容。
这里也用到了两个指针,APP_Rx_Ptr_in 指针,用于写入 FIFO 的起始地址,写
入一个字节,APP_Rx_Ptr_in 要加 1,还有一个是 APP_Rx_ptr_out 指针,用于读 出 FIFO 的起始地址,读出一个字节,APP_Rx_ptr_out 要加 1。 如果 FIFO 中有数据需要发送,状态标志位赋值 USB_Tx_State=1,没有数据需要 发送状态标志位赋值 USB_Tx_State=0。 想发送数据,只要把想发送的数据放入 APP_Rx_Buffer[2048]缓冲,并调用下面 语句既可以,这里的 USB_Tx_ptr,是要发送数据的起始地址,USB_Tx_length 是 要发送数据的长度,如何在主函数调用这个语句呢
7>记得将 Demo 程序的优化等级改成 None,避免跟踪调试时乱跳。
6. STM32F4 的 USB 虚拟串口 Demo 解析
官方例程用 IAR 打开如上图所示,这里主要关注下 app.c 源文件、stm32fxxx_it.c 源文件、usbd_cdc_vcp.c 源文件和 usbd_cdc_core.c 源文件。 1>App.c 源文件有 main 函数,main 函数主要是 USBD_Init()语句,是对 USB 虚 拟串口设备的初始化,进行添加自己的语句也主要是在 while(1)语句里。 2>初始化后,USB 的枚举及传输数据都是在 stm32fxxx_it.c 的中断中发起的。 枚举是在中断和底层驱动及内核中完成的,这里不用管,也不需要改动。 3>对于数据的传输是我们关心的是在 usbd_cdc_vcp.c 中,阅读例程,我们可以 发现,USBD_Init()语句初始化时初始化了两个串口:COM1 和 EVAL_COM1,如下 图 usbd_cdc_vcp.c 的第 106 行到 109 行;其中 COM1 是虚拟出来的串口,即 USART0, 而 EVAL_COM1 是真实存在的 USART2,挂载在 APB1 总线上,详见 stm32f407xx 数 据手册。
通过以上分析不难得出 Demo 程序的功能就是: 通过 PC 端的串口小助手下发数据到下位机,下位机通过串口中断接收到数据放 在 APP_Rx_Buffer,通过 USB 转发给上位机的 USB 的 IN 端点;同时也可以 PC 通 过 USB 接口的 OUT 端点下发数据到下位机的 USB_Rx_Buffer 数组中,并通过 UART 发送到 PC 端的串口小助手。 功能如下面框图所示。
而 BUF 数据的来源是哪里呢,我们通过查找是通过 APP_FOPS 结构体和 VCP_fops 结构体衔接在一起的,所以下面的程序来源就 usbd_cdc_vcp.c 源文件中第 69 行到 76 行,关于 VCP_fops 的定义。
以及 usbd_cdc_core.c 的 136 行,将 VCP_fops 和 APP_FOPS 联系到一起,下面 APP_FOPS 都干了些什么?
5. STM32F4 的 USB 虚拟串口 Demo 的使用
1>下载 STM32 的官方例程:STM32_USB-Host-Device_Lib_V2.1.0 2>开发板自己准备,要求 PA11,PA12 连接 D+,D-,PA9 是否连接 VBUS 都可以 3>打开例程: STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\VCP\EWAR M 里的工程配置 cpu 为 stm32F407IG,
其中在 usbd_cdc_core.c 的 671 到 689 行利用到了 APP_FOPS,通过联系上下文 可 以 知 道 这 个 函 数 是 通 过 usb 的 out 端 点 接 收 主 机 发 来 的 数 据 放 在 USB_Rx_Buffer 中,其中 USB_Rx_Cnt 就是存放在 USB_Rx_Buffer 的数据长度。 因为 VCP_fops 和 APP_FOPS 联系到一起,所以就不难理解上面的 BUF 就是 USB 通过 OUT 端口接收的数据。
4. STM32F4 的 USB 的中断作用
STM32 的 USB 模块可以产生三种中断:USB 唤醒中断、USB 高优先级中断和 USB 低优先级中断,在 STM32 的参考手册中没有详细说明这三种中断对应哪些事件, 现说明如下: 1)USB 唤醒中断:在中断向量表中的位置是 42。这个中断在 USB 设备从暂停模 式唤醒时产生,唤醒事件由 USB_ISTR 寄存器的 WKUP 位标识。 2)USB 高优先级中断:在中断向量表中的位置是 19。这个中断仅由 USB 同步 (Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,正 确传输事件由 USB_ISTR 寄存器的 CTR 位标识。 3)USB 低优先级中断:在中断向量表中的位置是 20。这个中断由所有其它的 USB 事件产生,例如正确传输(不包括同步模式和双缓冲块模式)、USB 复位等,事件 标志位在 USB_ISTR 寄存器中。 在 STM32 的 USB 开发包的例子中包含了上述中断的处理,例如在 USB 扬声器的例 子中,CTR_HP 函数处理 USB 高优先级中断;在所有例子中都有 USB_Istr()函数 处理 USB 低优先级中断。
2. 如何区分全速设备和高速设备
USB 如何区分低速、全速和高速设备:对于全速和高速设备,上拉电阻是接在 D+ 上;而低速设备则是上拉电阻接在 D-上。
3. USB 枚举过程
(1)USB 主机检测到 USB 设备插入后,对设备复位。 (2)USB 主机对设备发送获取设备描述符的标准请求。 (3)设备收到该请求后,在数据过程将设备描述符返回给主机。
这样以后,USB 接收的数据就可以在 app.c 中使用了,这里的接收的数据长度是 根据接收的数据不断清 0,并赋值的,所以可以根据 Rx_Length 大于 0,判断是 否有新的数据接收。
综上所述,USB 的接收是放在 USB_Rx_Buffer[CDC_DATA_MAX_PACKET_SIZE]数组 中,所以只要在主函数中引用就行,但是因为没办法获取 USB_Rx_Buffer[]中存 储的数据长度,在这引入一个全局数组变量,在 usbd_cdc_vcp.c 中定义:
并在 usbd_cdc_vcp.h 中声明,
整理以上的信息,我们就不难理解以上函数牵扯的功能是,USART2 中断接收的 数据放在 APP_RxBuffer[]中,而又通过 APP_RxBuffer[]发送的 USB 上位机上。
下面继续阅读 usbd_cdc_vcp.c 中的程序,如下图所示是 usbd_cdc_vcp.c 源文件 的第 245 行到 256 行,功能是将 BUF 中的数据通过 USART2 发送到主机 PC。
首先了解下 USB 的接收缓冲区,USB_Rx_Buffer[CDC_DATA_MAX_PACKET_SIZE]这 里的 CDC_DATA_MAX_PACKET_SIZE=64,也即是一个包最大的接收量。 再次了解下 APP_Rx_Buffer[APP_RX_DATA_SIZE]的 FIFO 环形缓冲区,这 里,APP_RX_DATA_SIZE=2048,即 2KB 字节,主要用于上发数据:
(4)主机在成功获取到一个数据包的设备描述符后并且确认无错误后,返回一 个 0 长度的状态数据包给设备。 (5)主机再对设备复位一下,接下来进入到设置地址阶段。 (6)USB 主机发出一个设置地址的请求,地址包含在建立包中。 (7)USB 设备在收到地址后,返回 0 长度的状态包。 (8)主机收到 0 长度的状态包之后,返回一个 ACK。 (9)设备在收到这个 ACK 之后,就可以启用新的地址了。 USB 一直进中断的原因:主机每 1ms 就给设备发送一个 sof,3ms 没反应主机就 挂起。所以一直进中断属于正常现象。
7. STM32F4 的 USB 虚拟串口 Demo 裁剪
下面讲解下如何裁剪 Demo 程序达到如下框图所示功能,就是收发数据都是通过 USB 口。这里主要讲解上位机下发的数据,下位机收到后立马转发到上位机。
想只用 USB,就要把 UART 的中断接收语句 void EVAL_COM_IRQHandler(void)禁 止掉,在 usbd_cdc_vcp.c 文件的最后
基于 STM32_USB-Host-Device_Lib_V2.1.0 或 V2.2.0 官方 DEMO 例程的 STM32F4 全速 USB 虚拟串口 VCP 程序裁剪
教程
1. 概述Baidu Nhomakorabea
本文档是基于 STM32_USB-Host-Device_Lib_V2.1.0 官方库中 Device 下 STM32F4 全速 VCP 裁剪的,主要是利用 STM32F4 已有资源,代替 UART 串口,用于和上位 机进行通信,理论最大通信速率是 64*19*8b/1ms=950kbps,这里的 64 是 1 个包 数据量 64 个字节,19 是一帧最大是 19 个包,8 是一个字节 8 位,1ms 是一帧的 时间,详见 USB2.0 英文协议。如果想开发更高速模式下的通信,可以考虑使用 高速模式下的 VCP 通信,本文档也可以作为参考。 以下是列举的准备工作: 1>下载 STM32_USB-Host-Device_Lib_V2.1.0 官方库,同时去 ST 官方下载 UM1021 关于本例程的说明文档。可以在 ST 官方下载,找不到的也可以去 STMCU 论坛搜 索。 2>本文档的图片是基于 IAR6.4 开发环境进行截图。 3>下载 USB2.0 英文协议。需要了解 USB 的枚举,以及 USB 的工作机制,对每次 发起通信都是由主机轮询开始的有清晰的认识,并重点看一下批量传输。有条件 的可以借用 USB480 协议分析仪。 4>阅读 STM32F4 数据手册中关于 USB 的一些寄存器的介绍。
进一步下向下读程序,是打开了 USART2 的接收中断,通过 USART2 的接收中断接 收数据,并通过 VCP_DataTx(0,0)进行了数据处理,如下图 usbd_cdc_vcp.c 的 第 366 行到 379 行。
下面主要看看 VCP_DataTx(0,0)是怎么处理的,如下图所示是 usbd_cdc_vcp.c 的第 208 行到 228 行。是将通过 USART2 的中断接收的数据放进 APP_RxBuffer[] 中,这里的数组最大长度是 2048。
以及在 app.c 中声明,
同时修改 usbd_cdc_vcp.c 中 static uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len)函数,将 Buf 中的数据放入定义的全局数组变量 Rx_Buffer[]中, 并将长度 Len 赋值给全局变量 Rx_Length。
4>C/C++预定义: USE_STDPERIPH_DRIVER,STM32F4XX,USE_STM324xG_EVAL,USE_USB_OTG_FS 5>打开 USB_conf.h 文件,把 #define VBUS_SENSING_ENABLED 封掉,如果我们 不用 VBUS(PA9)。 否则不用封掉。 6>编译,下载,复位板子,并安装虚拟串口驱动(ST 官网上有),上面的步骤完 成后,计算机中的虚拟串口出来。如果不出来很可能是 D+和 D-的连线问题,请 检查下是否需要连接 ESD 和去耦电容。
这里也用到了两个指针,APP_Rx_Ptr_in 指针,用于写入 FIFO 的起始地址,写
入一个字节,APP_Rx_Ptr_in 要加 1,还有一个是 APP_Rx_ptr_out 指针,用于读 出 FIFO 的起始地址,读出一个字节,APP_Rx_ptr_out 要加 1。 如果 FIFO 中有数据需要发送,状态标志位赋值 USB_Tx_State=1,没有数据需要 发送状态标志位赋值 USB_Tx_State=0。 想发送数据,只要把想发送的数据放入 APP_Rx_Buffer[2048]缓冲,并调用下面 语句既可以,这里的 USB_Tx_ptr,是要发送数据的起始地址,USB_Tx_length 是 要发送数据的长度,如何在主函数调用这个语句呢
7>记得将 Demo 程序的优化等级改成 None,避免跟踪调试时乱跳。
6. STM32F4 的 USB 虚拟串口 Demo 解析
官方例程用 IAR 打开如上图所示,这里主要关注下 app.c 源文件、stm32fxxx_it.c 源文件、usbd_cdc_vcp.c 源文件和 usbd_cdc_core.c 源文件。 1>App.c 源文件有 main 函数,main 函数主要是 USBD_Init()语句,是对 USB 虚 拟串口设备的初始化,进行添加自己的语句也主要是在 while(1)语句里。 2>初始化后,USB 的枚举及传输数据都是在 stm32fxxx_it.c 的中断中发起的。 枚举是在中断和底层驱动及内核中完成的,这里不用管,也不需要改动。 3>对于数据的传输是我们关心的是在 usbd_cdc_vcp.c 中,阅读例程,我们可以 发现,USBD_Init()语句初始化时初始化了两个串口:COM1 和 EVAL_COM1,如下 图 usbd_cdc_vcp.c 的第 106 行到 109 行;其中 COM1 是虚拟出来的串口,即 USART0, 而 EVAL_COM1 是真实存在的 USART2,挂载在 APB1 总线上,详见 stm32f407xx 数 据手册。
通过以上分析不难得出 Demo 程序的功能就是: 通过 PC 端的串口小助手下发数据到下位机,下位机通过串口中断接收到数据放 在 APP_Rx_Buffer,通过 USB 转发给上位机的 USB 的 IN 端点;同时也可以 PC 通 过 USB 接口的 OUT 端点下发数据到下位机的 USB_Rx_Buffer 数组中,并通过 UART 发送到 PC 端的串口小助手。 功能如下面框图所示。
而 BUF 数据的来源是哪里呢,我们通过查找是通过 APP_FOPS 结构体和 VCP_fops 结构体衔接在一起的,所以下面的程序来源就 usbd_cdc_vcp.c 源文件中第 69 行到 76 行,关于 VCP_fops 的定义。
以及 usbd_cdc_core.c 的 136 行,将 VCP_fops 和 APP_FOPS 联系到一起,下面 APP_FOPS 都干了些什么?
5. STM32F4 的 USB 虚拟串口 Demo 的使用
1>下载 STM32 的官方例程:STM32_USB-Host-Device_Lib_V2.1.0 2>开发板自己准备,要求 PA11,PA12 连接 D+,D-,PA9 是否连接 VBUS 都可以 3>打开例程: STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\VCP\EWAR M 里的工程配置 cpu 为 stm32F407IG,
其中在 usbd_cdc_core.c 的 671 到 689 行利用到了 APP_FOPS,通过联系上下文 可 以 知 道 这 个 函 数 是 通 过 usb 的 out 端 点 接 收 主 机 发 来 的 数 据 放 在 USB_Rx_Buffer 中,其中 USB_Rx_Cnt 就是存放在 USB_Rx_Buffer 的数据长度。 因为 VCP_fops 和 APP_FOPS 联系到一起,所以就不难理解上面的 BUF 就是 USB 通过 OUT 端口接收的数据。
4. STM32F4 的 USB 的中断作用
STM32 的 USB 模块可以产生三种中断:USB 唤醒中断、USB 高优先级中断和 USB 低优先级中断,在 STM32 的参考手册中没有详细说明这三种中断对应哪些事件, 现说明如下: 1)USB 唤醒中断:在中断向量表中的位置是 42。这个中断在 USB 设备从暂停模 式唤醒时产生,唤醒事件由 USB_ISTR 寄存器的 WKUP 位标识。 2)USB 高优先级中断:在中断向量表中的位置是 19。这个中断仅由 USB 同步 (Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,正 确传输事件由 USB_ISTR 寄存器的 CTR 位标识。 3)USB 低优先级中断:在中断向量表中的位置是 20。这个中断由所有其它的 USB 事件产生,例如正确传输(不包括同步模式和双缓冲块模式)、USB 复位等,事件 标志位在 USB_ISTR 寄存器中。 在 STM32 的 USB 开发包的例子中包含了上述中断的处理,例如在 USB 扬声器的例 子中,CTR_HP 函数处理 USB 高优先级中断;在所有例子中都有 USB_Istr()函数 处理 USB 低优先级中断。
2. 如何区分全速设备和高速设备
USB 如何区分低速、全速和高速设备:对于全速和高速设备,上拉电阻是接在 D+ 上;而低速设备则是上拉电阻接在 D-上。
3. USB 枚举过程
(1)USB 主机检测到 USB 设备插入后,对设备复位。 (2)USB 主机对设备发送获取设备描述符的标准请求。 (3)设备收到该请求后,在数据过程将设备描述符返回给主机。
这样以后,USB 接收的数据就可以在 app.c 中使用了,这里的接收的数据长度是 根据接收的数据不断清 0,并赋值的,所以可以根据 Rx_Length 大于 0,判断是 否有新的数据接收。
综上所述,USB 的接收是放在 USB_Rx_Buffer[CDC_DATA_MAX_PACKET_SIZE]数组 中,所以只要在主函数中引用就行,但是因为没办法获取 USB_Rx_Buffer[]中存 储的数据长度,在这引入一个全局数组变量,在 usbd_cdc_vcp.c 中定义:
并在 usbd_cdc_vcp.h 中声明,
整理以上的信息,我们就不难理解以上函数牵扯的功能是,USART2 中断接收的 数据放在 APP_RxBuffer[]中,而又通过 APP_RxBuffer[]发送的 USB 上位机上。
下面继续阅读 usbd_cdc_vcp.c 中的程序,如下图所示是 usbd_cdc_vcp.c 源文件 的第 245 行到 256 行,功能是将 BUF 中的数据通过 USART2 发送到主机 PC。
首先了解下 USB 的接收缓冲区,USB_Rx_Buffer[CDC_DATA_MAX_PACKET_SIZE]这 里的 CDC_DATA_MAX_PACKET_SIZE=64,也即是一个包最大的接收量。 再次了解下 APP_Rx_Buffer[APP_RX_DATA_SIZE]的 FIFO 环形缓冲区,这 里,APP_RX_DATA_SIZE=2048,即 2KB 字节,主要用于上发数据:
(4)主机在成功获取到一个数据包的设备描述符后并且确认无错误后,返回一 个 0 长度的状态数据包给设备。 (5)主机再对设备复位一下,接下来进入到设置地址阶段。 (6)USB 主机发出一个设置地址的请求,地址包含在建立包中。 (7)USB 设备在收到地址后,返回 0 长度的状态包。 (8)主机收到 0 长度的状态包之后,返回一个 ACK。 (9)设备在收到这个 ACK 之后,就可以启用新的地址了。 USB 一直进中断的原因:主机每 1ms 就给设备发送一个 sof,3ms 没反应主机就 挂起。所以一直进中断属于正常现象。
7. STM32F4 的 USB 虚拟串口 Demo 裁剪
下面讲解下如何裁剪 Demo 程序达到如下框图所示功能,就是收发数据都是通过 USB 口。这里主要讲解上位机下发的数据,下位机收到后立马转发到上位机。
想只用 USB,就要把 UART 的中断接收语句 void EVAL_COM_IRQHandler(void)禁 止掉,在 usbd_cdc_vcp.c 文件的最后
基于 STM32_USB-Host-Device_Lib_V2.1.0 或 V2.2.0 官方 DEMO 例程的 STM32F4 全速 USB 虚拟串口 VCP 程序裁剪
教程
1. 概述Baidu Nhomakorabea
本文档是基于 STM32_USB-Host-Device_Lib_V2.1.0 官方库中 Device 下 STM32F4 全速 VCP 裁剪的,主要是利用 STM32F4 已有资源,代替 UART 串口,用于和上位 机进行通信,理论最大通信速率是 64*19*8b/1ms=950kbps,这里的 64 是 1 个包 数据量 64 个字节,19 是一帧最大是 19 个包,8 是一个字节 8 位,1ms 是一帧的 时间,详见 USB2.0 英文协议。如果想开发更高速模式下的通信,可以考虑使用 高速模式下的 VCP 通信,本文档也可以作为参考。 以下是列举的准备工作: 1>下载 STM32_USB-Host-Device_Lib_V2.1.0 官方库,同时去 ST 官方下载 UM1021 关于本例程的说明文档。可以在 ST 官方下载,找不到的也可以去 STMCU 论坛搜 索。 2>本文档的图片是基于 IAR6.4 开发环境进行截图。 3>下载 USB2.0 英文协议。需要了解 USB 的枚举,以及 USB 的工作机制,对每次 发起通信都是由主机轮询开始的有清晰的认识,并重点看一下批量传输。有条件 的可以借用 USB480 协议分析仪。 4>阅读 STM32F4 数据手册中关于 USB 的一些寄存器的介绍。