可以将DMA、ADC和USART连在一起,通过DMA实现ADC采集后数据的自动传输到USART进行发送。以下是基于GD32的例程,需要使用GD32标准固件库。
首先,需要进行相关的初始化,包括DMA、ADC、USART和GPIO。
#include "gd32e10x.h"
void dma_adc_usart_init(void)
{
/* DMA clock enable */
rcu_periph_clock_enable(RCU_DMA);
/* ADC clock enable */
rcu_periph_clock_enable(RCU_ADC);
/* USART clock enable */
rcu_periph_clock_enable(RCU_USART0);
/* GPIO clock enable */
rcu_periph_clock_enable(RCU_GPIOA);
/* DMA configuration */
dma_deinit(DMA_CH0);
dma_parameter_struct dma_init_struct;
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)adc_value;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = 1;
dma_init_struct.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
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);
/* ADC configuration */
adc_parameter_struct adc_init_struct;
adc_struct_para_init(&adc_init_struct);
adc_init_struct.clock_sync = ADC_CLOCK_SYNC_PCLK_DIV4;
adc_init_struct.resolution = ADC_RESOLUTION_12B;
adc_init_struct.data_alignment = ADC_DATAALIGN_RIGHT;
adc_init_struct.scan_mode = ADC_SCAN_MODE_SINGLE;
adc_init_struct.continuous_mode = DISABLE;
adc_init_struct.external_trigger = ADC_EXTERNAL_TRIGGER_DISABLE;
adc_init_struct.channel_number = 0;
adc_init(ADC0, &adc_init_struct);
adc_calibration_enable(ADC0);
/* USART configuration */
usart_deinit(USART0);
usart_parameter_struct usart_init_struct;
usart_struct_para_init(&usart_init_struct);
usart_init_struct.baud_rate = 115200;
usart_init_struct.word_length = USART_WL_8BIT;
usart_init_struct.stop_bits = USART_STB_1BIT;
usart_init_struct.parity = USART_PM_NONE;
usart_init_struct.mode = USART_MODE_TX;
usart_init_struct.flow_restriction = USART_FLOWCONTROL_NONE;
usart_init_struct.overrun_error_detection = USART_OEDETECT_DISABLE;
usart_init(USART0, &usart_init_struct);
usart_enable(USART0);
/* GPIO configuration */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
/* Enable DMA channel */
dma_channel_enable(DMA_CH0);
}
然后,在ADC采样和USART发送之间使用DMA进行数据传输。
void dma_adc_usart_transfer(void)
{
/* Start ADC conversion */
adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL);
while(!adc_flag_get(ADC0, ADC_FLAG_EOC));
/* DMA transfer */
dma_transfer_enable(DMA_CH0);
/* Wait for transfer to complete */
while(dma_flag_get(DMA_CH0, DMA_FLAGF_FTF) == RESET);
/* Clear DMA flag */
dma_flag_clear(DMA_CH0, DMA_FLAGF_FTF);
/* USART send data */
usart_data_transmit(USART0, adc_value[0]);
}
完整的代码如下:
#include "gd32e10x.h"
uint16_t adc_value[1];
void dma_adc_usart_init(void)
{
/* DMA clock enable */
rcu_periph_clock_enable(RCU_DMA);
/* ADC clock enable */
rcu_periph_clock_enable(RCU_ADC);
/* USART clock enable */
rcu_periph_clock_enable(RCU_USART0);
/* GPIO clock enable */
rcu_periph_clock_enable(RCU_GPIOA);
/* DMA configuration */
dma_deinit(DMA_CH0);
dma_parameter_struct dma_init_struct;
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)adc_value;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = 1;
dma_init_struct.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
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);
/* ADC configuration */
adc_parameter_struct adc_init_struct;
adc_struct_para_init(&adc_init_struct);
adc_init_struct.clock_sync = ADC_CLOCK_SYNC_PCLK_DIV4;
adc_init_struct.resolution = ADC_RESOLUTION_12B;
adc_init_struct.data_alignment = ADC_DATAALIGN_RIGHT;
adc_init_struct.scan_mode = ADC_SCAN_MODE_SINGLE;
adc_init_struct.continuous_mode = DISABLE;
adc_init_struct.external_trigger = ADC_EXTERNAL_TRIGGER_DISABLE;
adc_init_struct.channel_number = 0;
adc_init(ADC0, &adc_init_struct);
adc_calibration_enable(ADC0);
/* USART configuration */
usart_deinit(USART0);
usart_parameter_struct usart_init_struct;
usart_struct_para_init(&usart_init_struct);
usart_init_struct.baud_rate = 115200;
usart_init_struct.word_length = USART_WL_8BIT;
usart_init_struct.stop_bits = USART_STB_1BIT;
usart_init_struct.parity = USART_PM_NONE;
usart_init_struct.mode = USART_MODE_TX;
usart_init_struct.flow_restriction = USART_FLOWCONTROL_NONE;
usart_init_struct.overrun_error_detection = USART_OEDETECT_DISABLE;
usart_init(USART0, &usart_init_struct);
usart_enable(USART0);
/* GPIO configuration */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
/* Enable DMA channel */
dma_channel_enable(DMA_CH0);
}
void dma_adc_usart_transfer(void)
{
/* Start ADC conversion */
adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL);
while(!adc_flag_get(ADC0, ADC_FLAG_EOC));
/* DMA transfer */
dma_transfer_enable(DMA_CH0);
/* Wait for transfer to complete */
while(dma_flag_get(DMA_CH0, DMA_FLAGF_FTF) == RESET);
/* Clear DMA flag */
dma_flag_clear(DMA_CH0, DMA_FLAGF_FTF);
/* USART send data */
usart_data_transmit(USART0, adc_value[0]);
}
int main(void)
{
/* DMA, ADC, USART and GPIO initialization */
dma_adc_usart_init();
while(1)
{
/* DMA, ADC and USART data transfer */
dma_adc_usart_transfer();
}
}