基于STM32的电导率测量仪设计:模拟前端、信号链与校准实战
2026/9/16 18:00:56 网站建设 项目流程

简介:这是一款基于STM32F429的电导率测量仪完整工程资源,面向嵌入式、电子、自动化等专业的开发者与学生,旨在以较低成本实现工业级溶液电导率检测。项目从实际实验需求出发,设计了正弦波驱动、滤波、放大及负电源电压转换等硬件模块,并配套温度传感器、ADC、LCD显示、触摸屏交互、SD卡存储和串口打印等完整软件驱动,可完成数据采集、处理、显示与保存。压缩包共101个文件,以C/H源代码、原理图与PCB设计文档、Keil工程文件、HEX固件、说明文档、图片及演示视频为主,整体约72.96MB,目录结构清晰,便于对照学习与二次开发。目前已有648人学习下载。资源内项目代码经过运行测试,功能可靠,适合用于课程设计、毕业设计或入门进阶。通过学习可以掌握STM32外设驱动、传感器信号调理、模拟电路设计与嵌入式系统集成方法,也可在此基础进行功能扩展,具有较高的参考价值。

1. 基于STM32电导率测量仪的项目定位与可复现路径

用STM32做电导率测量仪,在“基于STM32的毕业设计”里属于模拟链路相对完整、又不需要复杂外设的选题。这个项目不光是写代码,它要求开发者把电极、运放、ADC和定时器串成一条能自洽的信号链:电极输出的电流是微安级,模拟前端要有足够增益,同时激励信号不能是直流,否则极化效应会让读数一直漂。本文从测量原理出发,把模拟前端参数、STM32源代码实现、校准和排错一次讲透,适合手里已经有一份“源代码+文档说明”工程包、但不知道怎么改参数的人看。整条链路下来,你会发现真正决定测量精度的不是主控,而是你选的反馈电阻和采样相位。

2. 电导测量原理与STM32模拟前端电路设计

2.1 电导率公式与电导池常数

电导率不是直接测出来的数字,它是通过电极几何结构换算出来的。两个平行金属极板浸在溶液里,等效成一个电阻R,电导G=1/R,单位是西门子S。把电导乘上由电极结构决定的比例系数K,才能得到不依赖探头尺寸的物理量:

κ = G × K = (1/R) × (L/A)

式中的K就是电导池常数,单位cm⁻¹,L是极板间距,A是电极有效面积。实际探头出厂时标称K值,但装配误差和电极表面状态会让真实K和标称值有偏差,所以后面校准过程本质上就是在修正这个常数。选电极时按下表粗定量程:

被测对象典型电导率范围推荐量程档典型电极常数K
去离子水 / 超纯水0.05 ~ 10 µS/cm200 µS/cm0.01
生活饮用水300 ~ 1500 µS/cm2 mS/cm1.0
农业用水 / 一般废水1 ~ 10 mS/cm20 mS/cm1.0
海水 / 高浓度工业液30 ~ 60 mS/cm200 mS/cm10

同一支电导池,极板面积越大或间距越小,K越小,测低电导率的敏感度越高。设计时先想清楚目标水质,再去买电极和定增益,顺序不能反。

2.2 为什么必须用交流激励

如果给电极加恒定的直流电压,溶液里的正负离子会向两极定向迁移,在电极表面形成极化层。这层极化等效成一个反向电动势,叠加在测量回路上,表现就是电流随时间衰减,读数反复漂移,无法稳定。所以所有电导率仪都用交流激励,极板上的电压极性周期性反转,极化层来不及建立就被打断。

激励频率的选择分两条线。低电导率溶液(低于200 µS/cm)用1kHz左右就够,频率太高时电极界面的双电层电容会变成低阻抗旁路,一部分激励电流不经过溶液而走电容,读数偏低。高电导率溶液(高于10 mS/cm)要提高到5kHz甚至更高,因为这时候体电阻小,需要靠高频来减小双电层电容的影响。这个取舍直接决定定时器的ARR值和低通滤波器的截止频率,是源代码里第一组要调整的参数。

2.3 跨阻放大器把电流变成电压

信号链路的骨架如下:STM32定时器PWM输出方波,经隔直电容变成双极性的交流激励,加到电极一端;电极另一端的电流进入跨阻放大器(TIA),电流在这一级被转换成电压;再经交流放大和低通滤波,送进STM32的ADC引脚。

TIA是整条链路里最关键的一级。电极一端接激励,另一端接运放反相输入端,反相输入端的“虚地”特性保证电极对地电位恒定,这能避免连接电缆的寄生电容和电极极板电容对激励形成分压。输出电压为:

Vout = -I × Rf

负号只表示反相关系。如果激励电压峰峰值为1V,电导G为2mS,那么电流就是2mA;取Rf=510Ω时,TIA输出约±1.02V。后级再接一个放大倍数为2的同相放大器,把信号变成约±2V,接近3.3V ADC的满量程但仍留10%裕量。如果做低量程档,把Rf换成10kΩ即可;所谓量程切换,本质就是切换Rf。

2.3.1 运放参数和地线处理

TIA运放要选输入偏置电流小的型号,普通LM358会在高阻抗反馈电阻上产生明显的失调误差。常见做法是选偏置电流在pA级别的CMOS运放,低成本型号里可选项很多。电源去耦要在运放供电脚就近放10Ω电阻和100nF电容组成RC滤波,把数字部分的高频噪声隔离掉。地线采用单点星形连接,TIA区域的模拟地不要跟STM32的GND大面积铺铜混在一起,否则ADC采样值会出现随串口发包而跳动的毛刺。

2.4 ADC采样参数与频率对齐

STM32F103系列内置12位ADC,转换速率最快1MHz,对1kHz的激励信号来说有充足的过采样空间。用100kHz采样率,一个周期能采到100个点,经过软件求峰峰值之后,噪声能被平均掉不少。如果追求更高分辨率,可以用过采样加求平均的方式,把12位数据提升到等效14位。要注意的是,ADC的采样时序最好由定时器触发,保证采样时刻和PWM激励在同一相位基准上。如果各采各的,电极电容充放电曲线的相位差会导致幅度计算不稳定。

3. STM32源代码实现:激励PWM、DMA采样、温度补偿

3.1 工程结构与文件划分

拿到一份“源代码+文档说明”的STM32项目,先别急着编译,花十分钟看文件划分。常见做法是CubeMX生成初始化代码,Keil MDK5编译调试,业务代码按模块拆开:

文件职责关键接口
main.c时钟、外设初始化、主循环main()
bsp_pwm.c激励方波生成PWM_Init(), PWM_SetFreq()
bsp_adc.cADC+DMA连续采集ADC_Start_DMA()
app_cond.c电导率计算、滤波、量程切换Conductivity_Process()
app_temp.cNTC温度读取NTC_ReadTemp()
app_uart.c结果输出UART_SendFrame()

文档说明里如果附了引脚分配表,第一件事就是对一下CubeMX的引脚配置:TIM2_CH1映射到哪个引脚,ADC1_INx又是哪个引脚,这两处最容易被初始化代码覆盖掉。曾经遇到过PWM和ADC复用同一个引脚,波形根本出不来,原因就是CubeMX重新生成代码时把GPIO模式覆盖了。

3.2 用定时器PWM生成1kHz激励信号

用STM32的定时器做PWM输出,不需要额外芯片,频率还能在代码里直接改。STM32F103的APB1定时器时钟为72MHz,设PSC=71得到1MHz计数时钟,ARR=999时PWM频率正好1kHz,占空比设置为50%产生对称方波。初始化代码如下:

TIM_HandleTypeDef htim2; htim2.Instance = TIM2; htim2.Init.Period = 999; // ARR, 决定频率 htim2.Init.Prescaler = 71; // 72MHz / (71+1) = 1MHz htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_PWM_Init(&htim2); TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 占空比 500/1000 = 50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

这段代码的逻辑是:先通过PSC把定时器时钟降到1MHz,再用ARR做分频得到目标频率。PSC=71、ARR=999时频率为1kHz;要切到5kHz,把ARR改成199,占空比参数Pulse同步改成100即可。引脚输出0~3.3V的单极性方波,后面串一个隔直电容后,变成约±1.65V的交流信号,幅度取决于电容和负载阻抗的分压关系。占空比必须保持50%,否则隔直电容会充上直流偏置,破坏激励对称性。

3.3 ADC用DMA连续采样并分离正负半周

激励频率1kHz,用100kHz采样率一个周期能采100个点。为了不占CPU,ADC配DMA循环模式,采样结果直接写入数组,传满一轮后进回调。代码框架如下:

#define N_SAMPLES 1024 uint16_t adc_buf[N_SAMPLES]; volatile uint8_t dma_done = 0; void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { if (hadc->Instance == ADC1) { dma_done = 1; // 通知主循环处理数据 } } // 主循环中判断标志位 if (dma_done) { dma_done = 0; HAL_ADC_Stop_DMA(&hadc1); process_conductivity(adc_buf, N_SAMPLES); HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buf, N_SAMPLES); }

之所以不在回调里直接处理,是因为数据处理涉及浮点运算和滤波,放在中断里会拖长中断响应时间,还可能影响定时器PWM的抖动。主循环在DMA传输完成的间隙处理数组,处理完立刻重启DMA,中间丢掉的几个采样周期对结果无影响。

process_conductivity里的核心工作是分离信号的正半周和负半周。假设模拟输出以1.65V为中心偏置,方波波形在正半周高于中心值、负半周低于中心值,用边沿检测和阈值判断分组累加:

void process_conductivity(uint16_t *buf, uint32_t len) { uint32_t sum_pos = 0, sum_neg = 0; uint32_t cnt_pos = 0, cnt_neg = 0; uint8_t stage = 0; // 0: 负半周, 1: 正半周 for (uint32_t i = 0; i < len; i++) { if (buf[i] > 1800) { stage = 1; // 高于阈值视为正半周 } else if (buf[i] < 1500) { stage = 0; // 低于阈值视为负半周 } if (stage) { sum_pos += buf[i]; cnt_pos++; } else { sum_neg += buf[i]; cnt_neg++; } } float vpos = (float)sum_pos / cnt_pos * 3.3f / 4095.0f; float vneg = (float)sum_neg / cnt_neg * 3.3f / 4095.0f; float vpp = (vpos - vneg) * 2.0f; // 正负半周差再乘2得到峰峰值 // 后续根据增益换算成电导率 }

阈值1500和1800的选取要配合实际波形的中心值。如果ADC参考电压是3.3V,偏置在中点1.65V,那么ADC码值大约在2048附近,正半周应明显高于2048,负半周明显低于。这两个常数不是通用的,换板子改电源电压时要重新标定。更可靠的做法是在代码里维护一个滑动平均中心值,实时计算阈值区间,但这种自适应方案调试成本较高,工程包自带的文档说明里若没写,就不要自行加上去。

3.4 温度补偿与25℃基准换算

电导率的温度系数很大,溶液温度每升高1℃,电导率大约增加2%。如果仪器不做温度补偿,夏天和冬天的读数差异会很夸张。常见做法是仪器内放一个NTC热敏电阻,测溶液温度,再把实际电导率折算回25℃下的标准值:

float ntc_to_temp(uint16_t adc_raw) { const float r_ref = 10.0f; // 串联电阻 10kΩ const float b_const = 3435.0f; // NTC B值 float r_ntc = r_ref * ((4095.0f / adc_raw) - 1.0f); float t_k = 1.0f / (1.0f / 298.15f + logf(r_ntc / 10.0f) / b_const); return t_k - 273.15f; } float cond_to_25(float cond_t, float temp_c) { const float alpha = 0.02f; // 温度系数约 2%/℃ return cond_t / (1.0f + alpha * (temp_c - 25.0f)); }

NTC计算用的B值公式是近似模型,在0~50℃范围内误差可以控制在0.5℃以内,对电导率补偿来说足够。alpha取0.02是大多数中性盐溶液的近似值,若被测溶液是强酸强碱,alpha会偏差较大,这时候需要在文档里注明用户可配置。

3.5 文档说明要写清楚的接口与协议

一套能给别人复用的工程包,文档至少要覆盖引脚映射、校准参数表、串口协议和量程切换逻辑。串口输出建议定成固定字节帧,方便上位机解析:

字节偏移含义格式
0帧头0xA5
1数据长度uint8
2~5电导率值×100float
6~9温度值×100float
10校验字节累加和

帧结构不宜做得太复杂,Modbus-RTU对毕设项目来说略重,简单帧头加校验就能满足调试和上位机显示需求。源代码里对应的发送函数要和这个表格严格对齐,否则文档和代码对不上,后面调起来非常痛苦。

4. 电导率仪校准、参数标定与现场排错

4.1 两点校准的具体操作

仪表装完,第一件事不是测水样,而是校准。常见做法是买标准电导率溶液,用两点法校准:低点用1413µS/cm的KCl标准液,高点用12.88mS/cm的标准液。流程上,先把电极放进1413µS/cm标准液,稳定30秒后让仪器记录一个ADC原始峰峰值;再换到12.88mS/cm标准液记录第二个点。软件里拿两个点的实测值与标准值做线性回归,求出斜率和截距,写入STM32内部Flash或外部EEPROM。

typedef struct { float gain; // 斜率, 单位 (µS/cm) / (ADC码值) float offset; // 截距, 单位 µS/cm float pool_k; // 实测电导池常数, 默认1.0 } calib_t;

4.2 电极常数K的现场修正

买来的电极标称K=1.0,但实际装到PCB上、线缆长短变了之后,K会有几个百分点的偏差。两点校准算出的gain实际上已经包含了K的影响,所以工程里不必单独修K,直接用量程系数就行。如果换了不同K值的电极,把之前的校准参数清掉,重新做两点校准,不能沿用旧参数,否则高量程会满偏。

4.3 反复出现的漂移问题

漂移是电导率仪最常见的故障。把电极放在标准液里,读数缓慢上升或下降,先排除极化现象:确认激励是交流信号,且频率没有被初始化代码无意间改掉。然后把电极拿出来检查,极板上有油污或氧化物时,有效面积改变,读数会持续漂移,处理方法是清洗电极并用标准液重新校准。还有一种隐蔽情况是被测液体里有气泡附着在极板表面,这会让有效接触面积变小,测出的电导率偏低。

4.4 常见的测量异常排查表

现象可能原因处理方式
读数始终接近零PWM没输出或隔直电容虚焊用示波器量TIM引脚和运放输出
读数偏高且不稳Rf太小,增益不足,信噪比差切换到高阻Rf档重新采样
读数随串口发送跳变数字地噪声串入模拟地检查地线布线,运放电源加RC滤波
温度读数偏差超过2℃NTC分压电阻选错核对NTC B值和10kΩ串联电阻
换水样后读数反应慢电极响应时间或气泡附着搅动溶液排出气泡,检查RC时间常数

给仪器做排错时,最好先把ADC原始值通过串口打印出来,避免看经滤波后的结果。原始值能直接反映模拟链路是否有信号,如果原始值是一条直线,后面再多的算法补偿都没意义。

5. 进阶验证:多量程自动切换与模拟电极自检

5.1 用双反馈电阻实现自动量程切换

单量程仪表测自来水与测海水时,动态范围不够,要么小信号被噪声淹没,要么大信号让运放饱和。常见方案是在TIA反馈回路并联两支电阻,用GPIO控制模拟开关切换,低量程档用高阻值Rf,高量程档切到低阻值Rf。主循环里判断ADC电压幅度:

float vpp_mv = get_vpp(); // 当前峰峰值, 单位mV if (vpp_mv < 200.0f) { switch_rf(HIGH_RF); // 切到 100kΩ 档,适合低电导率 } else if (vpp_mv > 2900.0f) { switch_rf(LOW_RF); // 切到 10kΩ 档,防止饱和 }

设置200mV和2.9V两个切换点,留出滞回区间,避免在临界点反复切换。切换后要等模拟链路稳定,再采集一组数据重新计算,切换瞬间的毛刺不能被滤波器记录进去。

5.2 用精密电阻代替电极做链路自检

校准完电极后,想确认模拟前端本身没有误差,有个很实用的技巧:把电极拆下来,在电极接口两端并接一个精度0.1%的500Ω电阻,模拟一个固定电导负载。这时如果激励幅度和Rf都已知,理论输出电压应为:

Vout = Vin × (Rf / R_test)

实测峰峰值和理论值偏差在0.5%以内,说明整个模拟链路没有问题,误差出在电极或校准参数上;偏差超过2%,就要回头查运放供电、Rf精度和ADC参考电压。这个技巧在工程交付时特别好用,做验收测试时不需要临时配标准液,只用电阻就能把硬件链路验证一遍。

5.3 长时间稳定性观察法

把模拟电极换成精密电阻后,开机连续记录两小时,观察串口输出的电导率数值。正常情况漂移应小于±1%。如果漂移超过这个范围,大概率是运放温漂或ADC参考电压不稳,先在代码里检查是否启用了内部参考电压,模拟参考电压VREF+需要外部基准源才稳定。稳定性测试的数据保存成CSV文件,可直接导入Excel做曲线分析,这一步能让“源代码+文档说明”的交付显得更完整。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询