GD32E230Fx DMA方式读内部ADC+定时器触发

本文介绍了如何在GD32单片机中通过DMA和TIMER0定时器协作,配置ADC进行高效的电压测量。重点讲解了DMA初始化、TIMER0通道0配置以及ADC数据读取的过程,以实现低资源占用下的连续AD转换。
摘要由CSDN通过智能技术生成

一、简介

由于需要使用GD32的片上ADC采集输入电压,所以了解了关于内部ADC的配置,这里为了不占用过多内核资源,我选择用DMA的方式定时采集ADC数据。因为CH1和CH2用来做串口数据收发,所以只能选择CH0:
在这里插入图片描述
至于ADC的外部触发选择TIMER0_CH0做为ADC规则通道的外部触发源。

二、初始化

DMA初始化

这里每次触发后连续读取2次AD值后结束DMA数据传输。

uint16_t ad_value[2];
void dma_config(void)
{
	    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA);
	
    dma_parameter_struct dma_init_struct;

    /* initialize DMA channel0 */
    dma_deinit(DMA_CH0);
    dma_init_struct.direction    = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr  = (uint32_t)ad_value;
    dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
    dma_init_struct.number       = 2;
    dma_init_struct.periph_addr  = (uint32_t)&(ADC_RDATA);
    dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
    dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA_CH0, &dma_init_struct);
    
    /* configure DMA mode */
    dma_circulation_enable(DMA_CH0);
    dma_memory_to_memory_disable(DMA_CH0);
    
    /* enable DMA channel0 */
    dma_channel_enable(DMA_CH0);
}

TIMER0通道0初始化

void timer_config(void)
{
    /* enable TIMER0 clock */
    rcu_periph_clock_enable(RCU_TIMER0);
	
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    timer_deinit(TIMER0);

    /* TIMER0 configuration */
    timer_initpara.prescaler         = 5;// 72/6 = 12MHz
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 399;// 12MHz/400 = 30KHz
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER0, &timer_initpara);

    /* CH0 configuration in PWM mode1 */
    timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_LOW;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
    timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara);

    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 100);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER0);
    timer_primary_output_config(TIMER0, ENABLE);
}

adc初始化

void adc_config(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
    /* ADCCLK = PCLK2/6 */
    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);// ADC时钟为 72/6 = 12MHz

    /* enable ADC clock */
    rcu_periph_clock_enable(RCU_ADC);
	
	/* ADC输入PA1 */
	gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);	
	
	dma_config();
	
	timer_config();
    /* ADC channel length config */
    adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);

    /* ADC regular channel config */
    adc_regular_channel_config(0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);//序号0 通道1,采样周期55.5

    /* ADC external trigger enable */
    adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
    /* ADC external trigger source config */
    adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0);//选择TIMER0_CH0为外部触发源
    /* ADC data alignment config */
    adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
    /* enable ADC interface */
    adc_enable();
    /* ADC calibration and reset calibration */
    adc_calibration_enable();
    /* ADC DMA function enable */
    adc_dma_mode_enable();
}

三、AD数据读取

uint16_t adc_get_channel(void)
{
	uint16_t recv_ad_val = 0;
	timer_enable(TIMER0);
	/* test on channel0 transfer complete flag */
	while( !dma_flag_get(DMA_CH0, DMA_FLAG_FTF));
	/* clear channel0 transfer complete flag */
	dma_flag_clear(DMA_CH0, DMA_FLAG_FTF);
	
	/* TIMER0 counter disable */
	timer_disable(TIMER0);
	recv_ad_val = (ad_value[0]+ad_value[1])/2;
	return recv_ad_val;
}

输出实际电压=recv_ad_val/4096 * 3.3V

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值