STM32F103芯片集成了USB2.0 Full-Speed接口,可以用作与外部设备进行通信,如电脑。基本连接如下:其中,V3P3是USB接口VBUS通过LDO转换为3.3V。
因为STM32F103内部没有集成USB2.0 Full-Speed的上拉电阻,因此外接上拉电阻(详细见上篇文章“USB2.0系列—HID设备”),然后将MCU_DM和MCU_DP分别接MCU的DM和DP,即可实现USB2.0Full-speed硬件配置。
关于STM32F103的Firmware,本文采用了STM32CubeIDE自动产生相应的参考代码,配置信息如下:
通过配置上述参数,然后即可生成相应的参考代码。注意:这个生产的参考代码是不完整的,不能直接用的。还需要填写Report Descriptor数据(详细见上篇文章“USB2.0系列—HID设备”)。打开USB_Device-->App-->usbd_custom_hid_if.c文件,找到下面的定义,将其大学内容书写完整。如下图所示:(数一下下面这个数组的Byte数为38,将上面配置中的Report Descriptor数目改为38,OUT Report Bytes设置为64)
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
/* USER CODE BEGIN 0 */
0x05, 0x8c, //0x05:USAGE PAGE
0x09, 0x00, //0x09:USAGE
0xA1, 0x00, //0xA1:COLLECTION
//下面开始数据配置
0x09, 0x00, //0x09:USAGE
0xA1, 0x00, //0xA1:COLLECTION
0x09, 0x00, //0x09:USAGE
0x15, 0x00, //0x15:LOGICAL MIN 最小数为0x00
0x26, 0xFF, 0x00, //0x26:LOGICAL MAX 最大数为0XFF
0x75, 0x08, //0x75:REPORT SIZE;0x08:8位bit
0x95, 0x40, //0x95:REPORT COUNT;0x40:最大64 bytes传输
0x91, 0x02, //0x91:OUTPUT;0x02:Var(可变量)
//上面OUT格式
0x09, 0x00, //0x09:USAGE
0x15, 0x00, //0x15:LOGICAL MIN
0x26, 0xFF, 0x00, //0x26:LOGICAL MAX
0x75, 0x08, //0x75:REPORT SIZE
0x95, 0x40, //0x95:REPORT COUNT
0x81, 0x02, //0x81:INPUT; 0x02:Var(可变量)
//上面IN格式
//有两个 COLLECTION,就需要两个END COLLECTION
0xC0, //END COLLECTION
/* USER CODE END 0 */
0xC0 /* END_COLLECTION */
};
然后设置USB接收的中断优先级,我这里设置为6,根据不同的需求进行调整。
另外,USB的时钟只能设置为48M,因此在设置Clock的时候要尤其注意,见下图所示:
这样,我们的STM32下位机插入电脑之后,电脑就会认为是HID设备,在电脑上打开USBTreeView.exe。可以看到我们设置的是否正确,如果是以上面的配置设置,那么电脑端应该显示如下:
那么,设备可以识别了,那么Firmware中通信要怎么弄呢?调用两个函数即可:
uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,uint8_t *report,uint16_t len);
//上面为STM32向主机发送数据
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state);
//上面为STM32接收到HOST的数据会执行的函数,这个函数需要自己完善,我自己完善的数据如下:
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
/* USER CODE BEGIN 6 */
USBD_CUSTOM_HID_HandleTypeDef *hhid_temp=(USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData; //STM32会将数据存储的位置
usb_status_t *usb_status_temp=get_usb_status();//自己定义的数组存储位置
uint8_t temp=0;
for(;temp<64;temp++)
{
usb_status_temp->usb_receive_data.usb_buffer[index]=hhid_temp->Report_buf[index];
}
//usb_status_temp->usb_receive_data.usb_buffer[index]将存储接受的数据,用来做你想要做的。
return (USBD_OK);
/* USER CODE END 6 */
}
另外提醒一下:
在USB上电初始化之后,最好检查一下USB是否配置完成(即与HOST的初始通信是否建立),然后进行相关的USB操作。hUsbDeviceFS.dev_config!=0并且hUsbDeviceFS.dev_address!=0。只要这两个参数不为0,那么表示USB的设备通信已经建立完成,否则则是有问题的。
USB HID接口建立完成,那么我们的HOST端(即电脑要怎么弄呢?),下一篇会介绍一下用C#实现简单的上位机软件与STM32进行通信。