免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

STM32+TSW-30低成本浊度检测仪制作教程

STM32+TSW-30低成本浊度检测仪制作教程 简介TSW-30浊度传感器与STM32F103C8T6组合的Keil5工程资源主要面向STM32初学者重点演示ADC转换与DMA传输的配合使用最终将水体浑浊度实时打印到串口。工程以标准外设库为基础源码覆盖定时器、Flash、RCC时钟、ADC、I2C、CAN等常用外设模块模块划分清晰便于理解单片机外设初始化与数据采集流程也能快速复用到其他传感器项目。资源共226个文件压缩包仅7.08MB主体包含Keil5工程文件.uvprojx/.uvoptx、C源码.c/.h、编译链接过程文件.o/.d/.crf/.axf/.hex以及TSW-30传感器技术手册PDF方便对照手册核对引脚定义与电气参数工程还附带清理中间文件的脚本工具便于重新编译和分发。已有1244人学习下载。配套资源提供了完整可运行的工程模板与串口输出逻辑适合作为水质监测、智能灌溉、鱼缸浑浊度检测等课程设计或毕业设计的基础。 很多玩嵌入式、搞水质检测的朋友让我写一篇最省钱的浊度检测方案我直接说结论TSW-30浊度传感器配STM32F103C8T6最小系统板开发环境用Keil5整套下来成本不到二十块却能搭出一台能读数、能标定、能串口输出的浊度检测仪原型。这篇文章不整虚的从硬件原理、接线、环境搭建、代码实现到实测标定全流程走一遍适合刚学STM32想做传感器项目的同学也适合实验室快速验证水质指标。我做这个项目时踩过电压匹配的坑也遇到过Keil5编译死活不过的糟心事所以下面会把我认为最关键的几个点重点展开——尤其是TSW-30的模拟输出和STM32 ADC参考电压之间的匹配问题很多人就是栽在这里。1. 项目思路为什么选这套组合1.1 TSW-30这颗传感器值不值市面上的浊度传感器从几十到上千都有TSW-30属于最便宜的那一档但它并不是玩具。它的核心是红外对管加光学透镜结构利用光在水中透过时被悬浮颗粒散射、吸收的原理来间接反映浊度。模块上同时引出数字输出D0和模拟输出A0板上还带了可调电位器用于设置数字输出的阈值单片机的ADC读A0就能得到与浊度相关的电压信号。TSW-30的常见规格是5V供电、模拟输出范围大约0到4.5V、能覆盖0到1000NTU的量程。注意这个“大约”不同批次、不同商家卖的模块输出电压和NTU的对应关系差异很大所以千万别直接照搬别人代码里的公式必须自己标定。这一点后面我会专门说。1.2 STM32F103C8T6小项目里的“万能钥匙”STM32F103C8T6是Cortex-M3内核、主频72MHz、64KB Flash、20KB RAM带3个USART和10个12位ADC通道。做单路浊度采集加串口输出资源绰绰有余。关键是它便宜最小系统板几块钱就能买到而且资料极其丰富——不管是标准外设库还是HAL库网上随便一搜都是现成的例程出问题基本都能搜到答案。顺带提一下国产替代。现在市面上很多GD32F103C8T6、APM32F103C8T6这类兼容芯片从封装到引脚定义基本和STM32一致很多情况下Keil5里选STM32F103C8的型号、直接烧录也能跑。但要注意国产兼容芯片在Flash等待周期、ADC上电时序等细节上可能和原版有差异如果你碰上烧录后运行异常可以先检查是不是芯片选型和启动文件的问题不要一上来就怀疑代码。1.3 Keil5仍是首选开发环境虽然现在VSCode加插件、IAR、GCC工具链都很流行但新手做STM32项目我还是推荐Keil5。理由很实际教程多、例程多、排查问题容易。网上搜Keil5安装教程、Keil5创建工程步骤、Keil5安装STM32芯片包出来的答案一抓一大把这种生态优势是其他工具链比不了的。而且MDK自带的调试器对ST-Link支持很好直接硬件仿真看变量、看寄存器都很方便。2. 硬件连接与原理2.1 TSW-30的工作原理TSW-30内部结构可以简化成一个红外发光管持续发光光线穿过水样后到达另一侧的光敏晶体管。水越浑悬浮颗粒越多到达光敏管的透射光就越少光敏管输出的电流就越小模块A0口的电压随之降低。所以TSW-30的电压-浊度关系是单调递减的电压高代表水清电压低代表水浊。这也是后面做标定时最容易理解错的地方——别把高电压当成高浊度。模块上除了A0和D0还有VCC和GND两个电源引脚。D0是经过比较器后的数字输出配合板上电位器可以设置“浊度超过某个值时输出低电平或高电平”做简单的报警开关非常方便但精度要求高的场合还是要读A0。2.2 接线与ADC通道选择STM32F103C8T6的ADC1有10个通道分布在PA0到PA7、PB0和PB1上。我习惯用PA1作为浊度传感器的模拟输入通道接线如下TSW-30模块STM32F103C8T6最小系统板VCC5V引脚GNDGNDA0PA1经分压电阻D0不接或接PA0做阈值判断这里有一个必须强调的点TSW-30用5V供电时A0输出电压最高能到4.5V左右而STM32F103C8T6的ADC参考电压是VDDA一般在3.3V。如果你直接把A0接到PA1电压超过3.3V的部分不仅读不出来还可能损伤引脚。最廉价的解决方案是电阻分压但分压比例要算好。我用的方案是在A0和PA1之间串一个3.9K电阻PA1对地再接一个10K电阻。这样分压比是10除以(3.9加10)约等于0.719。4.5V乘以0.719约等于3.24V刚好压在3.3V以内既充分利用了ADC量程又不会烧引脚。如果找不到3.9K用4.7K也能凑合分压比变成10除以(4.7加10)约等于0.684.5V分压后约3.06V安全但量程利用率略低。2.3 关于最小系统板的关键说明我用的STM32F103C8T6最小系统板就是最常见的蓝色Pill板板载AMS1117稳压芯片给5V就能工作板上3.3V也给出来了。这种板子出厂默认BOOT0接低电平、从Flash启动所以只要用ST-Link通过SWD接口接SWDIO、SWCLK、GND、3.3V四根线就能下载调试不需要额外按复位键。注意ADC采集时如果直接用板载3.3V作为参考电压而这个3.3V又是从5V经过线性稳压得到的当传感器电流变化时板载3.3V会有轻微波动导致ADC读数有低频漂移。解决方法是软件滤波加多次采样取平均硬件上也可以在VDDA引脚附近加一个104电容让参考电压更稳。3. Keil5环境搭建与工程创建3.1 安装与芯片包Keil5和老的Keil4不一样它本身只是一个壳芯片支持需要通过Pack Installer装。安装好MDK5后打开在Pack Installer里找到STMicroelectronics目录选STM32F1系列的支持包下载。如果你网络不好也可以去官网下载离线pack文件双击安装即可。这里提醒一下有的电脑装完Keil5后打开工程提示找不到芯片基本就是支持包没装好重新装一遍Pack就能解决。3.2 新建工程步骤与文件组织我习惯把工程目录这样划分Project/ ├── User/ // main.c、stm32f10x_it.c ├── BSP/ // 自己写的板级驱动 ├── CMSIS/ // 内核相关文件 ├── FWLIB/ // 标准外设库源码 └── Output/ // 编译产物创建工程时在Keil5里选新工程弹出Select Device后搜“STM32F103C8”选对应型号。接下来会问你需不需要添加启动文件在老版本的Keil里这一步会直接加启动文件但新版本经常不帮你加强烈建议自己手动添加启动文件startup_stm32f10x_md.sC8T6属于中容量产品要用md这个版本。还要添加system_stm32f10x.c和标准外设库里的stm32f10x_adc.c、stm32f10x_usart.c、stm32f10x_gpio.c、stm32f10x_rcc.c等源文件。然后打开Options for Target在C/C的Define栏写上STM32F10X_MD,USE_STDPERIPH_DRIVER在Include Paths里把User、BSP、CMSIS、FWLIB这些头文件目录全部加进去。这一步漏了编译会报“找不到stm32f10x.h”新手最常见的报错之一就是这个。3.3 编译下载与调试烧录用ST-Link在Debug设置里选择ST-Link Debugger然后切到Settings把端口改成SW速度选低一点的比如1MHz稳定性更好。下载时如果提示找不到目标设备优先检查SWDIO、SWCLK是否接反以及BOOT0是不是被跳线帽接到了高电平。BOOT0接高时芯片会进入系统存储器模式不会响应SWD下载。有人下载完发现板载LED在闪问我正不正常。如果你代码里恰好配置了PC13引脚做翻转那么LED闪烁就完全是你的程序在运行如果代码里没碰过PC13那就要怀疑是不是看门狗在反复复位需要检查初始化代码里是否意外开启了IWDG。正常下载后电源指示灯常亮、程序控制LED闪烁都属于正常现象。4. 核心代码实现4.1 ADC采集我用标准外设库写ADC1初始化代码不长核心就是开启GPIOA和ADC1时钟、把PA1配成模拟输入、设置ADC为独立模式、单通道、右对齐、由软件触发转换。这里给出可直接用的初始化函数void ADC1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, GPIO_InitStructure); ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode DISABLE; ADC_InitStructure.ADC_ContinuousConvMode DISABLE; ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); }校准流程是STM32F1 ADC特有的上电后最好做一次能让内部电容的初始误差被校准掉。很多人上来就读ADC发现初始值有几十个字的偏差多半就是跳过了校准环节。4.2 电压换算与NTU公式采集原始ADC值后要换算回真实电压。PA1处测得的电压先由ADC值除以4096再乘以3.3得到但由于前面有分压电阻需要再除以分压比0.719还原成TSW-30的实际输出电压V_sensor (ADC_Value / 4096.0) * 3.3 / 0.719网上流传的TSW-30经验标定公式是一个二次多项式NTU -1120.4 * V_sensor^2 5742.3 * V_sensor - 4352.9这个公式在特定电源电压和特定模块下是有意义的但它不是万能的。我实际测过把这个公式套在另一个商家买的模块上读数偏差很大。所以我的建议是先用这个公式跑通流程再拿已知浊度的水样做两点或三点标定重新拟合你自己的系数。特别是当你加了分压电阻后V_sensor已经还原为模块原始输出电压所以公式形式可以不变但系数一定要重新标。4.3 串口输出与验证为了方便看数据我开了USART1的printf重定向9600波特率这样在串口助手就能直接看到ADC原始值、还原电压和NTU读数。重定向代码很简单int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); return ch; }主循环里做10次采样取平均再把结果打印出来。我习惯把采样频率控制在5Hz左右既能看到实时变化又不会让串口刷屏刷到看不清。实测下来稳定水样下ADC读数波动一般在正负两三个字以内换算成NTU约在正负几个单位做趋势判断完全够用。5. 实测校准与常见问题5.1 零浊度校准零浊度校准是整套流程里最重要的一步。拿纯净水或蒸馏水静置一段时间让气泡消散把传感器放进水里稳定后记录ADC值或电压这就是零点。由于TSW-30是电压随浊度增大而减小的特性零点电压通常是最高的可能接近4V甚至4.5V。如果这个电压经过分压后超出ADC量程说明分压比设计有问题需要增大分压电阻比例或改用3.3V供电方案。校准的时候要注意传感器探头不能贴住容器底部否则会测到沉淀物水样中的气泡会严重干扰读数必须静置或超声除气探头表面要保持干净不能有指纹或油膜。这些都做到位了零点标定才有参考意义。5.2 常见问题速查表我把这个项目里最容易踩的坑整理成了一张表供你对照排查现象可能原因解决办法Keil5连接不上芯片驱动未装、SWD线接反、BOOT0跳线过高装ST-Link驱动检查SWDIO/SWCLK/GNDBOOT0接低编译报错error: createprocess failed工程路径含中文或被杀毒软件拦截把工程放到纯英文路径关闭实时防护ADC读值一直是4095输入电压超过参考电压检查分压电路是否生效A0是否直接接入ADC读值一直是0引脚未初始化、模块供电不对检查GPIO_AIN配置和VCC/GND接线读数跳动很大电源纹波、水样气泡、采样次数太少增加采样平均次数VDDA加104电容静置水样数值和实际浊度对不上公式系数来自其他模块用已知浊度溶液重新标定下载后LED异常闪烁代码翻转了LED引脚或看门狗复位检查PC13配置和IWDG初始化5.3 踩坑心得最后聊几个实操层面的经验。第一别迷信“5V供电直接接ADC引脚没事”这种说法STM32F103虽然引脚有钳位二极管但长期超压会损坏引脚甚至芯片电阻分压的成本几乎为零不值得省。第二TSW-30模块的响应速度并不快水样变化后电压需要几秒才能稳定所以采集程序里加一个启动延时和稳定判断比疯狂提高采样频率更有意义。第三Keil5新建工程时如果你自己管理工程文件务必把输出目录和中间文件目录分开配置这样工程目录清爽出问题调试也方便。这个项目做完之后你可以很方便地扩展成自动水质监测站点、鱼缸浊度监控或者配合继电器做自动换水装置。核心就一个思路模拟传感器加单片机ADC加串口输出整个链路打通之后剩下的都是应用层的事。希望这篇文章能帮你少走几步弯路。本文还有配套的精品资源点击获取
返回列表