Blackpill WeAct v3.0读取NTC时ADC读数异常:置_outPin为LOW后出错
硬件配置
- 开发板:Blackpill WeAct v3.0
- 微控制器:STM32F401CEU6
- IDE:Platformio
- 核心库:STM32duino
问题背景
使用带滤波电容的NTC分压电路(NTC与固定电阻Rs串联,分压点接滤波电容到地后连ADC输入),采用以下流程读取温度:
- 将
temp_outpin置为HIGH - 读取
temp_inpin的ADC值并计算温度 - 将
temp_outpin置为LOW
当temp_outpin始终保持HIGH时读数正常,但添加digitalWrite(_outPin, LOW);后读数异常,尝试1-100ms延迟无法解决,需要低功耗的可行方案。
核心原因与解决办法
1. 滤波电容充放电时序不匹配
当_outPin置为LOW时,STM32推挽输出模式会直接将引脚接地,滤波电容会快速放电至0V。下次读取时,即使立刻置HIGH,电容需要重新充电到NTC与Rs的分压值,若充电时间不足,ADC读取的是未稳定的电压,导致计算出的温度异常。
解决步骤:
将充电延迟放在置HIGH之后、循环采样之前,确保电容完全充电至稳定值:
digitalWrite(_outPin, HIGH); delay(100); // 根据电容大小调整,比如10uF电容需200ms以上,100nF只需10ms float accumulated = 0; for (int i = 0; i < iterations; i++) { delay(1); // 给ADC采样留微小缓冲时间 int adc = analogRead(_inPin); // 温度计算逻辑不变 float rt = ((adc * rs) / ((pow(2, resolution)) - adc)); rt = rt / r0; rt = log(rt); float temp = beta / (rt + beta / t0); temp = temp - 273.5; accumulated += temp; } digitalWrite(_outPin, LOW); temperature = accumulated / iterations + offset;
可通过RC充电公式计算准确等待时间:T = -R*C*ln(1-Vtarget/Vcc),其中R为Rs与NTC的串联电阻,C为滤波电容值,Vtarget为分压后的目标电压。
2. 优化ADC采样时间
STM32默认ADC采样时间较短,面对滤波电容带来的缓变电压,采样电容可能无法充分充电,导致读数误差。
解决步骤:
通过代码修改ADC采样时间(以PA0为例,对应ADC1_IN0):
// 在setup()中配置 analogReadResolution(resolution); ADC->SMPR2 |= ADC_SMPR2_SMP0_2 | ADC_SMPR2_SMP0_1 | ADC_SMPR2_SMP0_0; // 设置最长采样时间480周期
更长的采样时间能提升ADC对缓变电压的读取精度。
3. 改用输入模式替代LOW输出(最优低功耗方案)
将_outPin置为输入模式(高阻态)而非LOW输出,这样滤波电容不会形成放电回路,能保持分压电压,下次读取时无需长时间充电,同时输入模式的引脚功耗远低于推挽输出LOW的功耗。
解决步骤:
// 读取完成后,将引脚设为输入模式 pinMode(_outPin, INPUT); // 下次读取前,重新设为输出并置HIGH pinMode(_outPin, OUTPUT); digitalWrite(_outPin, HIGH); delay(10); // 微小延迟确保电压稳定(因电容未放电,无需长时间等待) // 后续采样计算逻辑不变
4. 调整滤波电容值
若滤波电容过大(如uF级),会大幅增加充放电时间。可尝试将电容减小至10-100nF,平衡滤波效果与响应速度,同时缩短充电等待时间。
5. 确认引脚输出模式
确保_outPin配置为推挽输出模式,避免开漏模式导致的充电缓慢:
pinMode(_outPin, OUTPUT_PUSH_PULL);
内容的提问来源于stack exchange,提问作者Harvid

