一、简介
由于需要使用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