RISC-V技术论坛
直播中

华仔stm32

3年用户 2951经验值
擅长:嵌入式技术
私信 关注
[经验]

【兆易创新GD32VF103R-START开发板试用体验】电压表(定时器触发,DMA采集)

【目的】驱动ADC外设,并初始测量ADC的精度。这里使用PA1做为采集IO,使用定时器触发,DMA数据传输。
1、配置ADC0、DMA、定时器的时钟
  1. void rcu_config(void)
  2. {
  3.     /* enable GPIOA clock */
  4.     rcu_periph_clock_enable(RCU_GPIOA);
  5.     /* enable ADC0 clock */
  6.     rcu_periph_clock_enable(RCU_ADC0);
  7.     /* enable ADC1 clock */
  8.     //rcu_periph_clock_enable(RCU_ADC1);
  9.     /* enable DMA0 clock */
  10.     rcu_periph_clock_enable(RCU_DMA0);
  11.     /* enable timer1 clock */
  12.     rcu_periph_clock_enable(RCU_TIMER1);
  13.     /* config ADC clock */
  14.     rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);
  15. }
2、配置PA1
  1. void gpio_config(void)
  2. {
  3.     /* config the GPIO as analog mode */
  4.     gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
  5. }
3、配置DMA
  1. void dma_config(void)
  2. {
  3.     /* ADC_DMA_channel configuration */
  4.     dma_parameter_struct dma_data_parameter;

  5.     /* ADC DMA_channel configuration */
  6.     dma_deinit(DMA0, DMA_CH0);

  7.     /* initialize DMA data mode */
  8.     dma_data_parameter.periph_addr  = (uint32_t)(&ADC_RDATA(ADC0));
  9.     dma_data_parameter.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
  10.     dma_data_parameter.memory_addr  = (uint32_t)(&adc_value);
  11.     dma_data_parameter.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
  12.     dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
  13.     dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT;
  14.     dma_data_parameter.direction    = DMA_PERIPHERAL_TO_MEMORY;
  15.     dma_data_parameter.number       = 1;
  16.     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;
  17.     dma_init(DMA0, DMA_CH0, &dma_data_parameter);

  18.     dma_circulation_enable(DMA0, DMA_CH0);

  19.     /* enable DMA channel */
  20.     dma_channel_enable(DMA0, DMA_CH0);
  21. }
4、配置定时器:
  1. void timer_config(void)
  2. {
  3.     timer_oc_parameter_struct timer_ocintpara;
  4.     timer_parameter_struct timer_initpara;

  5.     /* TIMER1 configuration */
  6.     timer_struct_para_init(&timer_initpara);
  7.     timer_initpara.prescaler         = 5399;
  8.     timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
  9.     timer_initpara.counterdirection  = TIMER_COUNTER_UP;
  10.     timer_initpara.period            = 9999;
  11.     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
  12.     timer_initpara.repetitioncounter = 0;
  13.     timer_init(TIMER1,&timer_initpara);

  14.     /* CH0 configuration in PWM mode1 */
  15.     timer_channel_output_struct_para_init(&timer_ocintpara);
  16.     timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
  17.     timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  18.     timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);

  19.     timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 3999);
  20.     timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM1);
  21.     timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
  22. }
5、配置ADC0:
  1. void adc_config(void)
  2. {
  3.    /* reset ADC */
  4.     adc_deinit(ADC0);

  5.     /* ADC mode config */
  6.     adc_mode_config(ADC_DAUL_REGULAL_PARALLEL);
  7.     /* ADC continous function enable */
  8.     adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);

  9.     /* ADC data alignment config */
  10.     adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);

  11.     /* ADC channel length config */
  12.     adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2);

  13.     /* ADC regular channel config */
  14.     adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
  15.     adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);

  16.     /* ADC trigger config */
  17.     adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_T1_CH1);

  18.     /* ADC external trigger enable */
  19.     adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);


  20.     /* enable ADC interface */
  21.     adc_enable(ADC0);
  22.     /* ADC calibration and reset calibration */
  23.     adc_calibration_enable(ADC0);
  24.     delay_1ms(1);
  25.     /* ADC DMA function enable */
  26.     adc_dma_mode_enable(ADC0);
  27. }
6、在主函数主读取DMA中的数据并用OLED显示:
  1. float vref_value ;
  2. int value_h,value_l;
  3. int main(void) {

  4.         uint8_t v_show[10];
  5.         /* system clocks configuration */
  6.             rcu_config();
  7.             /* GPIO configuration */
  8.             gpio_config();
  9.             /* TIMER configuration */
  10.             timer_config();
  11.             /* DMA configuration */
  12.             dma_config();
  13.             /* ADC configuration */
  14.             adc_config();
  15.             /* enable TIMER1 */
  16.                 timer_enable(TIMER1);
  17.         led_init();
  18.         key_init();
  19.         my_i2c0_init();
  20.         gd_eval_com_init();
  21.         printf("GD32VF103rn");
  22.         oled_display_test();
  23.         delay_1ms(2000);
  24.         oled_clear();
  25.         OLED_ShowStr(2,0,"GD32VF103R",24);
  26.         while (1) {
  27.                 //sta_flash(key_sta);
  28.                 printf("rn ADC0 regular channel 0 data = %08X rn",adc_value[0]);
  29.                 vref_value = (adc_value[0] * 3.3f/4096);
  30.                 value_h = (int)vref_value;
  31.                 vref_value = (vref_value-value_h)*1000;
  32.                 value_l = (int)vref_value;
  33.                 printf(" the Reference voltage data is %2d.%03dV rn", value_h,value_l);
  34.                 sprintf(v_show,"%d.%03dV",value_h,value_l);
  35.                 OLED_ShowStr(18,3,v_show,24);
  36.                 delay_1ms(1000);
  37.         }
  38. }
【总结】用定时器触发ADC采集数据,DMA传输。获取的数据没有处理,但是精度还算可以,目测在正负0.03之间。

电压表

更多回帖

发帖
×
20
完善资料,
赚取积分