STM32基于HAL库的非DMA的轮询ADC单通道与多通道的采样
目录
单通道(连续转换模式)
扫描模式失能,间断模式失能,连续转换模式使能
规则模式使能
对于F1系列的芯片
HAL_ADCEx_Calibration_Start(&hadc1); //AD校准
F4则不需要,已经自动进行了校准
在while前只需启动一次ADC
HAL_ADC_Start(&hadc1); //启动ADC转换
定时读取adc
if(adct>1000){
adct=0;
HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
adcval[0] = HAL_ADC_GetValue(&hadc1); //获取AD值
printf("ADC1 Reading : %d \r\n",adcval[0]);
printf("PA1 True Voltage value : %.4f \r\n",adcval[0]*3.3f/4096);
}
}
串口读取
[2022-07-20_18:10:59:740]ADC1 Reading : 2017
[2022-07-20_18:10:59:740]PA1 True Voltage value : 1.6250
单通道(单次转换模式)
而单次转换每次转换都要启动adc
HAL_ADC_Start(&hadc1); //启动ADC转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms
非DMA的多通道采样
这个问题困扰了我很久,轮询模式(单次加间断)我也试过了,多通道测试的时候数据不准,比如两个通道的引脚外接0或3.3v的电压,要么就都是0要么就都是3.3
但经过测试又读出来不一样两个通道的电压值又不一样
参考
stm32cubeMX配置ADC多通道采集(非dma和中断方式)_Error-500的博客-CSDN博客_stm32扫描多通道采集
对比cubeMX依据hal库生成的adc初始化代码
只要在cubeMX里配置多通道,那么多通道就给你使能了。
另外还有这两句
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
这样配置明显后者设置的通道覆盖了前者,属于冗余的代码。
这是通道配置的结构体参数,也就是sConfig
再进入HAL_ADC_ConfigChannel(对寄存器进行赋值)
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
还是之前没有去仔细看配置过程,单纯为了用库而用库,所以按照很多教程(非DMA得多通道采样都失败了。)
最终看到正点原子文档上的代码。(它用的hal库,但延续了标准库的风格,所以完全就是自己写,没有用cubeMX去自动生成代码)
最终解决方法:简单地说就是让多通道变成单通道,改配置就好了,改的配置就是通道!因为cubeMX只生成了一次,所以就定义了一次配置。。。。
重写adc的初始化: 也就是变成单通道
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
}
另外引脚的GPIO初始化为模拟输入这个用cubeMX生成的就可以。
每次根据自己想读的adc通道去进行读取,也就是改adc句柄的配置,以adc1位例子
u16 get_adc(u32 ch){
ADC_ChannelConfTypeDef _adc;
_adc.Channel=ch;
_adc.Rank=1;
_adc.SamplingTime=ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1,&_adc);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
return (u16)HAL_ADC_GetValue(&hadc1);
}
效果 (引脚测试电压正确)
结论:多通道按单通道配置。我测试的时候是单次转换和连续转换都行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?