/* configure USB capabilities */
(void)usb_basic_init (&udev->bp, &udev->regs, core);
usb_globalint_disable(&udev->regs);
/* initializes the USB core*/
(void)usb_core_init (udev->bp, &udev->regs);
/* set device disconnect */
usbd_disconnect (udev);
#ifndef USE_OTG_MODE
usb_curmode_set(&udev->regs, DEVICE_MODE);
#endif /* USE_OTG_MODE */
/* initializes device mode */
(void)usb_devcore_init (udev);
usb_globalint_enable(&udev->regs);
/* set device connect */
usbd_connect (udev);
udev->dev.cur_status = (uint8_t)USBD_DEFAULT;
}
配置USB中断函数如下。
C
void usb_intr_config(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
#ifdef USE_USB_FS
nvic_irq_enable((uint8_t)USBFS_IRQn, 3U, 0U);
#if USBFS_LOW_POWER
/* enable the power module clock */
rcu_periph_clock_enable(RCU_PMU);
/* USB wakeup EXTI line configuration */
exti_interrupt_flag_clear(EXTI_18);
exti_init(EXTI_18, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_enable(EXTI_18);
nvic_irq_enable((uint8_t)USBFS_WKUP_IRQn, 0U, 0U);
#endif /* USBFS_LOW_POWER */
#elif defined(USE_USB_HS)
nvic_irq_enable((uint8_t)USBHS_IRQn, 3U, 0U);
#if USBHS_LOW_POWER
/* enable the power module clock */
rcu_periph_clock_enable(RCU_PMU);
/* USB wakeup EXTI line configuration */
exti_interrupt_flag_clear(EXTI_20);
exti_init(EXTI_20, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_enable(EXTI_20);
nvic_irq_enable((uint8_t)USBHS_WKUP_IRQn, 0U, 0U);
#endif /* USBHS_LOW_POWER */
#endif /* USE_USB_FS */
#ifdef USB_HS_DEDICATED_EP1_ENABLED
nvic_irq_enable(USBHS_EP1_Out_IRQn, 1, 0);
nvic_irq_enable(USBHS_EP1_In_IRQn, 1, 0);
#endif /* USB_HS_DEDICATED_EP1_ENABLED */
}
内部上拉电阻被上拉后,主机将会对设备进行枚举,设备端采用while (USBD_CONFIGURED != hid_keyboard.dev.cur_status) 语句进行等待。当USB设备状态变为USBD_CONFIGURED状态时,表明设备枚举完成。
枚举完成之后,程序将进入主循环中,在主循环中,循环调用HID USB模拟键盘数据处理函数,在该函数中,首先判断上次传输是否完成,完成之后通过扫描按键的方式查看按键是否被按下,若按键被按下,则通过hid_report_send()函数发送键盘报告数据。
C
static void hid_key_data_send(usb_dev *udev)
{
standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE];
if (hid->prev_transfer_complete) {
switch (key_state()) {
case CHAR_A:
hid->data[2] = 0x04U;
break;
case CHAR_B:
hid->data[2] = 0x05U;
break;
default:
break;
}
if (0U != hid->data[2]) {
hid_report_send(udev, hid->data, HID_IN_PACKET);
}
}
}
报文发送函数定义如下,该函数包含三个参数,udev为初始化后的设备操作结构体;report为发送报告缓冲区地址;len为发送报告的长度。在该函数中,如果设备已经被枚举成功,则首先将prev_transfer_complete标志位设置为0,表明接下来将进行发送数据,数据并未发送完成,之后,调用usbd_ep_send()将需要发送的报告拷贝到USB外设缓冲区中并设置端点为有效状态,等待主机发送IN令牌包,USB设备将外设缓冲区中的数据发送给主机。
C
uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len)
{
standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE];
hid->prev_transfer_complete = 0U;
usbd_ep_send(udev, HID_IN_EP, report, len);
return USBD_OK;
}
当数据发送完成,USB设备将调用hid_data_in()函数进行数据处理。该函数程序如下所示。在该函数中,首先判断hid->data[2]的数据是否为0x00,如果不为0x00表明上次发送的为按键按下的键值,还需发送按键松开的键值,如果为0x00表明上次按键按下和松开的键值均已发送完成,之后将prev_transfer_complete设置为1,表明上一次的按键数据传输完成,可进行下次按键数据传输。
C
static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num)
{
standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE];
if (0U != hid->data[2]) {
hid->data[2] = 0x00U;
usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET);
} else {
hid->prev_transfer_complete = 1U;
}
return USBD_OK;
}
在该例程中通过hid->prev_transfer_complete数据流程标志位进行数据发送控制,读者可使用该标志位用于对数据发送的控制,当该标志位为0的时候,表明数据已被填送到USB缓冲区,但还没有发送给主机,此时MCU不能继续调用发送函数向缓冲区中填数据,否则可能导致数据覆盖丢失,正确做法是等待该标志位置位,表明上一包数据已被主机读取,然后再继续发送后续数据。
13.5实验结果
将本例程烧录到紫藤派开发板中,通过Type C数据线连接开发板和PC,之后分别按下WKUP和USER按键,将会向PC发送A、B键值。
上一篇:GD32F303固件库开发(8)----USART收发配置
下一篇:最后一页
设计资源 培训 开发板 精华推荐
- 用于电力线通信的 3-LED 通用 LED 驱动器
- LT3970IMS 5V 降压转换器的典型应用
- DC933A,使用 LT5512 HF/VHF/UHF 下变频混频器的演示板
- AD5331 并行接口、单电压输出、10 位 DAC 的典型应用
- LTC1174 5V、175mA 表面贴装
- LT3970IMS-5 5V、2MHz 降压转换器的典型应用
- LDK130C-R 300 mA 低静态电流极低噪声 LDO 的典型应用固定版本电路
- 使用 Analog Devices 的 LT1173CN8 的参考设计
- MC33163 外部 PNP 饱和开关稳压器的典型应用
- 1.2V, 1.8V, 2.5V, 3.3V 直流转直流单输出便携式电脑电源
- 借助完全可互操作且符合 EMC 标准的 3.3V CAN 收发器简化汽车接口设计
- 珠海航展的这些展品,令人眼前一亮
- 现代化制造策略推动ICT在线测试持续精进
- 英特尔宋继强:云边端协同创新,加速智能计算的落地应用
- Melexis与吉利携手共创汽车照明设计新纪元
- 尼得科驱动(CT)推出五年质保服务
- 意法半导体Web工具配合智能传感器加快AIoT项目落地
- 兆易创新选择 Arteris产品用于开发 符合增强型 FuSa 标准的下一代汽车 SoC
- ROHM开发出适合高分辨率音源播放的MUS-IC™系列第2代音频DAC芯片
- 贸泽开售适用于AI和机器学习应用的 AMD Versal AI Edge VEK280评估套件