ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STC15单片机读写DS18B20温度传感器:时序、延时与Proteus仿真实战

STC15单片机读写DS18B20温度传感器:时序、延时与Proteus仿真实战 简介面向 STC15 单片机与传感器应用开发学习者这套 Proteus 仿真 Keil 源代码工程演示了 STC15W4K32S4 通过单总线读取 DS18B20 温度并利用串口 UART 将温度值发送至外部设备适合希望掌握 DS18B20 驱动和串口通信的嵌入式入门用户。压缩包共 37 个文件包含 C 语言源码.c/.h、Keil 工程配置.uvproj/.uvopt、Proteus 仿真设计.pdsprj/.pdsbak以及 hex、obj、lst 等编译与中间产物整体仅 233KB结构紧凑、便于下载。已有 3201 人学习下载工程经过验证参考价值可观。下载后可获得可直接打开运行的完整 Keil 工程与 Proteus 仿真图代码按模块划分 DS18B20 初始化、温度读取、波特率配置和串口发送等函数目录层次清楚方便对照仿真电路理解执行流程也可作为后续基于 STC15 系列做环境监测或嵌入式课程设计的起点。1. 项目整体认知从51到STC15的思维转变这个项目标题看起来像是课程设计或毕业设计里的常见题目但STC15W4K32S4这颗芯片和传统的STC89C52、AT89C51用法有本质区别。如果你只是把网上找的“89C52DS18B20串口”代码直接抄过来改个芯片型号十有八九会踩坑。先说清楚这颗芯片的定位。STC15W4K32S4属于STC15系列指令集和传统8051兼容但内核是1T架构——也就是说同频下执行速度比传统12T的89C52快12倍左右。这直接影响了延时函数的编写很多DS18B20的读时序需要微秒级延时89C52时代常用的for(i0;i100;i);循环写法在STC15上跑出来的实际延时时间完全不一样。如果不做适配DS18B20的初始化时序、读时序、写时序全都对不上温度数据自然读出来就是85°C这个值是DS18B20在上电复位后暂存器里的默认值也是读不到真实温度时最典型的错误特征。另一个关键点是STC15W4K32S4的IO口模式。传统51单片机的IO口是准双向口上电默认高电平可以直接驱动DS18B20但STC15系列的IO口默认状态是高阻输入除了P3.0和P3.1是准双向口。如果代码里没有把接DS18B20的引脚配置成准双向口或者开漏模式数据线上拉不到高电平时序就会乱掉。这个问题非常隐蔽很多新手在Proteus里仿真时由于Proteus的模型并不完全模拟真实芯片的IO状态仿真能跑通但换到真机就废了。整体来看这个项目涉及的知识点链是STC15系列的时钟系统和IO配置 → DS18B20的单总线时序协议 → 串口发送数据 → Proteus仿真联调。四块内容环环相扣任何一环出问题最终表现都是“串口输出乱码”或者“温度始终是85°C”。我在整理这篇博文时将从实际操作的角度把每一环掰开揉碎把排查链路写清楚方便你在Proteus仿真和真机调试时都能快速定位问题。2. DS18B20的时序不是“读温度”而是在“挤牙膏”DS18B20是Dallas现在叫Maxim出的单总线数字温度传感器测温范围-55°C到125°C分辨率可配置为9到12位。它的核心特点就是只有一个数据引脚供电、通信都靠这一根线完成所以时序协议非常严格。2.1 单总线通信的基本逻辑单总线的本质是“半双工、开漏、带上拉电阻”的通信方式。主机单片机和数据线之间需要一个4.7kΩ左右的上拉电阻总线空闲时为高电平。所有操作都是主机发起的DS18B20被动的根据主机给的时序来响应。操作一个完整的温度读取周期分为四步主机发送复位脉冲拉低480μs以上然后释放并等待DS18B20的存在脉冲主机发送跳过ROM命令0xCC因为总线上只挂了一个传感器主机发送启动温度转换命令0x44延时12位分辨率下需要750ms实际等待1秒以上比较稳妥再次复位发送跳过ROM0xCC发送读暂存器命令0xBE连续读取9个字节前两个字节就是温度值这里有个容易忽略的点DS18B20默认在上电后会自动开始一次温度转换但如果你不发送0x44命令就直接去读暂存器读到的是上一次的转换结果。对于需要实时温度的场景正确顺序是复位→0xCC→0x44→延时→复位→0xCC→0xBE→读数据。2.2 读时序的“挤牙膏”真相DS18B20的读时序是整个通信中最容易出问题的地方。每次读位时主机把总线拉低至少1μs然后释放之后DS18B20会在60μs内把总线拉高或者保持低电平来代表“1”或“0”。问题在于主机必须在拉低释放后的15μs内去采样读取电平采样早了读到的还是高电平因为传感器还没来得及把线拉低采样晚了传感器可能已经释放总线了读到的一律是高电平。我习惯把这个过程比喻成“挤牙膏”主机把牙膏盖拧开拉低总线传感器接着把牙膏挤出来拉低或保持高电平主机必须在牙膏刚挤出来的瞬间接住15μs内采样接晚了牙膏就掉地上了总线恢复高电平读到1。所以读时序的代码里两个关键延时——拉低持续时间1μs和释放后到采样的时间12-15μs——必须严格匹配。STC15在12MHz晶振下1T模式下1个机器周期约等于1/12MHz83.3ns。如果用_nop_()指令空操作一条大概是83ns。但Keil C51编译器对_nop_()的处理很直接如果你想写一个精确到微秒的延时函数最靠谱的方案是用STC提供的STC-ISP软件里的“延时计算器”工具。它会根据你选的芯片型号和主频直接生成一个近似微秒级延时的C代码这个工具在STC官方下载软件里自带非常实用。2.3 复位时序的应答判断复位时序中主机拉低480-960μs然后释放接着DS18B20会等15-60μs后拉低总线60-240μs表示“我在这里”。主机在这期间必须读取总线状态来判断传感器是否存在。如果你的代码里没有检测存在脉冲直接往下执行命令那么当传感器未连接或接触不良时程序会一直卡在某个状态或者读到全1的数据。好的代码习惯是复位后读一次总线如果为0说明存在如果为1直接报错返回。这个判断在仿真时尤其重要——很多人仿真时根本不接DS18B20也能跑但串口输出的数据全是无效值原因就是没有做存在性检测。3. 硬件设计细节从数据手册到Proteus的原理图Proteus仿真DS18B20的使用方法比真机简单得多因为Proteus内置的DS18B20模型已经帮你去掉了电气特性不会出现上拉电阻不够导致信号不稳定等真实硬件才有的问题。但这不代表你可以忽略硬件电路。我的建议是仿真时按规范画电路真机焊接时才不容易出问题。3.1 STC15W4K32S4的引脚分配我在Proteus里选芯片时直接搜“STC15W4K32S4”就能找到模型。默认的引脚和STC官方LQFP44封装对应。实际常用的引脚是P3.0RXD和P3.1TXD串口使用STC15系列默认这两个脚是准双向IO口可以直接接CH340或FT232等USB转串口模块P1.0到P1.7正常IO口可以用来接DS18B20VCC和GND接5V电源注意Proteus里需要显式加电源网络否则仿真时芯片不工作我习惯把DS18B20接在P1.0上。原因有两个一是这个引脚在Proteus仿真布局时容易布线二是在STC15的数据手册中P1口可以配置为ADC输入等复用功能但在这里只是普通IO操作简单。3.2 上拉电阻的取值问题在真实硬件上DS18B20的数据线必须接一个4.7kΩ的上拉电阻到VCC。如果你的单片机IO口配置成了准双向口内部其实也有一个微弱的上拉但强度不够特别是在较长线缆或者多个DS18B20并联时必须外接上拉。在Proteus仿真中如果不接上拉电阻DS18B20模型可能也能工作因为仿真模型默认内部有理想上拉。但为了仿真和实物一致我仍然会在原理图上放一个4.7kΩ电阻。这样后续如果你把原理图转成PCB去打样电路不用再改。3.3 电源滤波和去耦真机上每个芯片的VCC引脚旁边都应该放一个0.1μF的去耦电容。DS18B20如果使用寄生供电方式只有两根线数据线兼做电源在温度转换时需要较大的电流数据线上必须提供强上拉MOS管开关才能保证转换稳定。但在Proteus仿真中寄生供电模式经常无法正确模拟所以我建议直接使用外部供电模式DS18B20的VCC接5VGND接地DQ接数据线这样最简单可靠。如果你在仿真时发现DS18B20模型读出的温度值一直是-55°C这是DS18B20的测量下限不要怀疑代码先检查一下元件配置。Proteus里双击DS18B20有一个“Program”选项可以选择加载一个二进制文件。很多情况下这个模型本身自带了固件不需要额外加载但如果你设置错了就会出现异常值。4. 代码移植与实现从STC89C52到STC15W4K32S4下面给出一个完整的代码示例这只是一种实现思路。STC15W4K32S4的内部结构决定了你在移植代码时必须注意以下几处改动。4.1 头文件和芯片型号选择的注意点Keil C51里要支持STC15系列你需要安装STC官方提供的Keil补丁包STC-ISP软件里有“Keil仿真设置”和“添加STC型号到Keil”的功能。安装完之后在Keil的Device栏里就能选到STC15W4K32S4。代码开头使用的头文件建议用#include STC15W4K32S4.h这个头文件在STC官方资料包里有里面定义了所有特殊功能寄存器SFR的名字和位定义。如果你使用的是传统的reg51.h很多STC15系列特有的寄存器比如P0M0、P0M1、P1M0、P1M1这些端口模式配置寄存器还有AUXR这个辅助寄存器根本找不到定义程序一编译就会报错。4.2 延时函数必须按STC15重新生成这个项目的核心难点不在DS18B20协议的实现而在于延时函数的精度。STC15W4K32S4的1T模式意味着原来12T模式下的延时循环需要重新调整。我的做法是直接用STC-ISP软件生成打开STC-ISP软件找到“延时计算器”模块选择芯片型号STC15W4K32S4设置主频为12MHz或者你实际使用的晶振频率选择“C语言代码”输入需要的延时时间比如1μs、5μs、10μs、500μs、750ms点击“生成代码”复制粘贴到你的工程里生成的延时函数大致是这样void Delay1us() //12.000MHz { unsigned char i; _nop_(); _nop_(); i 6; while (--i); } void Delay500ms() //12.000MHz { unsigned char i, j, k; i 28; j 25; k 162; do { do { while (--k); } while (--j); } while (--i); }注意STC-ISP生成的延时函数不带参数每次需要不同延时就得生成对应的函数。对于750ms的延时你可以生成一个500ms的再调用一次500ms和一次250ms拼起来或者直接生成一个750ms的。不要试图用一个带参数的延时函数因为在1T模式下带参数的函数调用和循环计算会引入不确定的额外时间误差会累积。4.3 DS18B20驱动代码的写法和坑DS18B20的驱动代码网上很多但针对STC15需要做几处修改。下面给出一个可工作的版本关键代码加了注释sbit DS18B20_DQ P1^0; // 微秒延时由STC-ISP生成这里简化写法 void DelayUs(unsigned int us) { while(us--) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } } // DS18B20复位 bit DS18B20_Reset(void) { bit presence; DS18B20_DQ 0; // 拉低总线 DelayUs(240); // 拉低480us以上 DS18B20_DQ 1; // 释放总线 DelayUs(30); // 等待15-60us presence DS18B20_DQ; // 读取存在脉冲 DelayUs(50); return presence; // 返回0表示存在 } // 写一个字节 void DS18B20_WriteByte(unsigned char dat) { unsigned char i; for(i0; i8; i) { DS18B20_DQ 0; // 起始信号 _nop_(); DS18B20_DQ dat 0x01; // 输出数据位 DelayUs(20); DS18B20_DQ 1; // 释放总线 dat 1; } } // 读一个字节 unsigned char DS18B20_ReadByte(void) { unsigned char i, dat 0; for(i0; i8; i) { dat 1; DS18B20_DQ 0; // 起始信号 _nop_(); _nop_(); DS18B20_DQ 1; // 释放总线 _nop_(); _nop_(); if(DS18B20_DQ) // 采样 dat | 0x80; DelayUs(20); } return dat; }这里有一个非常重要的细节在复位函数中我读到的presence为0表示传感器存在。很多初学者会搞反以为读到1表示存在。实际上DS18B20的存在脉冲是拉低总线所以主机读到的电平是0。如果代码写成presence 1才继续那永远进不了下一步。在DS18B20_ReadByte函数里每次读位完成后的DelayUs(20)是为了确保整个读时隙的长度至少60μs。这个延时不能省略否则连续读位时前一位还没结束就开始下一位会导致数据移位错误。4.4 主函数流程和串口发送主函数的逻辑非常直接void main(void) { unsigned char tempL, tempH; int temperature; unsigned char buf[20]; UartInit(); // 初始化串口9600bps while(1) { if(DS18B20_Reset() 0) // 检测到传感器 { DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0x44); // 启动温度转换 Delay500ms(); // 等待转换完成 DS18B20_Reset(); DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0xBE); // 读暂存器 tempL DS18B20_ReadByte(); // 温度低字节 tempH DS18B20_ReadByte(); // 温度高字节 temperature (tempH 8) | tempL; // 温度值处理见下文 } else { // 传感器未连接发送错误信息 } Delay500ms(); // 隔一段时间再采样 } }温度值的处理要根据分辨率来。DS18B20的测温结果以16位有符号数形式存放在暂存器前两个字节中低4位是小数部分。如果分辨率是12位那么实际温度 原始值 × 0.0625°C。例如原始值是0x0191十进制401实际温度就是25.0625°C。重点来了原始值的符号位在高字节的最高位。如果是零下温度比如-10°C原始值在内存里是以补码形式存在的0xFFF6直接转int会得到-10乘以0.625的整数处理方式需要特别注意。一个简单的处理方式float temp_c (float)(tempH 8 | tempL) * 0.0625; sprintf(buf, Temperature: %.2f C\r\n, temp_c); UartSendString(buf);在Keil C51中使用浮点数会额外消耗4-5KB的代码空间但STC15W4K32S4有64KB Flash完全不用担心。如果不想用浮点也可以直接用整数运算int temp_int (tempH 8 | tempL) * 100 / 16;然后把整数部分和小数部分分别处理用sprintf或者手动拼字符串。4.5 串口初始化STC15和传统51的差异STC15的串口初始化和传统51基本一致但有一个重要区别默认情况下STC15的定时器2可以作为串口波特率发生器使用这种方式更省定时器资源。下面是一个使用定时器2产生9600bps的初始化代码void UartInit(void) //9600bps12.000MHz { SCON 0x50; //8位数据,可变波特率 AUXR | 0x01; //串口1选择定时器2为波特率发生器 AUXR | 0x04; //定时器2时钟不分频 (1T模式) T2L 0xC0; //设置定时初始值 T2H 0xFF; //设置定时初始值 AUXR | 0x10; //启动定时器2 ES 1; //使能串口1中断 EA 1; //使能总中断 }这个初始化代码里最容易被忽略的是AUXR | 0x01这条语句。在传统51中串口1的波特率发生器默认是定时器1如果你想用定时器2必须通过AUXR寄存器切换。不切换的话定时器2的配置不会生效串口输出的波特率完全是错的。如果你不想用定时器2也可以用定时器1但代码需要相应调整void UartInit(void) //9600bps12.000MHz { SCON 0x50; //8位数据,可变波特率 TMOD 0x20; //定时器1模式28位自动重载 AUXR 0xBE; //定时器1时钟不分频串口1选择定时器1 TH1 0xE8; //设置定时重载值 TL1 0xE8; TR1 1; ES 1; EA 1; }两种方式都可以但我个人推荐使用定时器2的方式因为STC15系列对定时器2的支持更完善而且定时器1在某些情况下还会被用于其他功能比如PWM或者输入捕获减少抢占冲突。5. Proteus仿真联调虚拟终端与串口助手的位差仿真环境下的联调步骤很多人会卡在一个看起来很奇怪的问题上Proteus里代码能编译、能运行但虚拟终端或串口助手显示的内容乱码或者什么都没有。这种情况通常是波特率设置有偏差。5.1 Proteus的晶振频率必须和代码里的主频一致Proteus里双击STC15W4K32S4芯片会弹出一个属性对话框里面有一个“Clock Frequency”选项。默认值可能是1MHz或者你手动设置的11.0592MHz。这个设置必须和你代码里延时函数计算时使用的主频一致。比如你在STC-ISP里选择“12MHz”生成延时函数那么Proteus里的晶振频率也必须设置为12MHz。如果设置不一致延时函数的时间就会偏离理论值DS18B20的时序就会错乱。这里额外提醒一点代码中串口波特率的计算也依赖主频。我们前面写的9600bps初始化数值是按12MHz主频算出来的。如果你把Proteus的晶振频率改成11.0592MHz因为这个频率计算波特率比较准而又用12MHz的初始化参数结果一定是乱码。一个最常见的乱码原因解决路径是先把Proteus晶振频率设为12MHz用STC-ISP按12MHz生成延时函数串口初始化参数按上面的代码设置如果串口输出还是乱码用串口调试助手把波特率从9600改成4800或19200逐个试一次在Proteus中虚拟终端Virtual Terminal的波特率设置是在虚拟终端组件内部设置的。双击虚拟终端找到“Baud Rate”选项选择和代码一致的9600即可。如果你用的是COMPIM组件接虚拟串口再配合串口调试助手则需要检查COMPIM的配置主机波特率、虚拟波特率都要设置成9600。5.2 在线串口监视的方法Proteus本身有一个“Debug → Virtual Terminal”功能可以直接在仿真时显示串口输出。我习惯在原理图中放置一个虚拟终端组件TXD接单片机的RXD注意交叉然后在代码里调用串口发送函数就能在虚拟终端窗口看到输出。这种方法比使用COMPIM加外部串口助手更直观因为虚拟终端不依赖PC上的真实串口资源也不会因为驱动问题导致看不到输出。放置虚拟终端的步骤在Proteus左侧工具栏点击“Virtual Instruments”图标在列表中找到“VIRTUAL TERMINAL”放置到原理图中把虚拟终端的RXD引脚连接到单片机的TXD引脚P3.1如果你同时用了串口中断接收还需要把虚拟终端的TXD连接到单片机的RXD引脚P3.0运行仿真后如果代码正常虚拟终端会显示温度值。如果显示乱码优先检查波特率。在虚拟终端上右键选择“Edit Properties”还能设置数据位、停止位、校验位默认是8N1和我们的串口初始化一致。5.3 仿真时的延时和复位问题Proteus仿真中DS18B20模型的响应速度比真实芯片快很多但延时函数的延时时间还是要按照真实需求来。我在仿真时发现一个有趣的现象如果把温度转换后的750ms延时缩短到100ms仿真里依然能读出正确温度值因为Proteus的模型在模拟温度转换时不会真实消耗那么长时间。但如果你把这个缩短的延时用在真机上读出的温度就始终是初值。所以仿真通过不代表代码没问题温度的转换延时必须留足750ms。另外Proteus中“Run”按钮旁边有一个实时速度控制如果你的程序跑得非常快导致DS18B20的时序被仿真器的实时调度打乱可以尝试把运行速度调低一些比如从100%降到1%这样时序的模拟更接近真实。6. 实测环境中的坑与补救经验如果只是做Proteus仿真前面的内容已经够用了。但如果你打算把程序烧录到真实的STC15W4K32S4上看效果下面这些实际操作中遇到的坑我提前给你打预防针。6.1 STC15W4K32S4烧录时的硬件选择STC单片机烧录不需要专用的仿真器只需要一个USB转串口模块如CH340、CP2102、FT232。连接方式USB转串口模块的TXD接单片机P3.0RXDUSB转串口模块的RXD接单片机P3.1TXD共地STC的烧录是“先点下载再上电”的方式。使用STC-ISP软件选择芯片型号加载hex文件点击“下载/编程”然后给单片机重新上电。如果点击下载前开发板已经上电了会一直显示“正在检测目标单片机...”这时候按一下板子上的复位键或者重新断电再上电即可。有一个常见的坑CH340模块在3.3V下工作正常但STC15W4K32S4需要5V供电。如果你的USB转串口模块上有跳线可以选择5V输出很多模块的VCC是5V或3.3V可切换一定要设成5V。如果模块只支持3.3V输出那需要外部给单片机单独供5V电源但TXD/RXD的电压不匹配可能造成通信不稳定最好用5V电平的模块。6.2 真机上DS18B20的供电问题前面提到过寄生供电的问题。真机上如果你使用寄生供电模式DS18B20的VCC直接接地靠数据线的寄生电荷供电温度转换时吃电流比较大必须在上位机发送“Skip ROM”命令后立即把数据线拉高强上拉直到温度转换结束。这种模式在Proteus里仿真很难体现所以我强烈建议使用外部供电模式VCC接5VGND接地DQ接数据线加4.7kΩ上拉。这是最不容易出错的方式。另外注意DS18B20的引脚封装常见的是TO-92三引脚封装正面朝向自己平面朝前从左到右引脚依次是GND、DQ、VCC。很多人第一次用把引脚接反了温度值直接就是错的或者干脆读不到存在脉冲——别问我怎么知道的。6.3 串口输出的数据格式处理在串口助手上显示温度值时如果直接用十六进制显示你会看到类似XX XX这样的原始字节流比如01 91代表温度25.0625°C。如果直接用字符串显示那么代码里发送的内容就是能在串口助手上看到的文本。我建议在代码里发送格式化的字符串方便调试// 发送字符串的函数 void UartSendString(char *str) { while(*str) { SBUF *str; while(!TI); TI 0; } }发送时组合一个完整的字符串char buf[32]; sprintf(buf, Temp: %.2f C\r\n, temp_c); UartSendString(buf);注意\r\n是必须的否则串口助手上所有数据都挤在一行。有些串口助手需要勾选“发送新行”才会正确处理换行但如果你在代码里带上\r\n就能完全不受串口助手设置的影响。6.4 为什么读到85°C85°C是DS18B20上电复位后暂存器的默认值无论温度多少读取前两个字节都是0x0550。这段数据乘以0.0625后正好是85。如果程序一运行就读到85°C而且一直不变说明你根本没有成功启动温度转换就直接读了暂存器。排查顺序很简单先用示波器或者调试助手检查有没有执行0x44命令如果没有可能是延时不够温度转换还没结束就发读命令或者复位时序有问题导致DS18B20根本没响应指令所有的写操作都没写进去。在Proteus仿真时你可以在代码里适当加点调试信息比如在复位失败后向串口发送DS18B20 not found然后在虚拟终端里看是不是输出了这条信息。如果是问题就在复位和存在脉冲检测这一环如果不是问题就可能出在延时或者晶振频率配置。7. 从仿真到实物的几个“最后一公里”建议这个项目做到仿真跑通已经能应付大部分课程设计和毕业设计的要求了。但如果你想把它做成一个长期稳定运行的测量设备下面几个点值得再花点时间打磨。第一温度转换延时不要偷懒。DS18B20的转换时间在12位分辨率下最长750ms有些芯片批次可能更慢。你可以把延时加到800ms甚至1秒牺牲一点点刷新率换取稳定性。第二串口发送间隔不要太频繁。如果每100ms读一次温度并且发送一次不仅占用串口带宽而且长时间运行后DS18B20在连续转换时可能会因为供电不足导致读数漂移。我实际测试下来1秒一次的刷新率足够适用于大多数室温监测场景。第三Proteus仿真只是验证逻辑。要注意实际芯片的高速特性比如上电速度、IO口驱动能力在Proteus里没法完全体现。STC15W4K32S4在5V供电下IO口输出高电平时驱动能力很强直接驱动DS18B20完全没问题但如果你把IO口配置成高阻输入忘了改仿真正常实物必定翻车。第四如果温度值出现剧烈跳变先查供电。DS18B20对电源纹波比较敏感特别是用USB供电或者开关电源供电时数字电路的高频噪声会耦合到数据线上。解决办法是在DS18B20的VCC和GND之间加一个10μF电解电容和0.1μF陶瓷电容并联去耦同时数据线的上拉电阻不要省。我在实际做这个项目时还遇到过一种情况程序在Proteus仿真中温度显示正常但烧录到真机后温度值每隔几次就会出现一个明显偏大的值。后来检查发现是因为我把DS18B20的数据线布得太靠近板子上的晶振干扰导致的。把数据线换到远离晶振的位置后问题解决。这类问题只能靠实物调试验证仿真帮不了你。整个流程走下来你会发现这个项目其实是个很好的综合练习它把单片机最小系统、单总线协议、定时器、串口通信、仿真调试全串在了一起。把这套流程吃透以后做其他传感器项目DHT11、SHT30这些也都是类似的套路会顺手很多。本文还有配套的精品资源点击获取
返回列表