一:USB知识分享:
USB ,是英文 Universal Serial BUs(通用串行总线)的缩写,而其中文简称为“通串线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。
标准 USB 共四根线组成,除 VCC/GND 外,另外为 D+,D-; 这两根数据线采用的是差分电压的方式进行数据传输的。在 USB 主机上,D-和 D+都是接了 15K 的电阻到低的,所以在没有设备接入的时候,D+、D-均是低电平。而在 USB 设备中,如果是高速设备,则会在 D+上接一个 1.5K 的电阻到 VCC,而如果是低速设备,则会在 D-上接一个 1.5K 的电阻到 VCC。这样当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。
接下来,我们简单介绍一下 STM32 的 USB 控制器。
STM32F103 的 MCU 自带 USB 从控制器,符合 USB 规范的通信连接;PC 主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被 USB 外设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用 512 字节缓冲区(专用的 512 字节,和 CAN 共用),最多可用于 16 个单向或8个双向端点。USB 模块同 PC 主机通信,根据 USB 规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。整个传输的格式由硬件完成,其中包括 CRC的生成和校验。
每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数。当 USB 模块识别出一个有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随之发生相关的数据传输。USB 模块通过一个内部的 16 位寄存器实现端口与专用缓冲区的数据交换。在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。在数据传输结束时,USB 模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的中断来处理。
二:STM32 cube MX 软件配置过程:
2.1 原理图分享:

这里需要注意下,PE5引脚的配置,需要将PE5引脚置为高电平,从而将USB的D+,进入高电平,使电脑可以识别到USB设备,当时也是没有注意到这一点,查了半天才发现。(主要是自己疏忽了,之前使用库函数开发时候,这里都是直接焊接个电阻拉高的)
2.2 STM32 cube MX 软件的配置如下:


值得注意的是,需要将工程代码的栈加大,防止栈溢出,导致程序进入硬件错误。
三:软件代码编写:
注意:调试在之前的代码上添加功能。
定义USB相关的变量:
//USB 相关变量
uint8_t UsbPackFlag ; //接收一组完整的数据包
uint16_t UsbRxLength ; //实际接收的长度
uint16_t UsbTxLength ; //实际发送的长度
uint8_t UsbTxBuffer[UsbLengthData] ; //USB发送的数据
uint8_t UsbRxBuffer[UsbLengthData] ; //USB接收的数据
在USB接收的函数中,将收到的数据拷贝出来:
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
// CDC_Transmit_FS(Buf,Len[0]);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
memcpy(&UsbRxBuffer,Buf,Len[0]) ;
UsbRxLength = Len[0] ;
UsbPackFlag = 1 ;
return (USBD_OK);
/* USER CODE END 6 */
}
在定时器回调函数中,将USB收到的数据通过串口1回传到电脑:
if(Time6point %10 == 0)
{
if( UsbPackFlag ==1)
{
UsbPackFlag = 0 ;
HAL_UART_Transmit(&huart1, UsbRxBuffer, UsbRxLength, 0xffff);
memset(UsbRxBuffer,0,sizeof (UsbRxBuffer));
}
}
实际测试图如下所示:


感想:实测使用STM32 cubeMX软件,配置USB的CDC功能很方便,只是在学习需要根据实际的情况,进行配置使usb D+引脚接入高电平,否则电脑识别不到串口。
全部评论