因为GD官方给的例程中没有关于ADC2 DMA 独立模式多路采集的例程,所以在此上传一个。
直接上代码
#include "gd32f4xx.h"
#include "gd32f450i_eval.h"
#include "systick.h"
#include <stdio.h>
#define ADC_X ADC2
uint16_t adc_value[4];
void rcu_config(void);
void gpio_config(void);
void dma_config(void);
void adc_config(void);
void timer_config(void);
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* system clocks configuration */
rcu_config();
/* systick configuration */
systick_config();
/* GPIO configuration */
gpio_config();
/* TIMER configuration */
timer_config();
/* ADC configuration */
adc_config();
/* DMA configuration */
dma_config();
/* configure COM port */
gd_eval_com_init(EVAL_COM0);
while(1){
delay_1ms(1000);
printf("\r\n *******************************");
printf("\r\n ADC0 regular channel data = 0x%04X", adc_value[0]);
printf("\r\n ADC0 regular channel data = 0x%04X", adc_value[1]);
printf("\r\n ADC0 regular channel data = 0x%04X", adc_value[2]);
printf("\r\n ADC0 regular channel data = 0x%04X\r\n", adc_value[3]);
}
}
/*!
\brief configure the different system clocks
\param[in] none
\param[out] none
\retval none
*/
void rcu_config(void)
{
/* enable GPIOC clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_ADC2);
/* enable timer1 clock */
rcu_periph_clock_enable(RCU_TIMER1);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
/* enable DMA clock */
rcu_periph_clock_enable(RCU_DMA1);
/* config ADC clock */
adc_clock_config(ADC_ADCCK_PCLK2_DIV6);
}
/*!
\brief configure the GPIO peripheral
\param[in] none
\param[out] none
\retval none
*/
void gpio_config(void)
{
/* config the GPIO as analog mode */
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4 );
}
/*!
\brief configure the DMA peripheral
\param[in] none
\param[out] none
\retval none
*/
void dma_config(void)
{
/* ADC_DMA_channel configuration */
dma_single_data_parameter_struct dma_single_data_parameter;
/* ADC DMA_channel configuration */
dma_deinit(DMA1, DMA_CH0);
/* initialize DMA single data mode */
dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC_X));
dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_single_data_parameter.memory0_addr = (uint32_t)(adc_value);
dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;
dma_single_data_parameter.number = 4;
dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_single_data_mode_init(DMA1, DMA_CH0, &dma_single_data_parameter);
dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);
/* enable DMA circulation mode */
dma_circulation_enable(DMA1, DMA_CH0);
dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI2);
/* enable DMA channel */
dma_channel_enable(DMA1, DMA_CH0);
}
/*!
\brief configure the ADC peripheral
\param[in] none
\param[out] none
\retval none
*/
void adc_config(void)
{
/* ADC mode config */
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
/* ADC contineous function disable */
adc_special_function_config(ADC_X, ADC_CONTINUOUS_MODE, DISABLE);
/* ADC scan mode disable */
adc_special_function_config(ADC_X, ADC_SCAN_MODE, ENABLE);
/* ADC data alignment config */
adc_data_alignment_config(ADC_X, ADC_DATAALIGN_RIGHT);
/* ADC channel length config */
adc_channel_length_config(ADC_X, ADC_REGULAR_CHANNEL, 4);
/* ADC regular channel config */
adc_regular_channel_config(ADC_X, 0, ADC_CHANNEL_1, ADC_SAMPLETIME_15);
adc_regular_channel_config(ADC_X, 1, ADC_CHANNEL_2, ADC_SAMPLETIME_15);
adc_regular_channel_config(ADC_X, 2, ADC_CHANNEL_3, ADC_SAMPLETIME_15);
adc_regular_channel_config(ADC_X, 3, ADC_CHANNEL_4, ADC_SAMPLETIME_15);
/* ADC trigger config */
adc_external_trigger_source_config(ADC_X, ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T1_CH1);
adc_external_trigger_config(ADC_X, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_RISING);
/* ADC DMA function enable */
adc_dma_request_after_last_enable(ADC_X);
adc_dma_mode_enable(ADC_X);
/* enable ADC interface */
adc_enable(ADC_X);
/* wait for ADC stability */
delay_1ms(1);
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC_X);
// /* enable ADC software trigger */
// adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL);
}
/*!
\brief configure the timer peripheral
\param[in] none
\param[out] none
\retval none
*/
void timer_config(void)
{
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
/* TIMER1 configuration */
timer_initpara.prescaler = 19999;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 9999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1,&timer_initpara);
/* CH1 configuration in PWM mode0 */
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1,TIMER_CH_1,&timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,9900);
timer_channel_output_mode_config(TIMER1,TIMER_CH_1,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);
/* enable TIMER1 */
timer_enable(TIMER1);
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM0, (uint8_t)ch);
while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
return ch;
}
1,首先第一个需要注意的地方是 官方的例程中 关于DMA的配置
官方使用的是 DMA1 的通道0 ADC0
dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);
而我们要配置为 DMA1 的通道0 ADC2
dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI2);
2,如果要使用软件触发的话需要同时 使能扫描模式和连续转换模式,如果只使能扫描模式的话只会进行一次转换。
/* ADC contineous function disable /
adc_special_function_config(ADC_X, ADC_CONTINUOUS_MODE, ENABLE);
/ ADC scan mode disable */
adc_special_function_config(ADC_X, ADC_SCAN_MODE, ENABLE);
以上问题也是问了代理商技术支持后解决的,还是感谢技术支持,大家共勉,避免踩坑。