本帖最后由 lilijin1995 于 2022-3-28 22:49 编辑
一、知识准备1. 初探USB规格书中关于usb部分的介绍如下图: 从上图可以了解到雅特力usb支持otg模式,支持全速12Mb/s,有1280byte专用缓存,并支持8个输入8个输出端点等信息; 接着我们看参考手册中usb的介绍,USB OTG 全速的介绍在第二十章,下面是OTGFS的系统结构框图,更详细部分请直接阅读参考手册了解。 2. 初探ADCAT32F425的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上报的数据改变很慢,导致效果不佳,也可能是我配置不正确的问题; 最后附赠开源代码;
由于up主水平有限,所以帖子中难免有出错和讲得不好的地方,欢迎各位观众提出意见和建议,谢谢!
|