一. 前言
二. 主要代码
1. 变量定义
static uint16_t sampling_data[2];// 采样数据
2. 初始化配置函数(GPIO,ADC,DMA)
void ADC_DMA_Init(void)
{
/* GPIO 配置 */
rcu_periph_clock_enable(RCU_GPIOA); // 使能外设时钟。
gpio_mode_set (GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1); // 设置GPIO模式:浮空输入,无上下拉。
gpio_mode_set (GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
/* DMA 配置 */
dma_parameter_struct dma_init_struct; // DMA 初始化参数结构体。
rcu_periph_clock_enable (RCU_DMA); // 使能外设时钟。
dma_deinit (DMA_CH0); // 复位DMA通道x的所有寄存器。
dma_init_struct.periph_addr = (uint32_t)&(ADC_RDATA); // 设置DMA的外设地址,也是DMA数据传输的源地址。ADC单次采样转换结束后,会将数据存入ADC_RDATA地址中
dma_init_struct.memory_addr = (uint32_t)sampling_data; // 设置DMA存储器地址,也是DMAD数据传输的目标地址。
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; // 设置DMA的数据传输方向。
dma_init_struct.number = 2; // 设置DMA一个周期要传输的数据个数,单位由下方设置。ADC使能了两个采样通道,所以DMA每个周期需要传输两个数据。
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;// 设置DMA数据传输的源地址自增算法失能。ADC每次转换后数据存放的缓存地址不变,所以这里将之失能。
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; // 设置DMA数据传输目标地址自增算法使能,因为DMA每个周期需要传送两个数据,所以在一个周期内,目标地址要自增。
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; // 设置DMA从外设中取出的数据位数。因为ADC转化后的数值是16bit,所以这里设置为1字。
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; // 设置DMA存入存储器中的数据位数。
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; // 设置DMA数据传输高优先级。
dma_init (DMA_CH0, &dma_init_struct);// 将结构体送回,初始化DMA通道x
dma_circulation_enable (DMA_CH0); // DMA循环模式使能。这样DMA在传输两个数据结束后,存储器地址复位,自动开启下一轮传输。
dma_memory_to_memory_disable (DMA_CH0); // 存储器到存储器DMA传输使能。因为这里用不上,所以失能。
dma_channel_enable (DMA_CH0); // DMA通道x传输使能
/* ADC 配置 */
rcu_adc_clock_config (RCU_ADCCK_APB2_DIV6); // 设置ADC的采样时钟分频,因为ADC的采样时钟不得高于14MHz。
rcu_periph_clock_enable (RCU_ADC); // 使能外设时钟。
adc_deinit (); // 复位ADC外设。
adc_special_function_config (ADC_SCAN_MODE, ENABLE); // 配置ADC扫描转换模式。
adc_special_function_config (ADC_CONTINUOUS_MODE, ENABLE); // 配置ADC连续转换模式。
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE); // 配置ADC外部触发源是软件触发。
adc_data_alignment_config (ADC_DATAALIGN_RIGHT); // 配置ADC数据对齐方式是右对齐。
adc_channel_length_config (ADC_REGULAR_CHANNEL, 2); // 配置规则通道组或注入通道组的长度。因为要用到两个采样通道,所以是2.
adc_regular_channel_config (0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5); // 配置ADC规则通道组。rank代表扫描顺序,channel要根据ADC通道与GPIO的映射关系表确定。
adc_regular_channel_config (1, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
adc_enable (); // 使能ADC外设
adc_calibration_enable (); // ADC校准复位
adc_dma_mode_enable (); // ADCx DMA请求使能
adc_software_trigger_enable (ADC_REGULAR_CHANNEL); // ADC软件触发使能。
/* 排除原因:延时。原以为是因为配置后没有给够时间,导致配置失败,但是在启动之前加了1s的延时仍然无法采集到数据。*/
/* 猜测原因:应该是在某种不清楚的条件下,将该函数设置的标志位进行的重置。暂且就调用两次,完成ADC+DMA的软件触发方式采集。*/
adc_software_trigger_enable (ADC_REGULAR_CHANNEL);
}
3. 主函数
int main()
{
systick_config();
ADC_DMA_Init();
while (1)
{
SEGGER_RTT_printf(0,"%d, %d\n", sampling_data[0], sampling_data[1]);
delay_1ms(1000);
}
}