STM32CubeMX | STM32使用HAL库的ADC多通道数据采集(DMA+非DMA方式)+ 读取内部传感器温度
ADC模式介绍:
- 扫描模式: 使用STM32CUBEMX配置了多通道后,这一项默认开启且无法设置成关闭。这个模式就是自动扫描你开启的所有通道进行转换,直至转换完,例如你开启了CH0、CH1、CH2、CH3这四个通道,启动转换后ADC会自动将这4个通道全部转换完,但是这种连续性是可以被打断的,所以就引出了间断模式。
- 连续模式: 在CUBE中选中ENABLE就是连续模式,DISABLE就是单次模式。这个模式顾名思义,还是以CH0、CH1、CH2、CH3这四个通道为例,如果开启了连续模式那么就是一直在扫描多通道进行采集,也就是采集完这4个通道后又重新开始采集,不会停止;如果关闭了连续模式,多通道扫描4个通道各采集一次后就停止采集了不会从头再来。
- 间断模式: 可以将多个通道进行自动分组,例如你开启了CH0~3这4个通道,假如你设置了间断次数为4,就相当于将4个通道分成了4组,每组1个通道,那么要想采集完这4个通道就需要手动触发4次ADC采集;如果设置了间断次数为2,那么采集完4个通道就需要手动触发2次ADC采集。
案例一:轮训方式多通道采集
方式一:自用ADC的间断和扫描模式
我开启了通道0、1、2以及内部温度读取通道一共四个通道:
如果想使用轮训方式并且不使用DMA的多通道采集,那么就要配置为 【单次模式+间断模式】,并且将Number Of Discontinuous Conversions为1,也就是每个通道分成了一个组,配置如下图:
由于我这里设置间断数为1,也就是将4个通道分成了4组,那么我每次采集的时候都需要手动去触发ADC采集,也就是调用一次HAL_ADC_Start函数,完整代码如下:
我将通道0分别接到3.3V和GND上,4通道采集运行效果如下:
方式二:完全轮训
完全使用轮训的方式不能使用扫描模式,但是使用STM32CUBEMX配置多通道扫描模式不无法被关闭的,所以我们先用STM32CUBEMX配置成一个通道:
然后读取ADC采集数值的函数是这样:
uint16_t ADC_Read(uint32_t Channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = Channel; /* 通道 */
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; /* 采样时间 */
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
return (uint16_t)HAL_ADC_GetValue(&hadc1);
}
/*
uint16_t ADC_Value[5];
ADC_Value[0] = ADC_Read(ADC_CHANNEL_1); // 采集并读取通道1
ADC_Value[1] = ADC_Read(ADC_CHANNEL_4);
ADC_Value[2] = ADC_Read(ADC_CHANNEL_5);
ADC_Value[3] = ADC_Read(ADC_CHANNEL_6);
ADC_Value[4] = ADC_Read(ADC_CHANNEL_7);
*/
案例二:DMA实现多通道采集
通过DMA实现多通道数据采集,要将连续模式和间断模式关闭;如果连续模式开启,那么通过DMA传输到的数组中,每个通道所采集到的值对应数组中的一个位置就是不固定的,例如你开启了IN0~IN3这四个通道,ADC_Value这是个大小为4的u16类型数组,你在第一次采集的时候IN0的数值通过DMA被放在ADC_Value[0],第二次采集的时候IN0采集到的数值就被放到了ADC_Value[1],这样的话就极不方便我们对每个通道的数据进行分析和提取。
配置如下如:
开启ADC中断:
开启DMA:
代码如下:
4个通道采集运行效果如下:
补充:内部温度传感器ADC通道
上面图片是截取在STM32F103RC的datasheet中的,中文意思就是:温度传感器必须产生随温度线性变化的电压。转换范围在2v < VDDA < 3.6 V之间。温度传感器内部连接ADC1_IN16输入通道,用于将传感器输出电压转换为数字值。
内部温度计算公式:
【Temperature = {(V25 - VSENSE) / Avg_Slope} + 25】
字段说明:
- V25: 最小1.34V,最大1.52V,典型值1.43V
- Avg_Slope: 最小4.0,最大4.6,典型值4.3mv/℃
- VSENSE: ADC采集到的电压
ADC值转电压值计算公式:【电压 = ADC采集到的值 * 3.3 / 4096】
看上图我采集到的值为1703,先转换为电压值:1703*3.3/4096≈1.37
转换为温度:(1.43 - 1.37)/ 4.3 + 25 ≈ 25.01℃
2021年8月24号修正:上面这个计算有误,应该是:(1.43 - 1.37)/ 0.0043 + 25 ≈ 38.95℃
感谢评论区 @Li_Gao 的提醒~!
ends…