> 文档中心 > GD32 ADC采集电压

GD32 ADC采集电压

文章目录

    • ADC
    • TIM
    • DMA
    • 其他一些初始化
    • main
    • 总结

使用芯片为GD32F307

ADC

连续转换模式,可以运行在规则通道上,一旦相应软件触发或者外部触发产生,ADC就会采样和转换规定的通道。

采样时间,每个通道可以用不同的时间采样。ADC使用若干个ADC_CLK周期对输入的电压进行采样,在12位分辨率的情况下,总转换时间=采样时间+12.5个ADCCLK周期。

采样周期数目可以通过ADC_SAMPT0和ADC_SAMPT1寄存器的SPTn[2:0]位更改。如下面所示。

如果想要采样的频率比较快,那么可以设置采样时间为1.5个ADCCLK周期。

/* ADC channel sample time */#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0))     /*!< write value to ADC_SAMPTX_SPT bit field */#define ADC_SAMPLETIME_1POINT5    SAMPTX_SPT(0)   /*!< 1.5 sampling cycles */#define ADC_SAMPLETIME_7POINT5    SAMPTX_SPT(1)   /*!< 7.5 sampling cycles */#define ADC_SAMPLETIME_13POINT5   SAMPTX_SPT(2)   /*!< 13.5 sampling cycles */#define ADC_SAMPLETIME_28POINT5   SAMPTX_SPT(3)   /*!< 28.5 sampling cycles */#define ADC_SAMPLETIME_41POINT5   SAMPTX_SPT(4)   /*!< 41.5 sampling cycles */#define ADC_SAMPLETIME_55POINT5   SAMPTX_SPT(5)   /*!< 55.5 sampling cycles */#define ADC_SAMPLETIME_71POINT5   SAMPTX_SPT(6)   /*!< 71.5 sampling cycles */#define ADC_SAMPLETIME_239POINT5  SAMPTX_SPT(7)   /*!< 239.5 sampling cycles */

外部触发输入的上升沿可以触发规则组或注入组的转换。规则组的外部触发源由ADC_CTL1寄存器的ETSRC[2:0]位控制。外部触发信号的上升沿可以启动转换,那么就可以利用定时器的PWM输出模式获得上升沿。

这里选用TIMER0 CH0作为规则组的外部触发源。

在这里插入图片描述

DMA请求,设置ADC_CTL1寄存器的DMA位使能,ADC在规则组一个通道转换结束后产生一个DMA请求,DMA接受到请求后,将转换的数据从ADC_RDATA寄存器传输到用户指定的目的地址。RDATA[15:0],规则通道数据,这些位包含了规则通道的转换结果,只读。

下面的程序,其实还是根据手册的说明,修改寄存器的值,只不过用了一些库函数。

void rcu_config(void){    /* enable GPIOC clock */    rcu_periph_clock_enable(RCU_GPIOC);    /* enable GPIOA clock */    rcu_periph_clock_enable(RCU_GPIOA);      /* enable DMA clock */    rcu_periph_clock_enable(RCU_DMA0);    /* enable TIMER0 clock */    rcu_periph_clock_enable(RCU_TIMER0);    /* enable ADC0 clock */    rcu_periph_clock_enable(RCU_ADC0);    /* config ADC clock */    rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);//rcu_periph_clock_enable(RCU_DAC);}void gpio_config(void){    gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0);}void adc_config(void){//配置ADC同步模式 ADC_MODE_FREE模式每个ADC都独立工作    adc_mode_config(ADC_MODE_FREE);  //配置ADCx数据对齐方式    adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);//使能或禁能ADC特殊功能-扫描模式选择    adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);  //配置规则通道组或注入通道组的长度 通道长度,规则通道组为1-16,注入通道组为1-4    adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1);//配置ADC规则通道组 ADC通道选择-采样时间    adc_regular_channel_config(ADC0, 0,ADC_CHANNEL_10, ADC_SAMPLETIME_1POINT5);//配置ADC外部触发    adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);//配置ADC外部触发源 TIMER0 CH0事件    adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_T0_CH0);//使能ADCx外设    adc_enable(ADC0); delay_1ms(1);    //ADCx校准复位 A/D 转换前执行校准操作,软件设置CLB=1来对校准进行初始化,//校准期间CLB位会一直保持1,直到校准完成,该位由硬件清0。    adc_calibration_enable(ADC0);//ADCx DMA请求使能    adc_dma_mode_enable(ADC0);}

TIM

输出比较模式,TIMERx可以产生时控脉冲,当一个输出通道的TIMERx_CHxCV寄存器与计数器的值匹配时,根据CHxCOMCTL的配置,这个通道的输出可以被置高电平,被置低电平或者反转。

在PWM输出模式下,通道根据TIMERx_CAR寄存器和TIMERx_CHxCV寄存器的值,输出PWM波形,EAPWM(边沿对齐PWM)的周期由TIMERx_CAR寄存器值决定,占空比由TIMERx_CHxCV寄存器值决定。

PWM0模式,在向上计数时,一旦计数器值小于TIMERx_CH0CV时,O0CPRE为有效电平,否则为无效电平。在向下计数时,一旦计数器的值大于TIMERx_CH0CV时,O0CPRE为无效电平,否则为有效电平。

void timer_config(void){    timer_oc_parameter_struct timer_ocintpara;    timer_parameter_struct timer_initpara;    /* TIMER0 configuration */    timer_initpara.prescaler  = 0;    timer_initpara.alignedmode= TIMER_COUNTER_EDGE;//对齐模式    timer_initpara.counterdirection  = TIMER_COUNTER_UP;    timer_initpara.period     = 224;    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;    timer_initpara.repetitioncounter = 0;    timer_init(TIMER0, &timer_initpara);    /* CH0 configuration in PWM mode0 */    timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;//通道输出极性    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;//通道输出状态    timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara);//外设TIMERx的通道输出配置    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 56);//配置外设TIMERx的通道输出比较值    timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);//配置外设TIMERx通道输出比较模式 PWM模式0    timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);//禁能输出比较影子寄存器    /* TIMER0 所有的通道输出使能 */    timer_primary_output_config(TIMER0, ENABLE);    /* TIMERx自动重载影子使能 */    timer_auto_reload_shadow_enable(TIMER0);     /* enable TIMER0 */    timer_enable(TIMER0);}

DMA

ADC0外设请求被映射到DMA0通道0,下面就对DMA0通道0配置。

在这里插入图片描述

设置方向是外设到存储器。

CNT[15:0],该寄存器表明还有多少数据等待被传输。一旦通道使能,该寄存器为只读的,并在每个DMA传输之后值减1。

设置循环模式,循环模式用来处理连续的外设请求,循环模式中,当每次DMA传输完成后,CNT寄存器会被自动重装载为初始设置值。

源地址,规则数据寄存器 (ADC_RDATA) :RDATA[15:0],规则通道数据,这些位包含了规则通道的转换结果,只读。

uint32_t adc_value[120];void dma_config(void){    /* ADC_DMA_channel configuration DMA初始化结构体 */    dma_parameter_struct dma_data_parameter; /* ADC_DMA_channel deinit */    dma_deinit(DMA0, DMA_CH0); /* initialize DMA single data mode */    dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));    dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;    dma_data_parameter.memory_addr = (uint32_t)(adc_value);    dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;    dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;    dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT;    dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;    dma_data_parameter.number = 120;//DMA通道数据传输数量    dma_data_parameter.priority = DMA_PRIORITY_HIGH;      dma_init(DMA0, DMA_CH0, &dma_data_parameter);      dma_circulation_enable(DMA0, DMA_CH0);    //设置dma中断优先级    //nvic_irq_enable(DMA0_Channel0_IRQn, 0, 0);    /* enable DMA transfer complete interrupt */    //dma_interrupt_enable(DMA0,DMA_CH0, DMA_INT_FTF);    /* enable DMA channel */    dma_channel_enable(DMA0, DMA_CH0);  }

其他一些初始化

这个里面修改rcu_adc_clock_config可以改变ADC采集的频率。

//存储adc数据的内存数组uint32_t adc_value[120];void rcu_config(void){    /* enable GPIOC clock */    rcu_periph_clock_enable(RCU_GPIOC);    /* enable GPIOA clock */    rcu_periph_clock_enable(RCU_GPIOA);      /* enable DMA clock */    rcu_periph_clock_enable(RCU_DMA0);    /* enable TIMER0 clock */    rcu_periph_clock_enable(RCU_TIMER0);    /* enable ADC0 clock */    rcu_periph_clock_enable(RCU_ADC0);    /* enable ADC1 clock */    rcu_periph_clock_enable(RCU_ADC1);    /* config ADC clock */    rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);  rcu_periph_clock_enable(RCU_DAC);}void gpio_config(void){    gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0);}

main

    int main(void){    rcu_config();    systick_config();      gpio_config();    timer_config();    dma_config();    adc_config();    gd_eval_com_init(EVAL_COM0);sin_app();uint16_t i =0;    while(1){if(i==120) i=0;printf("%.3f\r\n",(float)adc_value[i]* 3.3f / 4096.0f);++i;    }}

总结

连续转换模式运行在规则组通道上,TIMER0 CH0外部触发产生,ADC就会采样和转换指定的通道(ADC0 CHANNEL_10,采集PC0引脚的电压)。

外部触发输入的上升沿可以触发规则组或注入组的转换,利用定时器的PWM输出模式获得上升沿,其中设置定时器的时候,改变计数器自动重载值(TIMERx_CAR)和输出比较值(TIMERx_CH0CV寄存器)可以改变触发的频率。

ADC在规则组一个通道转换结束后产生一个DMA请求,DMA接受到请求后,将转换的数据从ADC_RDATA寄存器传输到用户指定的目的地址。(ADC0外设请求被映射到DMA0通道0)

DAC输出一个电压,加到PC0引脚上,然后用ADC采集。

改采集的频率:使其刚好在一个波形周期采120个点。

主要修改的地方:

rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);//RCU_CKADC_CKAPB2_DIV6adc_regular_channel_config(ADC0, 0,ADC_CHANNEL_10, ADC_SAMPLETIME_1POINT5);//ADC_SAMPLETIME_1POINT5timer_initpara.period     = 224;timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 56);//配置外设TIMERx的通道输出比较值dma_data_parameter.number = 120;//DMA通道数据传输数量