【STM32】CubeMX+HAL库之ADC+DMA
前言
本文首先讲解STM32CubeMX配置多种模式ADC的操作,以及HAL库ADC接口函数,详细的讲解ADC的模式(独立模式、双/三重模式以及扫描模式、连续与间断模式,DMA接收等),本文将HAL库与STM32CubeMX结合在一起讲解,可以更快速的学会ADC的使用。
ADC-----模拟量转数字量的转换器。
所用工具:
- 开发板:STM32G474RE
- STM32CubeMX
- IDE: Keil-MDK
STM32CubeMX ADC配置
-
时钟配置 (如不了解点击下面链接)
【STM32】CubeMX+HAL库之时钟.
2.ADC配置
1.选择ADC模块(ADC1/ADC2/ADC3 ·····)
2.选择ADC通道(IN1/IN2/IN3 ····)
3.进行相关配置
在配置之前讲述独立模式与双/三重模式的区别,在只开启一个ADC模块时只能开启独立模式,双/三重模式是需要开启两个或者三个ADC模块时启用,并且打开相同通道,使用相同管脚读取转换后的值,好处就是提高采样率。如不需此操作就选择独立模式。
扫描模式在开启相同ADC模块下的多个通道并在第三个下拉菜单rank中设置各通道的顺序就会自动的打开扫描模式。
连续转换模式使能连续转换模式效果是在一个通道转换完毕后立刻转换下一个通道,不需要通过其他方式触发。
非连续转换模式使能后,会将多个通道捆绑,也就是说,一次转换多个,然后等待信号,之后再转换多个。
根据需要配置相应选项
在这里我们将使用一个ADC模块的三个通道启用DMA模式首先开启DMA
配置选项
3.生成代码 点击右上角 GENERATE CODE
代码示例
由于ADC_DR寄存器不是一个数组,而是一个16位的变量,所以只能保存最新的转换结果。例如,通道1和通道2都使用,通道1的转换结果放在DR寄存器。通道2转换完毕以后,就会覆盖通道1的结果。
程序里,当然可以通过一些处理,让通道1的结果在被覆盖之前就保存好。不过,运用STM32的DMA功能,可以更好地解决结果被覆盖的问题。
1.首先定义需要的变量Private variables
根据需要更改定义的通道个数以及采样次数
uint16_t i;
#define ADC1_CHANNEL_CNT 3 //采样通道数
#define ADC1_CHANNEL_FRE 3 //单个通道采样次数,用来取平均值
uint16_t adc1_val_buf[ADC1_CHANNEL_CNT*ADC1_CHANNEL_FRE]; //传递给DMA存放多通道采样值的数组
uint32_t adc1_aver_val[ADC1_CHANNEL_CNT] = {0}; //计算多通道的平均采样值的过程数组
uint16_t value[ADC1_CHANNEL_CNT] = {0};//多通道的平均采样值的数组
2.在主函数中添加开启ADC DMA的函数
这里解释一下HAL_ADC_Start_DMA()函数,第一个参数是ADC的操作句柄;第二个参数是用来保存ADC转换结果的数组的地址,是内容的copy所以要传递数组的地址;第三个参数是转换的数据长度。
if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc1_val_buf, (ADC1_CHANNEL_CNT*ADC1_CHANNEL_FRE)) != HAL_OK)
{
/* Start Conversation Error */
Error_Handler();
}
3.添加解算部分代码(例子使用均值滤波)
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
for(i = 0; i < ADC1_CHANNEL_CNT; i++)
{
adc1_aver_val[i] = 0;
}
/* 在采样值数组中分别取出每个通道的采样值并求和 */
for(i = 0; i < ADC1_CHANNEL_FRE; i++)
{
adc1_aver_val[0] += adc1_val_buf[i*ADC1_CHANNEL_CNT+0];
adc1_aver_val[1] += adc1_val_buf[i*ADC1_CHANNEL_CNT+1];
adc1_aver_val[2] += adc1_val_buf[i*ADC1_CHANNEL_CNT+2];
}
/* 依次对每个通道采样值求平均值 */
for(i = 0; i < ADC1_CHANNEL_CNT; i++)
{
value[i] = adc1_aver_val[i] / ADC1_CHANNEL_FRE;
}
}