简介:基于STM32F103C8的水库预警系统Proteus仿真方案,面向嵌入式课程设计、毕业设计及Proteus/Keil学习人群,解决多传感器联动控制与可视化仿真验证问题。项目中包含雨量、水流速、压力、风速等传感器检测,配合OLED屏实时显示水位、水质等参数,蜂鸣器高水位报警、LED指示、电机控制放水阀门,以及水泵运行逻辑。压缩包共279个文件,约8.57MB,主要包含c/h源码、uvprojx/uvoptx工程配置、pdsprj仿真电路、hex/axf可执行文件及docx说明文档,可直接在Keil5与Proteus 8.15中打开运行。方案整体提供了从源码编写、硬件仿真到调试运行的一整套参照,既便于上手复现,也可按需修改水位阈值与传感器组合,适合想快速掌握STM32外设驱动和Proteus联合仿真的读者。目前已有181人学习下载,尤其适合独立完成课设或项目验证时参考。
1. 用水库预警系统做Proteus仿真:我为什么劝你先在虚拟环境里跑通
水库预警系统的开发成本里,硬件调试占了大头。传感器探头要防水、信号线要屏蔽、现场供电要稳定,任何一环出错,排查周期都是以天计的。而在一开始就用Proteus做基于STM32的水库预警系统仿真,可以把电路设计、阈值逻辑、传感器接口和报警联动全部压缩到一块开发板的虚拟环境里跑通。仿真通过之后再移植到实物,省下的是板子反复焊、探头反复拆的时间。这篇文章适合两类人:一类是想在毕业设计或课程项目里快速出成果的学生,另一类是已经做过实物、想验证新预警逻辑的工程师。Proteus仿真最大的价值不是替代实物,而是让你在没有探头、没有水库、没有恶劣天气的前提下,提前把代码里的边界条件和报警流程逼出问题。
2. 水库预警的信号选型与阈值逻辑:先定系统再碰电路
2.1 水库预警要采哪些信号:水位、降雨量、温度怎么取舍
水库预警系统的核心是水位,辅以雨量、温度等环境信息。但Proteus仿真里要控制复杂度:传感器越多,元件库匹配、通信时序和采样调度的成本就越高。我一般会先做减法,保留三个信号源:水位(主判据)、温度(校验信号)、回波距离(防溢出辅助判据)。雨量计在Proteus里没有现成可用的标准模型,常见做法是用一个电位器模拟雨量传感器的连续电压输出,接到另一个ADC通道。这个取舍不是偷懒,而是让预警逻辑在仿真阶段先跑通,等实物阶段再接入真实雨量传感器。
水位测量有两种常见路线:一种是压力式水位计,输出4-20mA或0-3.3V模拟电压,直接接STM32的ADC采样;另一种是超声波测距,通过回波时间换算探头到水面的距离,再用安装高度减去距离得到水位。Proteus里HC-SR04模块是现成的,后者更贴近真实水库场景,也能顺便检验TIM输入捕获的编程能力。我建议采用超声波为主、ADC电位器模拟水位传感器为辅的双通道设计——两个信号同时超阈值时预警,可以避免单一传感器漂移造成的误报。
温度信号在这个系统里不是直接参与预警,而是用来补偿超声波声速。超声波在空气中的传播速度随温度变化,标准声速343m/s对应20℃,每升高1℃声速增加约0.6m/s。Proteus仿真的虚拟环境里温度是固定值,但代码里仍然要保留温度补偿的算法框架,否则实物移植时距离误差会超过应用要求。
2.2 多级预警逻辑:阈值怎么定,状态机怎么写
阈值设计是整个系统最需要提前想清楚的部分,因为Proteus仿真里把阈值改来改去很容易,但实物阶段改阈值就要重新标定传感器。常见做法是设三级预警:正常、关注、警戒、紧急。我这里用四级状态,便于演示状态机的完整迁移。
水位百分比通过ADC采样值换算:STM32 ADC是12位,满量程4096,水位百分比等于当前值除以4096。三级阈值分别设定为60%、75%、90%。实际项目中这些阈值来自水库库容曲线和防汛预案,仿真阶段用百分比代替米数,方便在电位器上直接旋出不同水位场景。
状态迁移要处理回差值(hysteresis),否则水位在阈值附近抖动时,预警级别会在两个状态间反复跳变,蜂鸣器和LED会被触发得像是坏了。处理方法是:进入高一级预警需要超过阈值,退出高一级预警则需要低于阈值减去回差量。回差取3%-5%的效果在虚拟环境里表现比较稳定。这个细节很多初学者容易忽略,Proteus里电位器本身噪声不大,所以不明显,但实物上一有干扰就露馅。
2.3 Keil与Proteus的工程分工:一个项目两个窗口
整套方案涉及两个软件工具,各自职责要分清。Keil负责STM32的代码编写、编译和生成HEX文件;Proteus负责电路仿真、加载HEX文件、观察虚拟信号。联调时最省事的流程是:在Keil里改代码、编译出HEX,然后在Proteus里重新加载一次HEX,点运行。不必每次都在Proteus里重新绘制电路或调整元件参数。
工程文件的组织上,我习惯把代码按功能拆成五个文件:main.c放主循环和调度逻辑,bsp_adc.c放水位和温度采集,bsp_timer.c放超声波回波捕获,bsp_uart.c放调试打印,bsp_lcd.c放显示。Proteus的仿真模型不关心你的代码文件组织,但模块化能让你在排查问题时快速定位到具体函数,而不是在一个几百行的main.c里翻。仿真项目文件则单独建一个文件夹,用到的LCD1602、HC-SR04、虚拟终端等元件的型号和参数都记录到一个readme里,防止换台电脑重新仿真时元件库对不上。
3. 用Proteus搭出水库预警电路:从元件库到引脚对照
3.1 元件清单与STM32F103C6的最小系统接线
Proteus元件库对照表里,STM32系列在8.x以上版本才内置,早期版本需要单独安装芯片包。我推荐使用STM32F103C6,它足够跑这个系统,而且Proteus对它的仿真模型比较成熟。元件清单如下:
| 元件 | Proteus关键字 | 数量 | 用途 |
|---|---|---|---|
| STM32F103C6 | STM32F103C6 | 1 | 主控 |
| HC-SR04 | HC-SR04 | 1 | 超声波测距 |
| LCD1602 | LM016L 或 LCD1602 | 1 | 显示水位与预警状态 |
| 电位器 | POT | 2 | 模拟水位/雨量电压输出 |
| 蜂鸣器 | BUZZER | 1 | 声音报警 |
| 发光二极管 | LED | 3 | 分级报警指示 |
| 晶振 | CRYSTAL | 1 | 8MHz外部晶振 |
| 电容/电阻 | CAP/ RES | 若干 | 复位电路与上拉电阻 |
最小系统接线是最容易被忽略但最容易出问题的环节。STM32F103C6的VDDA必须接3.3V,VSSA接地,否则ADC模块不工作。NRST引脚接一个10kΩ上拉电阻到3.3V,再并一个0.1μF电容到地,复位电路要低电平有效。BOOT0和BOOT1都接地,确保从主Flash启动。PD1和PD0(OSC_IN/OSC_OUT)之间接8MHz晶振,两个引脚各接一个20pF负载电容到地。Proteus里晶振参数设置比较直观,双击元件填入8MHz即可。
3.2 HC-SR04超声波测距模块的仿真接入
HC-SR04模块在Proteus里是现成模型,有四个引脚:VCC、GND、TRIG、ECHO。TRIG接到STM32的PA0(通用输出),ECHO接到PA1(定时器输入捕获通道)。这里有个关键点:Proteus里的HC-SR04默认供电是5V,而STM32的GPIO容忍3.3V,仿真时虽然不会烧毁模型,但如果你后面要做实物,必须加电阻分压或电平转换芯片,否则ECHO输出的5V高电平可能损坏STM32引脚。仿真阶段直接用连线连接,问题不大,但我在代码注释里会专门标注这一点,提醒实物移植时处理。
TRIG引脚的触发时序是:拉高至少10μs,然后拉低,模块会发出8个40kHz脉冲并拉起ECHO引脚。ECHO高电平持续的时间与障碍物距离成正比。在Proteus仿真里,这个模块是纯逻辑模型,不依赖真实超声回波,但时序判断和代码完全一致。距离计算公式是:距离(cm)= ECHO高电平时间(μs)× 0.017。需要注意,Proteus的仿真速度会影响这个时间值的精度,后面避坑章节再展开。
3.3 用电位器和ADC模拟水位传感器:通道配置与采样参数
水位传感器在Proteus里没有标准模型,常见做法是用电位器的分压输出模拟液位变送器的0-3.3V输出。电位器RV1的中置引脚接STM32的PA4(ADC1_IN4),电位器两端分别接3.3V和GND。旋动电位器,PA4上的电压在0到3.3V之间变化,对应水位0%到100%。同理,RV2接PA5(ADC1_IN5)模拟温度传感器或雨量传感器的电压输出。
ADC采样的参数设置有一个容易翻车的地方:STM32的ADC引脚对应关系容易记混。PA0是ADC1_IN0,PA1是ADC1_IN1,PA4是ADC1_IN4,PA5是ADC1_IN5。如果你把电位器接到了PA4,却在代码里配置通道ADC_CHANNEL_4,对应关系没错;但如果代码里写的是ADC_CHANNEL_0,读出来的值就恒为0。连线时就要在原理图上标注好通道号,代码与原理图对照检查后再写配置。
采样时序上,我给每个通道设置了一个稳定延时,在切换ADC通道之后等待约50μs,再启动转换。这是因为Proteus仿真模型中的采样保持电容有一个建立时间,切换通道后立刻采样会读到上一个通道的残留电压。实际项目中,ADC的采样时间寄存器(SMPR)也可以安排得更长,比如239.5周期,配合这个延时能稳一些。
3.4 LCD1602与虚拟终端的显示链路
LCD1602在Proteus里常用LM016L模型替代。接线采用4位数据模式,占用引脚少,但时序上比8位模式更敏感,初学者容易在时序上踩坑。4位模式接线:DB4-DB7接PB0-PB3,RS接PB10,RW接PB11,E接PB12。RW引脚在只写模式下直接接地,省一个引脚同时避免误读操作。VLCD引脚接一个10kΩ电位器到地,用于调节对比度,仿真时如果不接这个电位器,LCD可能显示不出字符。
虚拟终端是Proteus调试利器。UART1的TX(PA9)接虚拟终端的RXD,UART1的RX(PA10)接虚拟终端的TXD。仿真运行后,虚拟终端窗口会显示STM32通过USART1发出的所有调试信息。我习惯在预警状态每次切换时打印一行日志,包含当前水位百分比、预警级别和距离值,这样不需要盯着LCD屏幕也能回溯整个仿真过程。
4. 把预警逻辑写进STM32:滤波、捕获、状态机三件套
4.1 ADC多通道采集的水位滤波与切换延时
代码从ADC初始化开始。ADC1开启两个通道,规则通道序列长度设置为2,分别对应水位和温度模拟量。使用规则组连续转换模式,转换结果通过DMA搬运,减轻CPU负担。Proteus对DMA模式支持正常,但在DMA配置错误时,仿真可能表现为ADC值全部为零。如果采用轮询方式读取ADC值,务必在每次读取前启动转换并等待EOC标志,这个流程在代码里体现了:
#define ADC_WATER_CH ADC_Channel_4 // PA4,水位电位器 #define ADC_TEMP_CH ADC_Channel_5 // PA5,温度电位器 #define SAMPLE_TIMES 10 // 滑动平均次数 uint16_t water_raw = 0; uint16_t temp_raw = 0; uint16_t adc_read_channel(uint8_t ch) { ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1); } void adc_sample(void) { uint32_t water_sum = 0, temp_sum = 0; for (int i = 0; i < SAMPLE_TIMES; i++) { water_sum += adc_read_channel(ADC_WATER_CH); delay_us(50); // 通道切换后稳定延时 temp_sum += adc_read_channel(ADC_TEMP_CH); delay_us(50); } water_raw = water_sum / SAMPLE_TIMES; temp_raw = temp_sum / SAMPLE_TIMES; }代码里的delay_us(50)就是前面提到的通道稳定延时。我在Proteus仿真中发现,把延时去掉后,ADC读数会在某些电位器位置出现跳变,尤其在两通道交替采样时更明显。滑动平均次数取10次,对应一个约1ms的采样周期,对水库水位这种慢变量绰绰有余。如果后续接的是流量传感器,可能需要提高采样率并减小平均窗口,避免把真实波动也平均掉。
4.2 TIM2输入捕获测回波:定标器参数与距离换算
超声波回波测量在Proteus里最容易出错的不是逻辑,而是时基。STM32F103C6在Proteus里默认外部8MHz晶振,经过PLL倍频到72MHz系统主频。TIM2挂在APB1总线上,APB1时钟是36MHz,但定时器时钟自动倍频到72MHz。如果你在Keil里配置的时钟不对,系统主频不是72MHz,那么定时器计数的实际频率与理论值不符,距离换算必然出错。
TIM2配置为输入捕获模式,通道2捕获ECHO上升沿,通道1捕获下降沿。实际测回波宽度时,常用PWM输入模式,一个通道同时测量周期和占空比,但水库预警只需要单次回波宽度,我用最直接的方式:定时器从ECHO上升沿开始计数,下降沿触发捕获中断,读取计数差值。代码如下:
#define ECHO_PIN_PORT GPIOA #define ECHO_PIN GPIO_Pin_1 volatile uint32_t echo_tick = 0; volatile uint8_t echo_ready = 0; void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_CC2)) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); if (GPIO_ReadInputDataBit(ECHO_PIN_PORT, ECHO_PIN) == SET) { // 上升沿:清计数并开始计时 TIM_SetCounter(TIM2, 0); } else { // 下降沿:读取计数并标记完成 echo_tick = TIM_GetCapture2(TIM2); echo_ready = 1; } } }这段代码用GPIO电平判断捕获到的是上升沿还是下降沿,比配置两个捕获通道要简单。TIM2的预分频器设置决定计数的时基单位:设定PSC为7200-1,计数频率变为72MHz/7200=10kHz,每个计数代表0.1ms,也就是100μs。这个精度足够测厘米级距离,如果测更近的物体,可以减小分频让计数分辨率更高。回波宽度换算距离时,乘以声速再除以2,公式在注释里写清楚。
4.3 预警状态机代码与蜂鸣器驱动
预警状态机用一个枚举变量表示当前级别。每次主循环先采样水位,再计算水位百分比,然后根据阈值和回差值决定状态迁移。蜂鸣器驱动采用无源蜂鸣器,需要PWM或方波驱动才能发声,直接用GPIO拉高只会让蜂鸣器发出一个咔嗒声。Proteus里的BUZZER模型对直流电平响应不明显,所以代码里蜂鸣器控制采用定时翻转的方式,频率在1kHz左右。
typedef enum { LVL_NORMAL = 0, LVL_ATTENTION, LVL_WARNING, LVL_EMERGENCY } warn_level_t; warn_level_t level = LVL_NORMAL; uint8_t water_percent(void) { return (uint8_t)((water_raw * 100UL) / 4095); } void warn_update(void) { uint8_t pct = water_percent(); switch (level) { case LVL_NORMAL: if (pct >= 60) level = LVL_ATTENTION; break; case LVL_ATTENTION: if (pct >= 75) level = LVL_WARNING; else if (pct < 57) level = LVL_NORMAL; // 回差3% break; case LVL_WARNING: if (pct >= 90) level = LVL_EMERGENCY; else if (pct < 71) level = LVL_ATTENTION; // 回差4% break; case LVL_EMERGENCY: if (pct < 86) level = LVL_WARNING; // 回差4% break; } }阈值60、75、90换算成百分比,比较直观。回差值的设置在代码里体现为退出阈值低于进入阈值,避免临界抖动。蜂鸣器驱动单独放一个函数,根据当前预警级别产生不同频率和节奏。正常状态不响;关注状态响0.5秒停1秒;警告状态响0.2秒停0.2秒;紧急状态连续响。LED方面,黄色LED在关注级别点亮,红色LED在警告和紧急级别点亮,紧急级别让红色LED闪烁,通过主循环内的计数变量实现。
4.4 生成HEX并加载到Proteus:Keil配置与Proteus时钟对齐
Keil侧生成HEX文件的设置如下。点击魔法棒图标进入Options,在Output标签页勾选Create HEX File。之后每次编译,工程目录下会生成对应的.hex文件。在Debug标签页选择Use Simulator,不需要选择ST-Link或J-Link,因为仿真运行时由Proteus直接加载HEX。另一个关键点是Target标签页里的晶振频率。这里必须填写8.0MHz,如果你填了其它值,代码里用SystemInit函数配置PLL后主频仍然是72MHz,但Proteus模型里外设时钟的模拟基准会混乱。
Proteus侧加载HEX的步骤:双击STM32F103C6芯片,在弹出的属性对话框中找到Program File项,点击文件夹图标浏览到刚才生成的HEX文件。同时确认CKS这一项(时钟频率)填入8000000,对应8MHz外部晶振。如果这里不填或填错,芯片运行后定时器、串口的时序全部对不上。加载完成后直接点运行按钮。Proteus会先完成编译模型初始化,然后芯片开始执行Flash中的程序。
Proteus运行时如果按下单步调试按钮,你会发现系统没有按C语言源代码单步执行,而是按汇编指令步进。这是因为Proteus的ARM仿真默认加载HEX文件后只提供汇编级调试。要在Proteus里实现C语言源码级调试,需要配置Keil的Debug选项为Proteus VSM Simulator,并安装Proteus VSM Agent驱动。不过对于水库预警这个项目,我一般不加源码级联调,通过虚拟终端和LCD观察输出已经足够;加一层联调反而让操作复杂度上升,故障概率变大。
5. 避坑:5个高频事故与排查顺序
5.1 现象到解决(一):芯片通电了但GPIO没反应
现象:Proteus仿真开始后,STM32芯片上电,但连接LED的引脚输出恒为低电平,程序像是没跑。甚至把引脚配置为推挽输出并直接拉高,虚拟示波器观察仍然是0V。
原因:最常见的是时钟没跑。STM32F103C6上电后默认使用内部HSI时钟,主频8MHz,如果你在代码里使用了SystemInit配置外部晶振,但Proteus模型里没有接外部晶振或CKS参数没填,芯片会一直等待HSE就绪,卡在启动流程里出不来。另一个原因是BOOT引脚配置错误,BOOT0和BOOT1都悬空时,Proteus模型可能进入系统存储器启动模式,程序根本没从Flash开始执行。
解决:先检查外部晶振是否连接在PD0和PD1上。然后双击芯片,确认Program File里加载了正确的HEX路径,CKS填8000000。最后把BOOT0和BOOT1都通过下拉电阻接地。按这个顺序排查,90%的“程序没跑”问题都能解决。如果还不行,就在主函数第一行加一个GPIO翻转作为最小测试程序,单独验证芯片运行环境。
5.2 现象到解决(二):LCD1602花屏、乱码
现象:LCD1602在Proteus里显示一团方块,或者第一行正常第二行全黑,有时字符出现但位置错乱。
原因:LCD初始化时序太紧凑。真实LCD1602控制器要求上电后至少有40ms以上的等待时间,Proteus模型对初始化时序不如真实硬件宽容,如果初始化代码只延时了几毫秒就发命令,模型内部状态没准备好,后续显示就乱了。另一个原因是4位模式下的高4位和低4位接线顺序反了,DB4-DB7接到PB0-PB3时,如果原理图上把DB4接到了PB1,代码初始化就会乱套。
解决:初始化函数里加大延时。上电后延时50ms,然后按8位模式复位时序操作三次,再切换到4位模式。这个标准流程在Proteus里不要简化。同时回头核对原理图引脚编号,我在实物项目里吃过一次亏:代码里操作的是PB0-PB3,原理图里却接到了PB4-PB7,一对比才发现是连接线标号错了。仿真环境没有“烧坏元件”的代价,反倒容易忽略这类低级问题。
5.3 现象到解决(三):超声波回波时间全为0
现象:HC-SR04模块的ECHO引脚始终低电平,或者回波时间稳定但距离值明显偏大。
原因:TRIG触发脉冲宽度不够。HC-SR04的启动条件要求TRIG高电平持续至少10μs,如果代码里用delay_us实现,但delay_us函数本身依赖SysTick,而SysTick配置错误导致延时时间远小于理论值,模块没有收到有效触发。另外Proteus的Simulation Accuracy如果设置为Low或Medium,仿真时间步长过大,10μs的小脉冲在仿真时间轴上可能被直接跳过去。
解决:把TRIG拉高后延时改为精确系统延时,建议使用SysTick或直接操作定时器延时。同时在Proteus菜单中选择System,将Simulation Accuracy设为High,让仿真时间步长更小。回波时间全为0还有一个冷门原因:HC-SR04的触发引脚默认方向是输入,代码里忘了配置GPIO方向为推挽输出,导致TRIG引脚电平始终被外部下拉。初始化代码检查一遍就能发现。
5.4 现象到解决(四):虚拟终端乱码
现象:虚拟终端窗口显示的内容是乱码,或者字符缺一半,偶尔还出现一个字符重复两次。
原因:波特率不匹配。STM32代码里配置USART1波特率9600,但虚拟终端设置的是4800或115200,两边对不上,数据帧错位。Proteus虚拟终端的默认波特率是9600,双击元件打开属性框可以看到这个值。另一个原因是时钟配置错误导致波特率计算器分频结果和预期不一致,比如实际主频是36MHz,但代码按72MHz计算分频器,实际波特率与理论值差一倍。
解决:先把虚拟终端波特率改成与代码一致。修改代码后重新编译,不要只改一边。如果两边都是9600仍然乱码,检查代码里的时钟初始化是否把系统主频配成了36MHz而不是72MHz,用串口打印一个固定字符(如字母U)来测试,0x55的二进制是01010101,能够较好暴露波特率偏差。实物项目里乱码大多数是分频器整数舍入误差,但在Proteus里这个坑基本都是时钟配置引起的。
5.5 现象到解决(五):ADC值只在0或4095两端跳
现象:旋转电位器,ADC读数要么是0,要么是4095,中间值完全不存在,像是一个比较器而不是ADC。
原因:ADC通道配置错误。最常见的场景是代码里配置了通道0,但电位器实际接在通道4。当读取的通道悬空或未连接时,Proteus模型可能返回0或满量程。另一种可能是ADC的供电引脚没接好。VDDA必须接3.3V,VREF+引脚在F103C6封装里内部连接到VDDA,如果VDDA悬浮,ADC参考电压不稳定,读数会极端跳变。
解决:对照原理图把每个ADC通道的引脚编号全部列出来,再检查代码里的通道配置宏。在Proteus里可以用电压表表笔直接点电位器中间引脚,看电压是不是真的随旋钮变化,排除原理图接线问题。还有一点:ADC_SampleTime如果设置太短,比如1.5周期,Proteus模型可能来不及完成电荷重分配。我把采样时间放在239.5周期,ADC读数的线性度有明显改善,尤其在分压接近满量程时不再频繁跳满。
6. 进阶验证:把虚拟终端和示波器变成你的调试仪表
6.1 用重定向printf打印预警日志
虚拟终端接收到的十六进制字节不直观,如果能在代码里直接用printf打印格式化字符串,调试效率会提升很多。STM32的C库提供了fputc函数,重写它把字符发送到USART1即可:
int fputc(int ch, FILE *f) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, (uint8_t)ch); return ch; }之后在代码里使用printf("Warn level:%d water:%d%% dist:%dcm\r\n", level, pct, dist_cm)。虚拟终端窗口会按行输出,方便回溯整个仿真过程中水位变化和预警级别切换的关系。我习惯在每次状态迁移时加一条日志,标明发生迁移的时间点和当前水位,这样跑完一轮仿真,就能对照时间戳检查阈值回差是否正常。
6.2 双击LED看闪烁波形:示波器验证蜂鸣器周期
Proteus里的示波器不需要单独拖出来,直接双击LED和蜂鸣器元件就能打开波形窗口。这个方法知道的人不少,但能把波形和代码逻辑对应起来的人不多。紧急级别下红色LED闪烁和蜂鸣器连续声响,双击LED会看到一个方波,方波周期等于你代码里设定的闪烁周期。蜂鸣器因为驱动频率在1kHz左右,波形会显示为较密的方波。
我常用的验证技巧:把蜂鸣器引脚接到示波器A通道,把一个LED引脚接到B通道,同时观察两个波形。当水位从80%调到95%,应该看到LED方波频率不变但蜂鸣器输出从间歇变为连续。这一步不仅验证逻辑,还能直观感受仿真和实物的区别——虚拟波形没有毛刺,实物波形在继电器动作时会有明显干扰,所以仿真通过不等于实物省心。
6.3 最后跑一遍完整预案验证流程
仿真收尾前,按固定流程跑一遍完整预案:电位器从0%开始,每5秒调一次,先后经过正常、关注、警告、紧急四个状态,再反向调回。全程观察LCD显示、LED指示、蜂鸣器节奏和虚拟终端日志,记录每个状态切换点的水位百分比如下。正常到关注:应在60%到63%之间;关注到警告:应在75%到78%之间;警告到紧急:应在90%到93%之间;反向过程观察回差值是否在3%-5%之间。这套验证做完,整个系统的逻辑闭环就确认了。
最后说一个我的血泪经验:Proteus仿真里跑不通的问题,90%出在时钟配置,不是代码逻辑。每次新建工程我第一件事就是点亮一个LED并配置一个定时器中断,确认时钟正常后才开始写业务代码。这个习惯救过我很多次,因为当你把水位逻辑和超声波特测都写完后再排查时钟问题,你都不知道该怀疑谁。希望帮到你。
本文还有配套的精品资源,点击获取