51单片机+BMP180气压温度报警系统设计与仿真实现 📅 发布时间:2026/9/12 14:40:59 👁 浏览次数: 简介一套基于51单片机的气压温度检测报警项目适合电子类课程设计、毕业设计以及传感器应用初学者可解决气压与温度采集、液晶显示、上下限报警设定等常见问题。资源共35个文件压缩包约975KB包含Proteus仿真工程、Keil源程序、原理图、流程图、元件清单及PDF预览、编译中间文件等类型目录结构清晰便于按模块查阅。目前已有159人学习浏览。通过源码可理解I2C读取BMP180压力与温度数据、LCD1602显示驱动、按键调参和阈值比较报警的具体实现利用仿真图可直接运行观察效果原理图和物料清单则能指导硬件连接与元器件采购。流程图还展示了主程序与报警处理流程便于理清整体逻辑元件清单则列明所需器件规格适合对照搭建实物。整体方案完整可作为胎压监测、环境气压温度检测等实训项目的参考范例帮助读者快速完成从程序编写到仿真验证的学习闭环。1. 51单片机与BMP180的组合为什么适合做气压温度报警原型课程设计或快速原型里“51单片机BMP180上下限报警”是最不容易跑偏的组合之一。BMP180是数字气压和温度传感器输出走I2C总线不需要ADC、不需要运放51用两个普通IO口模拟I2C就能把数据读回来。报警部分更简单一组阈值比较加一个蜂鸣器就形成闭环。真正卡住人的地方通常在两个一个是BMP180内部校准系数和补偿公式没有处理好另一个是Proteus仿真里BMP180模型和实物行为不一致。这篇按交付顺序把原理图、流程图、物料清单、仿真图、源代码的落地方式写清楚以STC89C52为主控所有代码按Keil C51编写习惯给出。2. 先把系统框图、物料清单和引脚分配定下来原理图前的5项硬决策有些项目画到一半发现I2C引脚和按键抢占同一个IO口或者1602液晶的P0口没有加上拉电阻导致花屏。这些都属于画原理图之前没有做硬决策。这里把系统组成、BOM和引脚分配先定下来后面做原理图和仿真图才不会返工。2.1 系统组成与信号流向传感器到报警器的四段链路整个系统可以拆成四段链路传感器采集、主控运算、显示交互、报警执行。BMP180挂在I2C总线上作为从机51作为主机负责启动转换和读取校准数据读到的原始温度值和气压值经过补偿计算后送到1602液晶和串口上下限报警由阈值比较得出超出范围时拉低蜂鸣器驱动IO口。------------------ I2C ------------------ | 按键/模式切换 |-- | BMP180 | ------------------ | | 气压/温度传感器 | ------------------ | ----------------------- | 1602液晶显示 |----| STC89C52 最小系统 | ------------------ | ----------------------- ------------------ | | | 串口打印/虚拟终端 |-- -- 蜂鸣器/LED报警 ------------------ -- 阈值设置状态指示信号流向从右向左看更符合排查习惯先在BMP180侧确认能读到ACK再往主控侧确认换算值最后才看报警和显示。很多同学第一步就把BMP180和1602并行调试出问题时既可能是I2C时序又可能是LCD初始化定位难度翻倍。2.2 物料清单与引脚分配照着BOM表买件不再翻车物料清单直接按5V和3.3V两套电源域来列。BMP180裸片必须用3.3V供电如果买的是GY-68这类模块板上一般自带稳压和电平转换可以直接接5V供电。Proteus仿真模型不模拟这两种供电差异但原理图和实物必须区分清楚。序号物料名称规格/型号数量说明1主控MCUSTC89C52RC或AT89C52140脚DIPProteus里可选AT89C522晶振11.0592MHz1串口波特率计算方便3瓷片电容30pF2晶振负载电容4BMP180模块GY-681如果Proteus库缺模型用第三方模型51602液晶LCD160215V供电P0口接数据6无源蜂鸣器5V1加NPN三极管驱动7LED红/绿2报警指示和运行指示8按键轻触开关3模式切换、加、减9电阻10k、1k若干I2C上拉、LED限流、按键上拉10排阻10k 排阻1P0口上拉也可以用8个10k电阻引脚分配按Proteus仿真习惯来定I2C用P1口的P1.2和P1.3。这样做的理由是P1口在仿真和实物上都是准双向口不用额外设置引脚模式软件模拟I2C时方向切换更方便。引脚连接对象说明P1.2BMP180 SCLI2C时钟P1.3BMP180 SDAI2C数据P0.0-P0.71602 D0-D7必须通过排阻上拉到VCCP2.01602 RS寄存器选择P2.11602 RW读写选择通常接地P2.21602 E使能信号P1.4按键模式切换低电平有效P1.5按键加低电平有效P1.6按键减低电平有效P1.7蜂鸣器驱动三极管基极控制2.3 上下限报警的触发逻辑比较器思路而不是算法库上下限报警不需要PID不需要模糊控制本质是四个区间的“或”判断。把温度上限、温度下限、气压上限、气压下限定义成4个变量主循环里做一次比较只要任何一个越界就进入报警状态。#define TEMP_HIGH 300 // 温度上限单位0.1℃即30.0℃ #define TEMP_LOW 150 // 温度下限15.0℃ #define PRES_HIGH 102000 // 气压上限单位Pa即1020.0hPa #define PRES_LOW 95000 // 气压下限950.0hPa bit alarm 0; if ((temp TEMP_HIGH) || (temp TEMP_LOW) || (pres PRES_HIGH) || (pres PRES_LOW)) { alarm 1; BUZZER 0; // 蜂鸣器低电平触发 LED_ALARM 0; // 报警LED点亮 } else { alarm 0; BUZZER 1; LED_ALARM 1; }这里的单位约定很关键。温度变量temp由BMP180计算出来时单位是0.1℃所以300表示30.0℃不要直接和30比较。气压变量pres单位是Pa海平面标准大气压约101325Pa所以102000Pa对应1020.0hPa。理解这个单位约定后面改阈值时才不会出现“永远不报警”或者“一开机就报警”的问题。3. 读懂BMP180的I2C与时序再写驱动代码3.1 BMP180内部寄存器与一次测量的完整流程BMP180只有极少数几个寄存器需要直接操作核心是控制寄存器0xF4、数据寄存器0xF6到0xF8以及出厂校准系数寄存器0xAA到0xBF。上电后芯片把11个校准系数放在一组寄存器里必须先在程序里读出来之后每次温度、气压换算都要用到这些系数。一次测量的完整流程分两步。第一步读温度向0xF4写入0x2E等待4.5ms然后从0xF6和0xF7读16位无符号温度原始值UT。第二步读气压向0xF4写入0x34加上过采样设置等待时间根据过采样模式变化然后从0xF6、0xF7、0xF8读20位气压原始值UP。顺序不能颠倒先有温度补偿值才有准确气压。需要特别注意BMP180的7位I2C地址是0x77写操作发送0xEE读操作发送0xEF。有些资料把地址写成0x77实际在I2C发送时左移一位这是ACK丢失最常见的来源之一。3.2 用GPIO软模拟I2C51没有硬件I2C时的通用写法STC89C52内部不集成硬件I2C控制器标准做法是用两个IO口软件模拟。软件模拟I2C的难点不在速度而在于SDA在发送和接收之间要切换方向。下面这段代码是Keil C51可直接编译的底层层。#include reg52.h #include intrins.h sbit I2C_SCL P1^2; sbit I2C_SDA P1^3; #define I2C_DELAY() _nop_(); _nop_() void I2C_Start(void) { I2C_SDA 1; I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); I2C_SDA 0; I2C_DELAY(); I2C_SCL 0; } void I2C_Stop(void) { I2C_SDA 0; I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); I2C_SDA 1; I2C_DELAY(); } bit I2C_WriteByte(unsigned char dat) { unsigned char i; bit ack; for (i 0; i 8; i) { I2C_SDA (dat 0x80) ? 1 : 0; dat 1; I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); I2C_SCL 0; } I2C_SDA 1; I2C_DELAY(); I2C_SCL 1; I2C_DELAY(); ack I2C_SDA; I2C_SCL 0; return ack; } unsigned char I2C_ReadByte(bit ack) { unsigned char i, dat 0; for (i 0; i 8; i) { I2C_SCL 1; I2C_DELAY(); dat (dat 1) | I2C_SDA; I2C_SCL 0; I2C_DELAY(); } I2C_SDA ack ? 0 : 1; I2C_SCL 1; I2C_DELAY(); I2C_SCL 0; I2C_SDA 1; return dat; }逻辑说明I2C_Start在SCL高电平时拉低SDAI2C_Stop在SCL高电平时拉高SDA这是I2C协议定义起始和停止的唯一判定条件。I2C_WriteByte在SCL低电平时改变SDA信号SCL高电平时保持SDA不变这样从机才能稳定采样。返回的ack是第9个时钟周期读到的应答位0表示从机收到1表示从机没有应答。参数说明I2C_DELAY用_nop_实现在11.0592MHz下每个_nop_约0.09us。如果后续接的长线干扰大可以加长延时但不要超过10us否则BMP180内部状态机可能认为总线空闲。对于标准模式100kHz时钟确保SCL高电平和低电平的延时各不少于2.5us上面两个_nop_偏短实际使用时建议改成4个_nop_。3.3 气压、温度与海拔的换算不要跳过补偿参数BMP180出厂时每个芯片的校准系数都不同不能直接用原始值当作气压必须用数据手册里的补偿公式。下面代码实现的是读取校准系数、计算温度原始值、计算气压原始值的完整函数。#define BMP180_ADDR_W 0xEE #define BMP180_ADDR_R 0xEF int cal[11]; // AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD void BMP180_ReadCalibration(void) { cal[0] (int)BMP180_ReadUShort(0xAA); cal[1] (int)BMP180_ReadUShort(0xAC); cal[2] (int)BMP180_ReadUShort(0xAE); cal[3] (int)BMP180_ReadUShort(0xB0); cal[4] (int)BMP180_ReadUShort(0xB2); cal[5] (int)BMP180_ReadUShort(0xB4); cal[6] (int)BMP180_ReadUShort(0xB6); cal[7] (int)BMP180_ReadUShort(0xB8); cal[8] (int)BMP180_ReadUShort(0xBA); cal[9] (int)BMP180_ReadUShort(0xBC); cal[10] (int)BMP180_ReadUShort(0xBE); } unsigned int BMP180_ReadRawTemperature(void) { BMP180_WriteReg(0xF4, 0x2E); DelayMs(5); return BMP180_ReadUShort(0xF6); } unsigned long BMP180_ReadRawPressure(unsigned char oss) { unsigned long up; BMP180_WriteReg(0xF4, 0x34 (oss 6)); DelayMs(2 (3 oss)); // oss0时约5ms up ((unsigned long)BMP180_ReadByteReg(0xF6) 16) | ((unsigned long)BMP180_ReadByteReg(0xF7) 8) | BMP180_ReadByteReg(0xF8); return up (8 - oss); }逻辑说明BMP180_ReadRawTemperature返回的是16位UTBMP180_ReadRawPressure返回的是右移后的UP。过采样设置oss范围是0到30表示超低功耗转换最快3表示超高分辨率转换时间最长。延时用2加3左移oss表示oss0时约5msoss3时约26ms和实际芯片指标接近。参数说明oss的值会直接进入控制寄存器0xF4的高两位同时决定后面气压计算中B3和B7结果的位数。超高分辨率模式下UP有效位数更多计算出的气压跳动更小但51主循环的单次刷新周期会变长。课程设计建议选oss0或1先把闭环跑通再去优化分辨率。4. 源代码落地主循环、上下限阈值与显示输出4.1 主循环与状态机读取、换算、比较、输出的节奏主循环采用“轮询节拍”结构。每次循环先读温度和气压原始值再做补偿计算然后判断阈值最后刷新显示和串口。整个周期受BMP180转换时间限制约在20ms到60ms之间对于室内气压监测已经足够。long temp, pres; long b5; void main(void) { unsigned long raw; unsigned char oss 1; UART_Init(); LCD_Init(); BMP180_ReadCalibration(); while (1) { raw BMP180_ReadRawTemperature(); temp BMP180_CalcTemperature(raw, b5); raw BMP180_ReadRawPressure(oss); pres BMP180_CalcPressure(raw, oss, b5); AlarmJudge(temp, pres); LCD_ShowValue(temp, pres); printf(T%ld.%ld C P%ld.%ld hPa\r\n, temp / 10, temp % 10, pres / 100, pres % 100); DelayMs(50); } }逻辑说明b5是温度补偿计算的中间量必须从温度计算函数里带出来因为气压计算还要用b5。如果把b5声明成局部变量气压补偿就会算出错误结果。printf输出时temp单位是0.1℃所以temp/10得到整数位temp%10得到小数位pres单位是Papres/100得到hPapres%100得到小数点后的两位。参数说明DelayMs(50)决定屏幕刷新和串口打印频率。如果使用oss3单次气压转换要26ms再加上50ms延时刷新周期接近80ms数字变化看起来会卡顿。可以把延时改成20ms但不要改成0否则51主循环会一直占用CPU按键消抖和LCD写入都会被拖慢。4.2 阈值按键与EEPROM临时改阈值的几种做法初始阈值可以用宏定义但产品化或者课程设计演示时评审老师通常要求能现场改上下限。最简单的方法是把阈值从宏改成全局变量再用三个按键分别做模式切换、加、减。long tempH 300, tempL 150; long presH 102000, presL 95000; unsigned char mode 0; void KeyScan(void) { if (KEY_MODE 0) { DelayMs(10); if (KEY_MODE 0) { while (KEY_MODE 0); mode; if (mode 4) mode 0; } } if (KEY_UP 0) { DelayMs(10); if (KEY_UP 0) { while (KEY_UP 0); switch (mode) { case 1: tempH 5; break; case 2: tempL 5; break; case 3: presH 100; break; case 4: presL 100; break; } } } }逻辑说明mode等于0时是正常运行模式不调整阈值mode等于1到4时分别表示正在调整温度上限、温度下限、气压上限、气压下限。按一次模式下按键mode加1超过4回到0。加按键根据当前mode只修改对应阈值。参数说明tempH每次加5对应0.5℃presH每次加100对应1hPa。这两个步进值可以改成1或10但步进太小会按很多次才看到效果。这段代码没有做范围限制实际使用时应该加边界判断例如温度上限不能超过600即60℃气压下限不能高于气压上限。修改阈值后掉电会丢失如果要求保存需要外接EEPROM或者用STC内部EEPROM一般课程设计到变量级别就足够。4.3 串口与1602输出先验证传感器再验证报警在接1602之前强烈建议先用串口输出原始值和换算值把传感器数据确认正确后再接显示和报警。Proteus里放一个Virtual Terminal代码里重写putchar就可以用printf直接打印。char putchar(char c) { SBUF c; while (TI 0); TI 0; return c; } void UART_Init(void) { SCON 0x50; TMOD 0x0F; TMOD | 0x20; TH1 0xFD; TL1 0xFD; TR1 1; }逻辑说明Keil C51的printf最终会调用putchar函数重写putchar后printf的工作量就落在串口发送上。UART_Init把定时器1配置成波特率发生器模式2TH1和TL1都设为0xFD配合11.0592MHz晶振得到9600波特率。参数说明如果串口打印乱码先检查晶振是不是11.0592MHz再看TH1值是否匹配波特率。Proteus仿真里串口收到乱码多半是Virtual Terminal的波特率和代码里的9600不一致。1602显示部分优先级低于串口因为1602花屏只会影响读数展示而串口数据能直接验证BMP180换算是否接近真实大气压。5. Proteus仿真落地原理图、仿真图与BMP180模型排错5.1 原理图绘制与BMP180模型加载Proteus 8 Professional的元件搜索栏输入BMP180一般可以直接找到Bosch的仿真模型。放置后模型通常保留SCL、SDA两个I2C引脚再加VCC和GND。找不到模型时不要用普通电阻电容硬拼那是模拟不了I2C时序的正确做法是加载第三方BMP180模型库或者用I2C调试器配合逻辑分析来验证主机代码。原理图绘制时51单片机选AT89C52或AT89C51都可以电源接5VP0口必须接10k排阻到VCC。BMP180模型的VCC可以接到5V但实物模块如果带3.3V稳压VCC接5V没问题如果是裸片传感器必须接3.3V。I2C总线的SCL和SDA各接一个10k上拉电阻到VCC。连线顺序按照第2章的引脚分配表先接最小系统再接I2C然后接LCD最后接按键和蜂鸣器。每次接一部分都运行仿真确认比全部接完再查错快很多。5.2 仿真图怎么看虚拟终端、I2C调试器与流程图对应仿真运行后在Proteus里可以通过两个工具观察状态。第一个是Virtual Terminal接在51单片机的TXD和RXD上用来显示串口打印的温度气压值。第二个是I2C Debugger挂在SDA和SCL两条线上可以看到I2C总线上实际传输的从机地址、寄存器地址和数据内容。程序流程图建议按主循环的四个阶段画初始化、读取转换、阈值比较、输出显示。每个阶段对应一个状态框。Proteus仿真图则直接截取运行界面标注出液晶显示值、报警LED状态和虚拟终端输出。原理图、流程图、仿真图三个交付物要互相对应不要让流程图里的状态机和源码主循环对不上。仿真图中最容易忽略的是上电顺序。Proteus里运行仿真后BMP180模型需要时间完成内部初始化如果程序在main一开始就立刻读取校准数据可能读到全零。解决方法是上电后延时200ms再执行BMP180_ReadCalibration或者等用户按键后再开始显示。5.3 三个高频故障读数恒定、ACK丢失、显示花屏故障一读数恒定不变。常见原因是BMP180_ReadCalibration没有读到有效校准系数校准系数全零导致换算结果始终一样。排查方法是在初始化函数里把cal[4]和cal[5]通过串口打印出来如果AC5和AC6都是0说明I2C通信没有建立先查BMP180的VCC和GND。故障二ACK丢失。打开I2C Debugger观察从机地址字节是不是0xEE。如果Debugger显示主机发送的是0x77而不是0xEE说明地址左移错误。另一种可能是SDA和SCL接反两条线互换后再看ACK是否恢复。Proteus里SCL和SDA引脚颜色不同蓝色圆点代表低电平高电平状态下SDA和SCL都应该是红色。故障三1602花屏。P0口上拉排阻漏接是最常见原因。Proteus里P0口内部没有上拉接到1602数据线上如果不加外部上拉读数不稳定显示乱码。另外检查1602的RW引脚是否接地E引脚是否接对。花屏时先跑一个最简的“清屏点亮第一行”测试不要让BMP180的读取逻辑参与这样能快速分离显示和传感器两个环节。6. 上下限阈值校准的3个技巧用气压换海拔、窗口滞回和串口回读6.1 海拔换算决定阈值初值BMP180测的是绝对气压不是相对高度。海拔越高气压越低。把阈值设置成固定值时先估算所在位置海拔。近似公式是每升高8.5米气压下降约1hPa。如果所在城市海拔50米海平面气压按1013.25hPa算当地气压大约1007.4hPa。把气压上限设为当地气压加10hPa下限设为当地气压减10hPa比随手填950到1020更合理。要更精确地反推海拔可以用简化公式海拔等于44330乘以1减去气压除以101325的0.1903次方。51上不需要实现浮点幂运算用整数近似版本把气压值代入得到的高度用于修正阈值初始值。6.2 滞回比较避免报警抖动阈值附近如果只有1Pa的抖动蜂鸣器会反复响停。解决办法是设置报警触发阈值和报警解除阈值之间留出窗口。温度报警触发后至少要降到上限以下0.5℃才解除对应5个0.1℃单位气压报警触发后至少要回到限值以内50Pa才解除。if (alarm 0) { if (temp tempH || temp tempL || pres presH || pres presL) { alarm 1; } } else { if (temp tempH - 5 temp tempL 5 pres presH - 50 pres presL 50) { alarm 0; } }逻辑说明alarm为0时只要任意参数越界就进入报警alarm为1时所有参数都回到安全窗口才解除。这样即使温度在30.0℃附近波动也不会让蜂鸣器快速通断。6.3 用串口回读做一次现场校准硬件搭好后找一个本地气象站发布的当前海平面气压值和串口打印的气压值做对比。差值是固定的系统偏移把这个偏移加到代码的pres变量上或者直接调整presH和presL。温度也可以用标准温度计对比偏移量以0.1℃为单位修正。室内环境下气压变化范围很小验证传感器联动的一个有效方法是把BMP180放进干净塑料袋轻轻捏紧袋口观察气压值上升几十Pa蜂鸣器按照设定的上下限正确触发。这个动作能同时验证I2C读取、补偿计算、阈值判断和报警输出四条链路比只看串口数据更接近真实使用场景。最后留一个提醒BMP180的校准系数是从片内OTP存储器读出来的代码更换芯片后不需要改程序但Proteus仿真模型不一定模拟这个OTP读取过程。如果仿真中读数异常先检查校准系数是否读到非零值再检查补偿公式中的整数溢出。本文还有配套的精品资源点击获取