[活动专区] 【AT-START-F425测评】+ USB HID设备Joystick开发体验与外设ADC DMA...

[复制链接]
2728|0
 楼主| lilijin1995 发表于 2022-3-28 22:42 | 显示全部楼层 |阅读模式
本帖最后由 lilijin1995 于 2022-3-28 22:49 编辑

1.jpg 一、知识准备1. 初探USB
规格书中关于usb部分的介绍如下图:
image-20220327120241058.png
从上图可以了解到雅特力usb支持otg模式,支持全速12Mb/s,有1280byte专用缓存,并支持8个输入8个输出端点等信息;
接着我们看参考手册中usb的介绍,USB OTG 全速的介绍在第二十章,下面是OTGFS的系统结构框图,更详细部分请直接阅读参考手册了解。
image-20220327121456605.png
2. 初探ADC
AT32F425的ADC特性:
image-20220327142242859.png
ADC的框图
image-20220327142421373.png
3.初探GPIO
简介:
AT32F425 支持多达 55 个双向 I/O 引脚,分别为 PA0-PA15、PB0-PB15、PC0-PC15、PD2、PF0-PF1、PF4-PF7 每个引脚都可以实现与外部的通讯、控制以及数据采集的功能。每个引脚都支持通用功能输入输出(GPIO)或复用功能输入输出(IOMUX)。每个引脚都可以软件配置成浮空输入、上拉/下拉输入、模拟输入/输出、通用推挽/开漏输出、复用推挽/开漏输出。每个引脚都有独立的弱上拉/下拉功能。每个引脚都可以软件配置输出驱动能力以及输出信号斜率。每个引脚都可以配置为外部中断输入。每个引脚都支持配置锁定功能。
GPIO基本结构
image-20220327143158143.png

二、硬件设计用到PA4和PA5去采集摇杆模块的XY,再用PB0~PB7作为按键;
三、软件设计
在\project\at_start_f425\examples\usb_device\custom_hid基础上修改得来;


以下是A4和PA5作为ADC 的ch4和ch5 的DMA模式,B0~PB7作为gpio输入的初始化配置;
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  joystick gpio configuration.
  3.   * @param  none
  4.   * @retval none
  5.   */
  6. static void Joy_gpio_config(void)
  7. {
  8.         //X-Y
  9.         gpio_init_type gpio_initstructure;
  10.         crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  11.         gpio_default_para_init(&gpio_initstructure);
  12.         gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
  13.         gpio_initstructure.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5 ;
  14.         gpio_init(GPIOA, &gpio_initstructure);

  15.         //Button1~8
  16.         crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);        
  17.         gpio_default_para_init(&gpio_initstructure);
  18.         gpio_initstructure.gpio_pull=GPIO_PULL_UP;
  19.         gpio_initstructure.gpio_mode = GPIO_MODE_INPUT;
  20.         gpio_initstructure.gpio_pins = GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2|GPIO_PINS_3
  21.                                                                   |GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_6|GPIO_PINS_7;
  22.         gpio_init(GPIOB, &gpio_initstructure);
  23.         
  24. }


  25. /**
  26.   * [url=home.php?mod=space&uid=247401]@brief[/url]  dma configuration.
  27.   * @param  none
  28.   * @retval none
  29.   */
  30. static void Joy_dma_config(void)
  31. {
  32.         dma_init_type dma_init_struct;
  33.         crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  34.         nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
  35.         dma_reset(DMA1_CHANNEL1);

  36.         dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_ADC1);

  37.         dma_default_para_init(&dma_init_struct);
  38.         dma_init_struct.buffer_size = 10;
  39.         dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  40.         dma_init_struct.memory_base_addr = (uint32_t)adc1_ordinary_valuetab;
  41.         dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  42.         dma_init_struct.memory_inc_enable = TRUE;
  43.         dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
  44.         dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  45.         dma_init_struct.peripheral_inc_enable = FALSE;
  46.         dma_init_struct.priority = DMA_PRIORITY_VERY_HIGH;
  47.         dma_init_struct.loop_mode_enable = TRUE;
  48.         dma_init(DMA1_CHANNEL1, &dma_init_struct);

  49.         dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  50.         dma_channel_enable(DMA1_CHANNEL1, TRUE);
  51. }

  52. /**
  53.   * [url=home.php?mod=space&uid=247401]@brief[/url]  adc configuration.
  54.   * @param  none
  55.   * @retval none
  56.   */
  57. static void Joy_adc_config(void)
  58. {
  59.         adc_base_config_type adc_base_struct;
  60.         crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
  61.         crm_adc_clock_div_set(CRM_ADC_DIV_6);

  62.         adc_base_default_para_init(&adc_base_struct);
  63.         adc_base_struct.sequence_mode = TRUE;
  64.         adc_base_struct.repeat_mode = TRUE;
  65.         adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
  66.         adc_base_struct.ordinary_channel_length = 2;
  67.         adc_base_config(ADC1, &adc_base_struct);
  68.         adc_ordinary_channel_set(ADC1, ADC_CHANNEL_4, 1, ADC_SAMPLETIME_1_5);
  69.         adc_ordinary_channel_set(ADC1, ADC_CHANNEL_5, 2, ADC_SAMPLETIME_1_5);
  70.         adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
  71.         adc_dma_mode_enable(ADC1, TRUE);

  72.         adc_enable(ADC1, TRUE);
  73.         adc_calibration_init(ADC1);
  74.         while(adc_calibration_init_status_get(ADC1));
  75.         adc_calibration_start(ADC1);
  76.         while(adc_calibration_status_get(ADC1));
  77. }

  78. /**
  79.   * @brief  Joystick Initialization.
  80.   * @param  none
  81.   * @retval none
  82.   */
  83. void Joystick_Init(void)
  84. {        
  85.         Joy_gpio_config();
  86.         Joy_dma_config();
  87.         Joy_adc_config();
  88.         printf("software_trigger_repeat \r\n");
  89.     adc_ordinary_software_trigger_enable(ADC1, TRUE);
  90.     while(dma_trans_complete_flag == 0);
  91. }


以下是XY轴数据处理与按键数据的处理,代码如下:
  1. void Joystick_Handle(void)
  2. {

  3.           adcval1=0;
  4.           adcval2=0;
  5.           for( jindex = 0; jindex < 5; jindex++)
  6.           {
  7.                 adcval1+=adc1_ordinary_valuetab[jindex][0];
  8.                 adcval2+=adc1_ordinary_valuetab[jindex][1];
  9.           }
  10.          
  11.           Xtemp=adcval1/5;
  12.           Ytemp=adcval2/5;
  13. //          printf("X=%d,Y=%d\r\n",Xtemp,Ytemp);

  14.           X=((Xtemp-Xmin)*255)/(Xmax-Xmin);
  15.           Y=((Ytemp-Ymin)*255)/(Ymax-Ymin);
  16.           printf("X=%d,Y=%d\r\n",X,Y);
  17.           report_buf[0]=X;
  18.           report_buf[1]=Y;
  19.           report_buf[2]=(~gpio_input_data_read(GPIOB)&0xFF);
  20.           if(usbd_connect_state_get(&otg_core_struct.dev) == USB_CONN_STATE_CONFIGURED)
  21.           {
  22.                  custom_hid_class_send_report(&otg_core_struct.dev, report_buf, USBD_CUSTOM_IN_MAXPACKET_SIZE);
  23.           }
  24.          
  25.         
  26. }
最后是main函数,如下


  1. /**
  2.   * @brief  main function.
  3.   * @param  none
  4.   * @retval none
  5.   */
  6. int main(void)
  7. {
  8.         
  9.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

  10.   system_clock_config();

  11.   at32_board_init();
  12.   uart_print_init(115200);
  13.   Joystick_Init();
  14.    /* usb gpio config */
  15.   usb_gpio_config();

  16. #ifdef USB_LOW_POWER_WAKUP
  17.   usb_low_power_wakeup_config();
  18. #endif

  19.   /* enable otgfs clock */
  20.   crm_periph_clock_enable(OTG_CLOCK, TRUE);

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

  23.   /* enable otgfs irq */
  24.   nvic_irq_enable(OTG_IRQ, 0, 0);

  25.   /* init usb */
  26.   usbd_init(&otg_core_struct,
  27.             USB_FULL_SPEED_CORE_ID,
  28.             USB_ID,
  29.             &custom_hid_class_handler,
  30.             &custom_hid_desc_handler);

  31.   while(1)
  32.   {

  33.         Joystick_Handle();

  34.   }
  35. }


四、下载验证:
如下图,成功枚举成一个XY轴,8个按键的usb joystick,经测试,串口数据已经改变,但usb上报的数据改变很慢,导致效果不佳,也可能是我配置不正确的问题;
最后附赠开源代码;
Gamepad_Firmware.rar (7.95 MB, 下载次数: 26)


由于up主水平有限,所以帖子中难免有出错和讲得不好的地方,欢迎各位观众提出意见和建议,谢谢!
2.png








您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

165

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部