当前位置:网站首页>GD32 ADC采集电压

GD32 ADC采集电压

2022-06-26 01:41:00 _jym

使用芯片为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_DIV6
adc_regular_channel_config(ADC0, 0,ADC_CHANNEL_10, ADC_SAMPLETIME_1POINT5);//ADC_SAMPLETIME_1POINT5
timer_initpara.period            = 224;
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 56);//配置外设TIMERx的通道输出比较值
dma_data_parameter.number = 120;//DMA通道数据传输数量

在这里插入图片描述

原网站

版权声明
本文为[_jym]所创,转载请带上原文链接,感谢
https://jiangyiming.blog.csdn.net/article/details/125373326