GD32H759的ADC的DMA传输,DMA传输完成后进入传输完成中断后,ADC需要重新初始化才能正常采样。如果不开启传输完成中断,ADC可以一直采样传输。但是一使用传输完成中断,在传输完成中断中先关闭DMA通道,读取完数据后,在开启DMA通道后,要重新初始化ADC才能正常采样,否则ADC就无法采样数据完成DMA传输完成中断。ADC和DMA配置如下:
/*!
\brief configure the DMA peripheral
\param[in] none
\param[out] none
\retval none
*/
void adc_dma_config(void)
{
/* ADC_DMA_channel configuration */
dma_single_data_parameter_struct dma_single_data_parameter;
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
nvic_irq_enable(DMA0_Channel0_IRQn, 2, 0);
rcu_periph_clock_enable(RCU_DMA0);
rcu_periph_clock_enable(RCU_DMAMUX);
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
nvic_irq_enable(DMA0_Channel0_IRQn, 1, 0);
SCB_CleanDCache_by_Addr((uint32_t*)WindADC_Buf, WIND_ADCBUF_SIZE*2);
/* ADC DMA_channel configuration */
dma_deinit(DMA0, DMA_CH0);
/* initialize DMA single data mode */
dma_single_data_parameter.request = DMA_REQUEST_ADC2;
dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC2));
dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_single_data_parameter.memory0_addr = (uint32_t)(&WindADC_Buf);
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 = WIND_ADCBUF_SIZE;
dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_single_data_parameter.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
dma_single_data_mode_init(DMA0, DMA_CH0, &dma_single_data_parameter);
/* enable DMA circulation mode */
dma_circulation_enable(DMA0, DMA_CH0);
dma_interrupt_enable(DMA0, DMA_CH0, DMA_INT_FTF);
/* enable DMA channel */
dma_channel_enable(DMA0, DMA_CH0);
}
void adc_config(void)
{
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_GPIOC); // 使能GPIOC时钟
rcu_periph_clock_enable(RCU_ADC2); // 使能ADC2时钟
syscfg_analog_switch_enable(SYSCFG_PC2_ANALOG_SWITCH);
syscfg_analog_switch_enable(SYSCFG_PC3_ANALOG_SWITCH);
/* reset ADC */
adc_deinit(WIND_ADC);
/* ADC clock config */
adc_clock_config(WIND_ADC, ADC_CLK_SYNC_HCLK_DIV6);
/* ADC contineous function enable */
adc_special_function_config(WIND_ADC, ADC_CONTINUOUS_MODE, ENABLE);
/* ADC scan mode enable */
adc_special_function_config(WIND_ADC, ADC_SCAN_MODE, ENABLE);
/* ADC resolution config */
adc_resolution_config(WIND_ADC, ADC_RESOLUTION_12B);
/* ADC data alignment config */
adc_data_alignment_config(WIND_ADC, ADC_DATAALIGN_RIGHT);
/* ADC channel length config */
adc_channel_length_config(WIND_ADC, ADC_REGULAR_CHANNEL, 1);
/* ADC regular channel config */
adc_regular_channel_config(WIND_ADC, 0, WIND_ADC_DP_CHANNEL, 0);
adc_channel_differential_mode_config(WIND_ADC, ADC_DIFFERENTIAL_MODE_CHANNEL_0, ENABLE);
/* ADC trigger config */
adc_external_trigger_config(WIND_ADC, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
/* ADC DMA function enable */
adc_dma_request_after_last_enable(WIND_ADC);
adc_dma_mode_enable(WIND_ADC);
/* enable ADC interface */
adc_enable(WIND_ADC);
/* wait for ADC stability */
delay_ms(1);
/* ADC calibration mode config */
adc_calibration_mode_config(WIND_ADC, ADC_CALIBRATION_OFFSET);
/* ADC calibration number config */
adc_calibration_number(WIND_ADC, ADC_CALIBRATION_NUM1);
/* ADC calibration and reset calibration */
adc_calibration_enable(WIND_ADC);
/* ADC software trigger enable */
adc_software_trigger_enable(WIND_ADC, ADC_REGULAR_CHANNEL);
}
void DMA0_Channel0_IRQHandler(void)
{
if(RESET != dma_interrupt_flag_get(DMA0, DMA_CH0, DMA_INT_FLAG_FTF))
{
dma_interrupt_flag_clear(DMA0, DMA_CH0, DMA_INT_FLAG_FTF);
dma_channel_disable(DMA0, DMA_CH0);
SCB_InvalidateDCache_by_Addr((uint32_t*)WindADC_Buf, WIND_ADCBUF_SIZE*2);
memset(WindADC_Buf,0,WIND_ADCBUF_SIZE*2);
LED0_TOGGLE();
}
}
int main(void)
{
adc_dma_config();
adc_config();
while(1)
{
dma_channel_enable(DMA0, DMA_CH0);
adc_software_trigger_enable(WIND_ADC, ADC_REGULAR_CHANNEL);
delay_ms(100);
}
return 0;
}
|
|