GD32F407 ADC+DMA
#define VDDA_APPLI ((uint32_t) 3300) /* Value of analog voltage supply Vdda (unit: mV) */
#define RANGE_12BITS ((uint8_t) 12) //移位/* Max digital value with a full range of 12 bits */
#define COMPUTATION_DIGITAL_12BITS_TO_VOLTAGE(ADC_DATA) ( ((ADC_DATA) * VDDA_APPLI ) >> RANGE_12BITS)
uint16_t g_adc_dma_data[DRI_ADC_TIMES * DRI_ADC_NUMBER] = {0};
int dri_dma1_channel0_init(void)
{
dma_single_data_parameter_struct dma_init;
rcu_periph_clock_enable(RCU_DMA1);
dma_deinit(DMA1, DMA_CH0);
dma_init.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
dma_init.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init.memory0_addr = (uint32_t)g_adc_dma_data;
dma_init.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
dma_init.priority = DMA_PRIORITY_HIGH;
dma_init.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
dma_init.direction = DMA_PERIPH_TO_MEMORY;
dma_init.number = DRI_ADC_TIMES * DRI_ADC_NUMBER;
dma_single_data_mode_init(DMA1, DMA_CH0, &dma_init);
/* enable DMA circulation mode */
dma_circulation_enable(DMA1, DMA_CH0);
return 0;
}
int dri_adc0_init(void)
{
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC0);
/* config ADC clock */
adc_clock_config(ADC_ADCCK_PCLK2_DIV6);
rcu_periph_clock_enable(RCU_GPIOA);
/* config the GPIO as analog mode */
#if OPT_CHECK_EN > 0u
gpio_mode_set(DRI_ADC_OPT_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, DRI_ADC_OPT_PIN);
#endif
#if RF_CHECK_EN > 0u
gpio_mode_set(DRI_ADC_RF_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, DRI_ADC_RF_PIN);
#endif
/*reset all*/
adc_deinit();
/*!< ADC synchronization mode disabled.All the ADCs work independently */
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
/*连续模式*/
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
/*扫描模式*/
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
/* ADC channel length(num) config */
adc_channel_length_config(ADC0,ADC_ROUTINE_CHANNEL, 2);
/* ADC data alignment config */
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
/* ADC resolusion 12B */
adc_resolution_config(ADC0,ADC_RESOLUTION_12B);
/*禁用外部触发,只能使用软件触发*/
adc_external_trigger_source_config(ADC0, ADC_ROUTINE_CHANNEL, ADC_EXTTRIG_ROUTINE_T0_CH0);
adc_external_trigger_config(ADC0, ADC_ROUTINE_CHANNEL, ENABLE);
/* ADC routine channel config */
#if OPT_CHECK_EN > 0u
adc_routine_channel_config(ADC0, 0 , DRI_ADC_CHENNEL_OPTICAL, ADC_SAMPLETIME_15);
#endif
#if RF_CHECK_EN > 0u
adc_routine_channel_config(ADC0, 1 , DRI_ADC_CHENNEL_RF, ADC_SAMPLETIME_15);
#endif
adc_end_of_conversion_config(ADC0, ADC_EOC_SET_CONVERSION);
adc_dma_request_after_last_enable(ADC0);
adc_dma_mode_enable(ADC0);
/* enable ADC interface */
adc_enable(ADC0);
dri_timer_delay_us(1000);
/* wait for ADC stability */
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC0);
return 0;
}
void dri_adc0_dma1_init(void)
{
dri_adc0_init();
dri_dma1_channel0_init();
/*使能DMA通道*/
dma_channel_enable(DMA1, DMA_CH0);
/*软件触发*/
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}
static uint32_t dri_adc_sample_filter(uint32_t ulADCChannel, uint16_t *pusSample)
{
uint16_t i = 0;
uint16_t strtcnt = 0;
uint32_t filterValue = 0;
#if RF_CHECK_EN && OPT_CHECK_EN
if(ulADCChannel == DRI_ADC_CHENNEL_OPTICAL)
strtcnt = 0;
else
strtcnt = 1;
#else
strtcnt = 0;
#endif
for(i = strtcnt; i < DRI_ADC_TIMES * DRI_ADC_NUMBER; i += DRI_ADC_NUMBER)
{
filterValue += pusSample[i];
}
ADC_DEBUG("filterValue %d\r\n", filterValue);
filterValue /= DRI_ADC_TIMES;
return filterValue;
}
uint16_t dri_adc_convert(uint32_t ulADCChannel, uint8_t ucMode)
{
uint32_t ulSampleAvg = 0;
uint16_t fVoltage = 0;
ulSampleAvg = dri_adc_sample_filter(ulADCChannel, g_adc_dma_data);
switch(ucMode)
{
case DRI_ADC_OUTPUT_VOLTAGE:
fVoltage = COMPUTATION_DIGITAL_12BITS_TO_VOLTAGE(ulSampleAvg);
break;
default:
fVoltage = (uint16_t)ulSampleAvg;
break;
}
return fVoltage;
}