)
简介本资源是一套面向单片机初学者与毕业设计学生的温度电压双参数检测系统完整开发套件解决低温环境低至-50℃下高精度温压同步采集与本地可视化显示的实际工程需求适用于课程设计、电子竞赛及小型工业监控场景。压缩包共49个文件含11个说明类txt文档涵盖设计说明、使用指南、答辩技巧、4个PDF技术手册Keil工程说明、Proteus仿真操作等、3个HEX可执行文件、1个Proteus仿真源图.dsn、1个Keil工程.uvproj及配套C/A51源码、LCD12864与DS1621等关键器件资料包并附有Proteus8.10操作视频MP4与仿真图PDF总大小7.47MB。已有46人学习下载。读者可直接导入Keil与Proteus进行编译仿真快速验证I²C通信、12位AD采样、负温解析及12864图形显示全流程配套文档体系完整覆盖硬件选型依据、软件调试要点与答辩应答策略显著降低单片机数据采集类项目落地门槛。 温度电压双参数检测是51单片机课程设计里出场率最高的题目之一。这次分享的项目是个比较典型的组合51单片机做主控12864液晶做显示DS1621数字温度传感器负责测温支持零下MAX1241做12位电压采集外加Proteus仿真。整套东西做下来I2C、SPI、LCD驱动、AD转换这些嵌入式基本功都能练到非常适合课程设计、电子竞赛练手或者刚学完单片机想自己做个小系统的人参考。这个题目看上去元件不多但里面的门道其实不少。DS1621是I2C接口的数字温度传感器能测-55℃到125℃比常见的DS18B20在Proteus里更方便调负温度MAX1241是12位串行ADCSPI接口精度比ADC0809这类8位并行片子高一个档次12864液晶能同时显示汉字和数值界面比1602大气很多。这三个外设正好覆盖了两种最常见的串行总线做完这个项目以后任何I2C或SPI器件上手都会快很多。下面我把整个设计的思路、硬件电路、程序代码、仿真调试过程完整拆开讲踩过的坑和经验也一并写出来。1. 整体设计思路为什么是5112864DS1621MAX12411.1 这套组合解决了什么问题单片机课程设计通常有几个硬性要求要有传感器采集、要有显示、最好能仿真。这个题目一次全占了。温度采集属于环境量检测电压采集属于模拟量采集两个通道分别代表了数字传感器和模拟数字转换器两条技术路线老师看了会觉得你基础扎实自己也能通过对比明白数字量采集和模拟量采集的本质差异。从学习角度讲DS1621走I2C协议MAX1241走SPI协议这两种串行总线是嵌入式开发里使用频率最高的通信方式没有之一。很多学生毕了业进公司第一周看代码就是I2C和SPI。在学校里通过这个项目把两种协议的时序亲手调通比看十遍书都管用。从展示角度讲12864带中文字库可以直接显示“当前温度”“当前电压”这样的汉字提示再配合数字和单位整体仪表感很强答辩的时候效果比1602好不少。1.2 温度采集为什么选DS1621而不是DS18B20DS18B20在51单片机教程里太常用了几乎是标配。但做这个项目我反而推荐DS1621原因有三点第一Proteus仿真友好度。DS18B20在Proteus里虽然有模型但调节温度时需要手动修改元件参数有时候还要重新上电才能刷新体验比较别扭。DS1621在仿真里可以直接用滑动变阻器或者按键模拟温度变化负温度设置也方便调试效率高很多。第二I2C协议的价值。DS18B20用的是单总线协议虽然节省引脚但时序极其苛刻初学者经常因为延时不对导致读不到数据。DS1621是标准I2C协议和AT24C02、MPU6050、OLED这些器件是同一种总线学一次能复用一辈子。相比之下单总线协议除了DS18B20以外几乎没别的器件用学完就扔。第三负温度处理更直观。DS1621的温度寄存器是16位补码格式分辨率默认0.5℃读取后需要自己处理正负号和整数小数分离这个处理过程对理解计算机数据表示非常有帮助。标题里特别写了“可零下”说明负温度是这个项目的加分项DS1621能很自然地展示这个特性。当然DS18B20也有它的优点比如测温上限到125℃、单总线省引脚。如果你以后做的是温控器、热水器这类高温场景DS18B20更合适。但作为课程设计DS1621的综合收益更高。1.3 电压采集为什么用MAX1241而不是ADC0809很多课程设计选ADC0809因为它和51单片机的接口资料多、教材里都有。但ADC0809是8位并行ADC8个数据引脚直接占掉一组IO口如果还要接12864并行显示IO口就非常紧张。MAX1241是12位串行ADC数据通过3根线SCLK、DIN、DOUT读取不仅省IO精度也大幅提升。12位的分辨率是4096个等级如果参考电压2.5V每个LSB对应约0.6mV而8位ADC每个LSB约9.8mV差了16倍。用在电压检测这种精度敏感的场景12位的读数明显平滑稳定不会出现数值跳来跳去的情况。MAX1241在Proteus里的模型是标准的仿真时用滑动变阻器就能模拟电压输入调起来很顺手。1.4 显示部分12864液晶的选择和两种接线方式12864液晶分带字库和不带字库两种。带字库的是ST7920控制器可以直接显示汉字、英文字母和数字程序简单不带字库的是KS0108控制器需要自己做字模适合显示图形但操作麻烦。做课程设计建议选带字库的也就是ST7920后面代码部分我按ST7920写。12864的接口方式有两种并行和串行。并行方式就是RS、RW、E三根控制线加8根数据线共11根线串行方式只需要CS、SCLK、SID三根线加上电源也就5根。虽然串行省引脚但ST7920串行模式显示速度慢刷新的时候有肉眼可见的延迟。这个项目因为单片机52有32个IO口接完12864并行口和两个传感器后还有富余所以直接用并行方式显示速度快程序也直观。2. 硬件电路搭建接口细节与量程设计2.1 最小系统与引脚分配51单片机用AT89C51或者STC89C52都行Proteus里一般用AT89C51。晶振12MHz配合两个30pF电容构成晶振电路复位电路用经典的10μF电解电容加10k电阻。这部分是老生常谈不再赘述。关键是IO口分配建议画电路图前先规划好否则写程序的时候端口关系容易混乱。我用的分配如下功能模块引脚连接12864数据口P1.0-P1.7接12864 DB0-DB712864控制口P3.5、P3.6、P3.7接RS、RW、EDS1621P2.3、P2.4接SDA、SCLMAX1241P2.5、P2.6、P2.7接CS、SCLK、DOUT电源指示灯P0.0LED阳极经1k限流电阻接VCC这样分配后P2口正好被两个传感器瓜分P3口复用了串口功能也没关系这个项目不用串口。如果你想在实物上调试串口打印可以把12864的E脚换到P2.1把串口留出来。2.2 DS1621的接线与I2C上拉电阻DS1621是8脚芯片和AT24C02的引脚排列几乎一样。A0、A1、A2是地址选择引脚接地时I2C地址为0x90写/0x91读。SDA和SCL必须接上拉电阻到VCC典型值是4.7kΩ。这个电阻在Proteus里不接也能跑因为仿真模型总线上有默认上拉但实物上不接就完全无法通信习惯上还是要加上。DS1621的VDD接5VGND接地。还有一个T_OUT引脚是温度超限输出脚当温度超过TH寄存器设定的值时输出高电平这个引脚在基础项目中可以悬空扩展报警功能时再用。I2C总线上拉电阻的选值有个简单经验总线速度快选小一点例如2.2k速度慢选大一点例如10k常规5V系统用4.7k基本不会错。上拉电阻太大上升沿变缓通信距离长时容易出错上拉电阻太小灌电流太大可能损坏器件。2.3 MAX1241的接线与电压量程设计MAX1241的引脚中VIN是模拟电压输入REF是参考电压输入通常直接接2.5V基准源。如果做仿真直接用电源的2.5V即可如果做实物建议用TL431或者LM285做一个2.5V基准否则参考电压受电源波动影响测量值也会跟着漂。MAX1241的模拟输入范围是0到VREF也就是0-2.5V。但实际应用中我们经常要测0-5V的电压这时候需要做一个前端分压。最简单的办法是用两个10k电阻分压将0-5V映射到0-2.5V然后在软件里把读数乘以2还原。分压电阻的计算方式假设输入电压最大为5VMAX1241最大承受2.5V所以分压比K2.5/50.5。如果上电阻R110k接输入下电阻R210k接地中间抽头接VIN则VIN(R2/(R1R2))×VIN_IN0.5×VIN_IN。这样测量0-5V的电压分压后变为0-2.5V在ADC的线性范围内。注意分压电阻的精度直接影响测量精度普通5%精度电阻测出来会有些偏差。如果你手里有万用表最好实测一下两个电阻的实际阻值然后按实测值修正换算系数。2.4 12864液晶的接线与对比度调整ST7920控制器12864的引脚比较多VL是液晶对比度调节脚。实物上VL一般接一个10k电位器中间抽头接VL通过调节电压来改变对比度。在Proteus仿真里LM044L这个模型通常直接将VL接GND就能正常显示。如果屏幕上出现满屏黑点或者黑条多半是VL脚接错了。背光引脚A和K在仿真里可以不接实物上A接5V、K接GND但需要串一个限流电阻调整亮度一般20Ω到100Ω电流控制在20mA以内。PSB引脚是并串行模式选择高电平并行、低电平串行。这个脚很多人容易忘记接实物中直接接VCC选择并行模式不然液晶无法响应并口数据。2.5 电源与去耦电容系统统一5V供电。单片机、12864、DS1621都是5V器件直接共用一个5V电源没问题。MAX1241的VDD是5VREF是2.5V要注意模拟地和数字地尽量单点连接避免数字信号干扰模拟采集。每个芯片的电源引脚旁边建议加一个0.1μF去耦电容实物PCB上非常重要仿真里加不加都行。原因是芯片工作瞬间电流变化大加上去耦电容可以就近补充电流、滤除高频噪声防止芯片间互相干扰。这个习惯从仿真阶段就养成以后画PCB会省很多事。3. 软件程序实现从I2C到SPI的完整代码3.1 程序架构与工程文件组织代码在Keil C51里编写建议把工程拆成几个模块文件不要把代码全部堆在main.c里。我的做法如下main.c —— 主流程和全局变量delay.c / delay.h —— 延时函数i2c.c / i2c.h —— 模拟I2C底层时序ds1621.c / ds1621.h —— DS1621驱动max1241.c / max1241.h —— MAX1241驱动lcd12864.c / lcd12864.h —— 12864液晶驱动模块化好处很明显以后换一个I2C器件直接改ds1621.c就行i2c.c完全不用动。代码清晰答辩的时候老师问起来也好解释。3.2 I2C底层驱动与DS1621温度读取先用普通IO口模拟I2C时序而不是用51的硬件I2C51单片机大多也没有硬件I2C。I2C时序核心就是起始、停止、读写字节、应答判断。// i2c.c #include reg52.h #include intrins.h sbit SDA P2^3; sbit SCL P2^4; // 起始信号SCL高电平期间SDA产生下降沿 void I2C_Start(void) { SDA 1; SCL 1; _nop_(); _nop_(); SDA 0; _nop_(); _nop_(); SCL 0; } // 停止信号SCL高电平期间SDA产生上升沿 void I2C_Stop(void) { SDA 0; SCL 1; _nop_(); _nop_(); SDA 1; _nop_(); _nop_(); } // 发送一个字节返回从机应答位0有应答 unsigned char I2C_SendByte(unsigned char dat) { unsigned char i, ack; for(i 0; i 8; i) { SDA (dat 0x80) ? 1 : 0; dat 1; _nop_(); SCL 1; _nop_(); _nop_(); SCL 0; _nop_(); } SDA 1; // 主机释放总线 _nop_(); SCL 1; _nop_(); _nop_(); ack SDA; // 读取从机应答 SCL 0; _nop_(); return ack; } // 读取一个字节ack1回ACK表示继续读ack0回NACK表示读完 unsigned char I2C_RecvByte(unsigned char ack) { unsigned char i, dat 0; SDA 1; for(i 0; i 8; i) { dat 1; SCL 1; _nop_(); _nop_(); if(SDA) dat | 0x01; SCL 0; _nop_(); _nop_(); } SDA ack ? 0 : 1; // ack为1时拉低SDAACK为0时拉高NACK _nop_(); SCL 1; _nop_(); _nop_(); SCL 0; SDA 1; return dat; }DS1621的驱动代码要完成两件事初始化并启动温度转换然后读取16位温度值。DS1621的I2C地址是1001加A2A1A0A2A1A0都接地所以写地址0x90读地址0x91。// ds1621.c #define DS1621_WRITE 0x90 #define DS1621_READ 0x91 #define CMD_READ_TEMP 0xEE #define CMD_START 0xAC #define CMD_WRITE_CFG 0xA0 // 初始化DS1621配置为连续转换模式并启动转换 void DS1621_Init(void) { I2C_Start(); I2C_SendByte(DS1621_WRITE); // 发送写地址 I2C_SendByte(CMD_WRITE_CFG); // 写配置寄存器命令 I2C_SendByte(0x80); // 连续转换模式 I2C_Stop(); I2C_Start(); I2C_SendByte(DS1621_WRITE); I2C_SendByte(CMD_START); // 启动温度转换 I2C_Stop(); } // 读取温度返回值为实际温度的2倍单位0.5℃ // 例如返回51表示25.5℃返回-51表示-25.5℃ int DS1621_ReadTemp(void) { unsigned char th, tl; int temp; I2C_Start(); I2C_SendByte(DS1621_WRITE); I2C_SendByte(CMD_READ_TEMP); // 读温度命令 I2C_Stop(); I2C_Start(); I2C_SendByte(DS1621_READ); th I2C_RecvByte(1); // 读高字节还有下一字节所以回ACK tl I2C_RecvByte(0); // 读低字节最后一字节回NACK I2C_Stop(); temp ((int)th 8) | tl; if(temp 0x8000) // 负数判断 temp - 65536; return temp; }这里必须解释一下温度数据的补码处理。DS1621在负温度下温度寄存器以16位二进制补码形式存储。比如-25.5℃实际值是-25.5/0.5-5151的二进制是0x0033取反加1后是0xFFCD。我们把读到的th和tl拼成0xFFCD如果直接当成无符号数看是65485显然不对。所以要判断最高位bit15如果为1说明是负数需要减去65536得到-51这样再除以2就是-25.5℃。显示的时候把temp这个值除以2得到整数部分temp对2取余余数为0表示小数是.0余数为1表示小数是.5。这样不用浮点数也能显示0.5精度的温度。3.3 MAX1241的SPI采集与电压换算MAX1241在Proteus仿真里是个标准的SPI从设备单片机要模拟主机时序。它的工作流程是CS拉低启动转换然后SCLK给16个脉冲DOUT在SCLK下降沿依次输出12位数据。// max1241.c sbit AD_CS P2^5; sbit AD_SCLK P2^6; sbit AD_DOUT P2^7; // 读取12位ADC数据返回0-4095 unsigned int MAX1241_Read(void) { unsigned char i; unsigned int value 0; AD_CS 0; // 拉低CS启动转换 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); for(i 0; i 16; i) { AD_SCLK 1; _nop_(); AD_SCLK 0; _nop_(); value 1; if(AD_DOUT) value | 0x01; } AD_CS 1; return value 0x0FFF; // 12位有效数据 }注意这里为什么用16个时钟而不是12个。MAX1241的数据手册写的很清楚CS拉低后需要经过一段转换时间前4个SCLK脉冲期间DOUT输出无效数据或保持高阻从第5个SCLK开始依次输出12位结果。用16个时钟是为了凑够完整的数据周期读取结束后将低12位扣下来才是真实ADC值。如果你只发12个时钟前几个时钟打到转换间隙上就会丢数据或者整体错位。电压换算常见的写法是用浮点float voltage (float)ad_code * 2.5f / 4095.0f;C51的浮点运算会引入一个较大的库程序体积变大运行速度也会变慢。实际项目里更推荐用整数运算。比如我要显示0.00V到2.50V用0.01V为单位那么unsigned int volt100; volt100 (unsigned long)ad_code * 250 / 4095;ad_code是12位最大4095乘250后最大值约1023750需要用unsigned long防止溢出。这样算出的volt100范围是0-250表示0.00V到2.50V。如果前端加了2:1分压测0-5V就把250换成500即volt100 (unsigned long)ad_code * 500 / 4095;整数运算不仅快而且没有浮点库的内存开销51单片机这种资源紧张的环境下是很好的习惯。显示的时候buf[0] 0 volt100 / 100; // 整数位 buf[1] .; buf[2] 0 (volt100 / 10) % 10; // 十分位 buf[3] 0 volt100 % 10; // 百分位 buf[4] V; buf[5] \0;3.4 12864显示驱动与界面排版ST7920的初始化时序网上很多但有几个细节要注意。上电后要延时等待液晶内部复位然后连续发送三次0x30这是为了保险某些兼容屏少发一次可能初始化不成功。每次命令之间要有延时。// lcd12864.c sbit LCD_RS P3^5; sbit LCD_RW P3^6; sbit LCD_E P3^7; #define LCD_DATA P1 void LCD_WriteCmd(unsigned char cmd) { LCD_RS 0; LCD_RW 0; LCD_DATA cmd; LCD_E 1; delay_us(50); LCD_E 0; delay_us(50); } void LCD_WriteData(unsigned char dat) { LCD_RS 1; LCD_RW 0; LCD_DATA dat; LCD_E 1; delay_us(50); LCD_E 0; delay_us(50); } void LCD_Init(void) { delay_ms(50); LCD_WriteCmd(0x30); delay_ms(5); LCD_WriteCmd(0x30); delay_us(100); LCD_WriteCmd(0x30); delay_us(100); LCD_WriteCmd(0x0C); // 开显示不显示光标 LCD_WriteCmd(0x01); // 清屏 delay_ms(2); LCD_WriteCmd(0x06); // 写入后地址自动加1 } void LCD_ShowString(unsigned char row, unsigned char col, unsigned char *str) { unsigned char addr; // 12864的行地址不是连续的 switch(row) { case 0: addr 0x80 col; break; // 第一行 case 1: addr 0x90 col; break; // 第二行 case 2: addr 0x88 col; break; // 第三行 case 3: addr 0x98 col; break; // 第四行 default: return; } LCD_WriteCmd(addr); while(*str) { LCD_WriteData(*str); } }12864的行地址规律比较容易被忽视。第一行从0x80开始第二行从0x90开始第三行从0x88开始第四行从0x98开始。第三行不是0xA0而是0x88因为ST7920的显示RAM被分成了上下两个半屏的地址空间。如果想把字符串显示在第三行开头忘掉这个规律直接给0xA0屏幕上会显示到第一行或者干脆不显示。显示内容我设计了两行主要信息加一行状态第一行温度: xx.x C第二行电压: xx.xxV第三行显示DS1621的工作状态比如DS1621 OK或者DS1621 ERR如果I2C通信失败temp读出来的值会有异常这时候在第三行提示错误信息调试起来很直观。3.5 主流程整合主函数的逻辑很直接初始化液晶初始化DS1621然后进入死循环每隔500ms刷新一次采集和显示。// main.c void main(void) { unsigned char buf[17]; int temp_raw; unsigned int ad_code; unsigned int volt100; unsigned int t100; LCD_Init(); DS1621_Init(); while(1) { // 温度采集 temp_raw DS1621_ReadTemp(); if(temp_raw 0) { t100 0 - temp_raw; // 取绝对值 buf[0] -; buf[1] 0 t100 / 200; buf[2] 0 (t100 / 20) % 10; buf[3] .; buf[4] 0 (t100 % 20) / 2; buf[5] C; buf[6] \0; } else { t100 temp_raw; buf[0] ; buf[1] 0 t100 / 200; buf[2] 0 (t100 / 20) % 10; buf[3] .; buf[4] 0 (t100 % 20) / 2; buf[5] C; buf[6] \0; } LCD_ShowString(0, 0, 温度:); LCD_ShowString(0, 6, buf); // 电压采集 ad_code MAX1241_Read(); volt100 (unsigned long)ad_code * 500 / 4095; buf[0] 0 volt100 / 100; buf[1] .; buf[2] 0 (volt100 / 10) % 10; buf[3] 0 volt100 % 10; buf[4] V; buf[5] \0; LCD_ShowString(1, 0, 电压:); LCD_ShowString(1, 6, buf); delay_ms(500); } }这里温度显示稍微有些绕我把temp_raw统一看成“0.5℃的个数”。比如temp_raw51t10051t100/2000说明温度在0-9.9℃之间如果超过10℃这里会显示十位(t100/20)%10得到个位t100%20是余数除以2得到0或5对应小数位。这样用纯整数除法就把0.5℃精度拆成了xx.x格式。负温度时先取绝对值再加负号显示上不会出乱码。刷新周期500ms是最合理的。太快液晶显示会闪烁太慢温度电压变化感知不明显。如果想看动态效果更顺手可以用200ms但不要再低了12864的写入速度跟不上。4. Proteus仿真搭建与调试问题排错4.1 仿真电路搭建步骤Proteus版本我用的是8.x系列搭建步骤大致如下第一步新建工程后从元件库搜索并放置以下元件元件名称库内搜索关键词数量AT89C51AT89C511DS1621DS16211MAX1241MAX12411LM044L12864LM044L1滑动变阻器POT-HG1电阻RES4电容CAP2电解电容CAP-ELEC1晶振CRYSTAL1LED可选LED-RED112864在Proteus里的型号在不同版本不太一样有的版本叫LM044L有的叫AMPIRE128X64搜索“12864”或者“LM044L”都能找到。LM044L是ST7920控制器的模型引脚和实物基本一致可以直接用。第二步放置单片机最小系统。AT89C51的XTAL1和XTAL2接12MHz晶振晶振两端各接一个30pF电容到地。RST引脚接10μF电解电容到VCC、10k电阻到地。EA引脚必须接VCC否则单片机会去读外部程序存储器而Proteus模型里没有外部ROM程序就跑不起来。第三步按前面第二节的引脚分配表连线。DS1621的SDA和SCL各接一个4.7k电阻到VCCA0、A1、A2接地。MAX1241的VIN接滑动变阻器的滑动端滑动变阻器两端分别接5V和GND这样可以直接调出0-5V范围内的电压。注意如果MAX1241的VIN接0-5V超出了2.5V参考电压范围仿真可能不会烧毁器件但读出来会一直在满量程附近所以分压电阻该加就加我这里直接在VIN前面用两个10k电阻分压模拟测0-5V的场景。第四步写程序并编译出hex文件。在Keil里把代码编译通过后生成hex文件然后在Proteus里双击AT89C51芯片在Program File里选择这个hex文件。晶振频率也要改成12MHz和代码里的延时函数匹配。第五步点左下角的Play按钮运行仿真。如果一切正常12864上会显示温度和电压数值。4.2 仿真运行中的典型问题与解决方法我在调试过程中遇到过几个问题整理成表格方便查阅现象可能原因解决办法12864屏幕全黑VL对比度脚接错将VL接地或接一个电位器调节12864没有任何显示PSB脚没接高电平处于串行模式PSB接VCC选择并行模式温度显示0.0或固定值不变DS1621上拉电阻缺失或SCL/SDA接反加4.7k上拉核对引脚正确性温度显示异常大数读到了无符号负数加入负温度补码处理返回int类型电压读数一直4095VIN输入超过参考电压增加分压电路让输入不超过2.5V电压读数一直在0附近跳MAX1241的CS或SCLK接线错误核对三根SPI线是否一一对应单片机不运行EA引脚没接VCCEA接VCC加载hex文件还要特别提一个容易踩的坑在Proteus里给DS1621调节温度很多人找不到在哪里改。操作方式是选中DS1621元件右键选择Edit Properties或者直接双击在属性窗口里修改Temperature的值。改成负值就能测试零下温度显示是否正常。这个操作在调试负温度显示功能时必用。4.3 仿真的局限性与实物移植注意事项仿真跑通了不代表实物一定没问题。Proteus是理想化的环境几个差异要提前有心理准备第一时序宽容度。仿真模型对I2C和SPI时序的容错能力比实物强得多稍微有些延时偏差仿真也能跑通但实物可能直接死掉。所以代码里的延时不能随意删减特别是I2C的延时建议用_nop_()写短延时保持标准的SCL频率。第二上拉电阻。仿真里不加上拉电阻偶尔也能通信实物不加上拉电阻绝对不行。不要因为仿真能跑就省掉上拉。第三12864的对比度。仿真里VL接地通常就清晰了实物必须用电位器调节不然可能出现背光亮但字迹非常淡的情况。第四电源稳定性。实物中如果电源纹波大MAX1241的电压读数会不稳定。仿真里这是看不出来的实物的VDD和REF引脚要各加0.1μF去耦电容必要时加10μF电解电容。5. 功能扩展方向与个人经验5.1 还可以往哪些方向扩展这个项目的框架很适合继续加功能以下是我觉得性价比比较高的几个扩展方向第一加入温控报警。DS1621本身有TH和TL寄存器可以设置温度上限和下限还有一个T_OUT输出脚。当温度超过上限时T_OUT输出高电平这个引脚可以直接接一个三本文还有配套的精品资源点击获取