AT32 USB_DEVICE — USB 鼠标

AT32 AT32F403A_407_Firmware_Library V2.2.2 USB_DEVICE USB 鼠标 示例教学

USB_DEVICE — USB 鼠标

固件库: AT32F403A_407_Firmware_Library V2.2.2
芯片: AT32
源文件: AT32/AT32F403A_407_Firmware_Library_V2.2.2/project/at_start_f403a/examples/usb_device/mouse/src/main.c


功能简介

本示例演示 USB 设备模式 — USB 鼠标。MCU 作为 USB 设备连接到电脑,实现 HID 键盘/鼠标、虚拟串口(CDC)、大容量存储(MSC)等功能。

完整代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "at32f403a_407_board.h"
#include "at32f403a_407_clock.h"
#include "usbd_core.h"
#include "mouse_class.h"
#include "mouse_desc.h"
#include "usbd_int.h"

int main(void)
{
  __IO uint32_t delay_index = 0;
  /* config nvic priority group */
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

  system_clock_config();

  at32_board_init();

  /* select usb 48m clcok source */
  usb_clock48m_select(USB_CLK_HEXT);

#ifdef USB_LOW_POWER_WAKUP
  /* enable pwc and bpr clock */
  crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
  button_exint_init();
  usb_low_power_wakeup_config();
#endif

  /* enable usb clock */
  crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, TRUE);

  /* enable usb interrupt */
  nvic_irq_enable(USBFS_L_CAN1_RX0_IRQn, 0, 0);

  /* usb core init */
  usbd_core_init(&usb_core_dev, USB, &mouse_class_handler, &mouse_desc_handler, 0);

  /* enable usb pull-up */
  usbd_connect(&usb_core_dev);

  while(1)
  {
    if(at32_button_press() == USER_BUTTON)
    {
      if(usbd_connect_state_get(&usb_core_dev) == USB_CONN_STATE_CONFIGURED)
      {
        usb_hid_mouse_send(&usb_core_dev, RIGHT_BUTTON);
        press_mouse = 1;
      }
      /* remote wakeup */
      if(usbd_connect_state_get(&usb_core_dev) == USB_CONN_STATE_SUSPENDED
        &&(usb_core_dev.remote_wakup == 1))
      {
        usbd_remote_wakeup(&usb_core_dev);
      }
    }
    else if(press_mouse == 1)
    {
      delay_ms(10);
      usb_hid_mouse_send(&usb_core_dev, BUTTON_RELEASE);
      press_mouse = 0;
    }
 #ifdef USB_LOW_POWER_WAKUP
     /* enter deep sleep */
    if(((mouse_type *)(usb_core_dev.class_handler->pdata))->hid_suspend_flag == 1)
    {
      at32_led_off(LED2);
      at32_led_off(LED3);
      at32_led_off(LED4);
      /* congfig the voltage regulator mode */
      pwc_voltage_regulate_set(PWC_REGULATOR_LOW_POWER);

      /* enter deep sleep mode */
      pwc_deep_sleep_mode_enter(PWC_DEEP_SLEEP_ENTER_WFI);
      /* wait 3 LICK cycles to ensure clock stable, delay 120us*/
      /* when wakeup from deepsleep,system clock source changes to HICK */
      if((CRM->misc3_bit.hick_to_sclk == TRUE) && (CRM->misc1_bit.hickdiv == TRUE))
      {
        /* HICK is 48MHz */
        for(delay_index = 0; delay_index < 750; delay_index++)
        {
          __NOP();
        }
      }
      else
      {
        /* HICK is 8MHz */
        for(delay_index = 0; delay_index < 125; delay_index++)
        {
          __NOP();
        }
      }

      system_clock_recover();
      ((mouse_type *)(usb_core_dev.class_handler->pdata))->hid_suspend_flag = 0;
      at32_led_on(LED2);
      at32_led_on(LED3);
      at32_led_on(LED4);
    }
#endif

  }
}

void button_exint_init(void)
{
  exint_init_type exint_init_struct;

  crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE0);

  exint_default_para_init(&exint_init_struct);
  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
  exint_init_struct.line_select = EXINT_LINE_0;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(EXINT0_IRQn, 0, 0);
}

void usb_low_power_wakeup_config(void)
{
  exint_init_type exint_init_struct;

  exint_default_para_init(&exint_init_struct);

  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
  exint_init_struct.line_select = EXINT_LINE_18;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);

  nvic_irq_enable(USBFSWakeUp_IRQn, 0, 0);
}

代码讲解

系统时钟初始化:配置 MCU 的主频和时钟树。不同芯片的时钟配置不同,一般由工具生成。

板级初始化:初始化开发板上的 LED、按键等基础外设。

中断优先级配置:NVIC 设置中断的抢占优先级和子优先级。数字越小优先级越高。

延时:使用系统延时函数控制 LED 翻转间隔。

世界是你们
使用 Hugo 构建
主题 StackJimmy 设计