打印
[活动专区]

【AT-START-F425测评】+ USB HID设备Joystick开发体验与外设ADC DMA...

[复制链接]
1650|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 lilijin1995 于 2022-3-28 22:49 编辑

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

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


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

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

        //Button1~8
        crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);        
        gpio_default_para_init(&gpio_initstructure);
        gpio_initstructure.gpio_pull=GPIO_PULL_UP;
        gpio_initstructure.gpio_mode = GPIO_MODE_INPUT;
        gpio_initstructure.gpio_pins = GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2|GPIO_PINS_3
                                                                  |GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_6|GPIO_PINS_7;
        gpio_init(GPIOB, &gpio_initstructure);
        
}


/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  dma configuration.
  * @param  none
  * @retval none
  */
static void Joy_dma_config(void)
{
        dma_init_type dma_init_struct;
        crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
        nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
        dma_reset(DMA1_CHANNEL1);

        dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_ADC1);

        dma_default_para_init(&dma_init_struct);
        dma_init_struct.buffer_size = 10;
        dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
        dma_init_struct.memory_base_addr = (uint32_t)adc1_ordinary_valuetab;
        dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
        dma_init_struct.memory_inc_enable = TRUE;
        dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
        dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
        dma_init_struct.peripheral_inc_enable = FALSE;
        dma_init_struct.priority = DMA_PRIORITY_VERY_HIGH;
        dma_init_struct.loop_mode_enable = TRUE;
        dma_init(DMA1_CHANNEL1, &dma_init_struct);

        dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
        dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  adc configuration.
  * @param  none
  * @retval none
  */
static void Joy_adc_config(void)
{
        adc_base_config_type adc_base_struct;
        crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
        crm_adc_clock_div_set(CRM_ADC_DIV_6);

        adc_base_default_para_init(&adc_base_struct);
        adc_base_struct.sequence_mode = TRUE;
        adc_base_struct.repeat_mode = TRUE;
        adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
        adc_base_struct.ordinary_channel_length = 2;
        adc_base_config(ADC1, &adc_base_struct);
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_4, 1, ADC_SAMPLETIME_1_5);
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_5, 2, ADC_SAMPLETIME_1_5);
        adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
        adc_dma_mode_enable(ADC1, TRUE);

        adc_enable(ADC1, TRUE);
        adc_calibration_init(ADC1);
        while(adc_calibration_init_status_get(ADC1));
        adc_calibration_start(ADC1);
        while(adc_calibration_status_get(ADC1));
}

/**
  * @brief  Joystick Initialization.
  * @param  none
  * @retval none
  */
void Joystick_Init(void)
{        
        Joy_gpio_config();
        Joy_dma_config();
        Joy_adc_config();
        printf("software_trigger_repeat \r\n");
    adc_ordinary_software_trigger_enable(ADC1, TRUE);
    while(dma_trans_complete_flag == 0);
}


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

          adcval1=0;
          adcval2=0;
          for( jindex = 0; jindex < 5; jindex++)
          {
                adcval1+=adc1_ordinary_valuetab[jindex][0];
                adcval2+=adc1_ordinary_valuetab[jindex][1];
          }
         
          Xtemp=adcval1/5;
          Ytemp=adcval2/5;
//          printf("X=%d,Y=%d\r\n",Xtemp,Ytemp);

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


/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
        
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

  system_clock_config();

  at32_board_init();
  uart_print_init(115200);
  Joystick_Init();
   /* usb gpio config */
  usb_gpio_config();

#ifdef USB_LOW_POWER_WAKUP
  usb_low_power_wakeup_config();
#endif

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

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

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

  /* init usb */
  usbd_init(&otg_core_struct,
            USB_FULL_SPEED_CORE_ID,
            USB_ID,
            &custom_hid_class_handler,
            &custom_hid_desc_handler);

  while(1)
  {

        Joystick_Handle();

  }
}


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


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








使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

162

帖子

7

粉丝