恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
STC8A驱动SHT30温湿度传感器:从I2C通信到串口显示全解析
首页
资讯中心
/
STC8A驱动SHT30温湿度传感器:从I2C通信到串口显示全解析
STC8A驱动SHT30温湿度传感器:从I2C通信到串口显示全解析
发布时间:2026/8/31 1:52:53
简介本资源是一套面向嵌入式初学者与单片机开发者的STC8A单片机实战例程聚焦SHT30数字温湿度传感器的I²C通信与串口数据可视化。通过完整C51源码实现传感器驱动、数据解析、UART上传及串口助手实时显示覆盖硬件接口配置、协议时序控制、浮点数值转换等关键技能适用于智能家居、环境监测等物联网入门项目开发。压缩包共18个文件含5个核心C源文件i2c.c、sht30.c、uart.c、delay.c、main.c、5个对应头文件含STC8.H和传感器寄存器定义、Keil工程文件.uvproj/.uvopt、编译输出.hex/.m51及配套资料.rar总大小1.27MB结构清晰、模块分离便于理解I²C底层驱动与串口通信协同逻辑。已有241人学习下载提供可直接烧录运行的完整工程包含错误重试机制与数据单位换算代码助读者快速掌握STC8A平台下高精度环境传感系统的搭建全流程。 打开串口助手看到温度 25.63℃、湿度 52.14%RH 稳定刷新的时候这套 STC8A 加 SHT30 的例程就算是真正跑通了。最近不少朋友在折腾单片机温湿度采集实验翻来覆去还是 DHT11 那几个例程精度和稳定性都差点意思。如果你的开发板上恰好是 STC8A 系列单片机手头又有一颗 SHT30 数字温湿度传感器那这份例程源码正好能解决从硬件接线、I2C 通信到串口显示的全链路问题。我这次就把这套例程的完整逻辑、代码拆解和实际踩坑过程从头到尾梳理一遍帮助你快速跑通并理解背后的原理。1. 为什么这套组合值得玩STC8A 与 SHT30 的定位1.1 SHT30 相比 DHT11 的优势在哪里先说说传感器选型。DHT11 在入门实验里出场率确实高价格便宜、例程多得是但它的精度实在感人——湿度误差正负 5%RH温度误差正负 2℃而且对时序要求极其苛刻稍微有点中断延迟读取就会失败。AM2301DHT21好一点但也好得有限。SHT30 是 Sensirion 出的数字温湿度传感器走标准 I2C 接口温度精度能做到正负 0.3℃湿度精度正负 2%RH响应时间基本在 8 秒以内还带了 CRC 校验数据可靠性完全不是一个级别。我为什么强调 CRC 校验这一点DHT11 那种单总线协议读出来数据对不对全看时序错了你也发现不了SHT30 返回的 6 字节数据里带了两个 CRC 校验字节温度数据和湿度数据各有一个校验码读回来先校验再使用数据可信度高很多。对实验来说这可能只是少了一点误差但对后面的产品级开发来说这个习惯从一开始就值得养成。1.2 STC8A8K64S4 这颗芯片能干什么STC8A8K64S4 是 STC 8A 系列里比较有代表性的一颗增强型 8051 内核单片机。1T 指令周期主频最高能跑到 45MHz 左右64KB Flash、8KB SRAM4 个串口还有硬件 I2C、PWM、ADC 这些外设。拿它来驱动一颗 SHT30 传感器资源上那是相当富余。这套例程用的是软件模拟 I2C不是芯片自带的硬件 I2C 外设。这个选择后面会详细说但先记住一点模拟 I2C 在这种教学验证场景下最大的好处是引脚任意、逻辑清晰、方便移植你不用去翻数据手册查 I2C 外设的引脚映射表和寄存器配置把两根线接到任意两个 GPIO 上就能用。STC8A 的 GPIO 驱动能力也够SHT30 模块板上基本上都自带上拉电阻接线极其简单。1.3 开跑之前硬件软件清单与接线方式准备材料如下STC8A 系列开发板一块我用的是 STC8A8K64S4别的型号同理SHT30 温湿度传感器模块一个注意买的时候选带 I2C 上拉电阻的成品模块省很多事USB 转 TTL 串口模块一个烧录和串口打印共用杜邦线若干接线方式非常固定SHT30 模块就四个引脚SHT30 引脚接到 STC8AVCC3.3VGNDGNDSCLP1.0SDAP1.1开发环境方面代码用 Keil C51 编译STC8A 支持串口下载所以不需要专门的仿真器用 STC-ISP 软件就能把程序烧进去。串口助手我用的是 SSCOM这个工具后面单开一节专门讲。准备好这些就可以开始看代码了。2. SHT30 的 I2C 通信细节地址、命令、数据帧2.1 设备地址到底是多少0x44 还是 0x88SHT30 的 I2C 地址是 7 位地址由 ADDR 引脚的电平决定。ADDR 引脚接地或者悬空的时候7 位地址是 0x44ADDR 引脚接高电平地址变成 0x45。成品模块一般默认把 ADDR 拉低所以 0x44 是最常见的情况。但这里有一个特别坑初学者的事情I2C 通信时主机发送的地址字节是 7 位地址左移一位最低位补上读写标志。所以向 SHT30 写入时发送的字节是 0x44 1 0x88从 SHT30 读取时发送的字节是 0x44 1 | 1 0x89。很多新手拿着 0x44 直接往 I2C 总线上发结果设备根本没应答还以为是传感器坏了。你在例程里看到 0x88 和 0x89 这两个数要能立刻反应过来这其实是同一个地址的写和读。2.2 单次测量命令与时钟延展模式的选择SHT30 支持单次测量和周期测量两大类模式单次测量又分时钟延展Clock Stretching启用和禁用两种同时还有高、中、低三档重复性可选。这套例程以及大部分 51 单片机例程选的命令是0x24 0x00这个命令的含义是单次测量、高重复性、时钟延展禁用。为什么不选时钟延展启用的0x2C 0x06因为时钟延展模式下传感器在测量期间会把 SCL 线拉低主机要一直等待直到 SCL 释放才能继续通信。51 单片机的软件 I2C 实现这种等待逻辑比较绕而且一旦延时处理不好容易卡死。禁用时钟延展就简单粗暴了发完测量命令单片机自己延时 20ms保证测量完成后再去读数据逻辑上完全可控。高重复性对应的是测量精度最高的档位典型测量时间约 12.5ms最大 15ms。例程里延时 20ms 留了充足的余量这是稳妥的做法。2.3 返回的 6 字节数据与 CRC 校验原理单次测量完成后从 SHT30 读回来的数据是固定的 6 个字节顺序如下字节位置内容0温度数据高字节1温度数据低字节2温度数据 CRC 校验码3湿度数据高字节4湿度数据低字节5湿度数据 CRC 校验码温度和湿度原始值都是 16 位无符号整数高字节在前。读取的时候有个细节前 5 个字节读完主机要回 ACK最后 1 个字节读完主机要回 NAK然后发停止信号。如果你全程回 ACK 或者全程回 NAKSHT30 的通信状态也会乱套读回来的数据会错位。CRC 校验的算法是 CRC-8多项式是x^8 x^5 x^4 1对应十六进制就是 0x31初始值 0xFF。这个算法不是 SHT30 独有的SHT31、SHT35、SHT85 这些 Sensirion 的传感器都用同一套 CRC。校验的时候把温度两个字节放进算法得到 CRC然后和传感器返回的第三个字节比对一致说明温度数据可靠湿度同理。2.4 从原始 ADC 值到温湿度的换算公式SHT30 返回的 16 位原始值不是直接的温湿度需要用公式换算温度T -45 175 * rawT / 65535湿度RH 100 * rawH / 65535rawT 是温度原始 16 位值rawH 是湿度原始 16 位值。为什么要除以 65535因为 SHT30 内部 ADC 是 16 位满量程就是 65535。这个换算关系是在传感器出厂时就标定好的直接套公式就行。温度范围 -40℃ 到 125℃湿度范围 0%RH 到 100%RH公式算出来不会越界。3. 例程源码拆解从 I2C 时序到串口输出3.1 工程文件结构与主循环逻辑这套例程的源码结构不复杂核心文件就几个main.c负责主循环和串口输出i2c.c实现底层 I2C 时序sht30.c是 SHT30 的驱动层delay.c提供延时函数。整体分层很明确底层 I2C 时序对上层的 SHT30 驱动透明SHT30 驱动又对上层的 main 函数透明这是非常典型的嵌入式驱动分层写法。主循环的核心逻辑大概是这样void main(void) { unsigned char sht30_data[6]; unsigned int rawT, rawH; float temp, humi; UART1_Init(); delay_ms(100); SHT30_SoftReset(); while (1) { if (SHT30_ReadTempHum(sht30_data) 0) { rawT (sht30_data[0] 8) | sht30_data[1]; rawH (sht30_data[3] 8) | sht30_data[4]; temp -45.0f 175.0f * rawT / 65535.0f; humi 100.0f * rawH / 65535.0f; UART1_SendData(temp, humi); } delay_ms(500); } }主循环的逻辑很直白每次都读取一次温湿度读到了就换算成物理量通过串口发送出去然后等 500ms。这个间隔对温湿度采集来说完全够用SHT30 本身响应就很灵敏在室内环境下温度半秒一次的采样率已经非常充裕了。3.2 软件 I2C 底层实现为什么不用硬件外设前面说了例程用的是软件模拟 I2C底层代码就围绕 GPIO 实现起始、停止、读写字节这几个基本操作。我用的是 P1.0 做 SCL、P1.1 做 SDA你可以按自己的接线改sbit SCL P1^0; sbit SDA P1^1; void I2C_Start(void) { SDA 1; SCL 1; _nop_(); _nop_(); SDA 0; _nop_(); _nop_(); SCL 0; } void I2C_Stop(void) { SCL 0; SDA 0; _nop_(); _nop_(); SCL 1; _nop_(); _nop_(); SDA 1; } bit I2C_WriteByte(unsigned char dat) { unsigned char i; bit ack; for (i 0; i 8; i) { SDA (dat 0x80) ? 1 : 0; dat 1; SCL 1; _nop_(); _nop_(); SCL 0; } SDA 1; SCL 1; _nop_(); _nop_(); ack SDA; SCL 0; return ack; } unsigned char I2C_ReadByte(void) { unsigned char i, dat 0; for (i 0; i 8; i) { SCL 1; _nop_(); dat (dat 1) | SDA; SCL 0; _nop_(); } return dat; }为什么这套例程选模拟 I2C 而不是 STC8A 自带的硬件 I2C 外设我在前面埋了个伏笔这里展开说。STC8A 的硬件 I2C 确实存在而且功能完整但它的问题在于引脚映射不是随便选的需要查寄存器配置对应的 I2C 引脚组寄存器配置也比 GPIO 翻转复杂涉及 I2CCFG、I2CMCR、I2CSR 这一串寄存器。对于教学实验、例程验证这种场景模拟 I2C 的代码每行都是直白的逻辑GPIO 拉高拉低出了问题单步调试也直观。另外软件模拟 I2C 的代码拿到 STC89C52、STC15 这些其他 51 单片机上也能直接跑可移植性好得多。I2C 时序里有一个细节容易被忽略_nop_()的作用。STC8A 的 GPIO 翻转速度很快如果不加延时SCL 的频率可能飙到 1MHz 以上虽然 SHT30 也支持 fast mode最高 400kHz但杜邦线连接的情况下信号质量会很差。加几个 NOP 不是为了凑代码行数而是把 I2C 时钟降到合理范围。这套例程里用的是 Keil C51 的_nop_()实际等效约一条指令的时间在 24MHz 主频下大概是 0.17 微秒SCL 频率基本落在可控范围内。如果你的杜邦线比较长或者环境干扰大可以在每个阶段多加几个 NOP牺牲一点速度换取稳定性。3.3 SHT30 驱动软复位、触发测量、读取数据SHT30 的驱动层封装了三个操作软复位、读取温湿度、校验。软复位命令是0x30 0xA2主要在做完初始化后让传感器恢复到确定状态。读取温湿度的完整流程是这样的unsigned char SHT30_ReadTempHum(unsigned char *buf) { unsigned char ret 0; unsigned char i; I2C_Start(); ret | I2C_WriteByte(0x88); // 写地址 ret | I2C_WriteByte(0x24); // 单次测量高重复性时钟延展禁用 ret | I2C_WriteByte(0x00); I2C_Stop(); delay_ms(20); // 等待测量完成 I2C_Start(); ret | I2C_WriteByte(0x89); // 读地址 for (i 0; i 5; i) { buf[i] I2C_ReadByte(); I2C_ACK(); } buf[5] I2C_ReadByte(); I2C_NAK(); I2C_Stop(); if (ret ! 0) return 1; // 地址无应答 // 校验温度 CRC 和湿度 CRC if (SHT30_CRC8(buf[0], 2) ! buf[2]) return 2; if (SHT30_CRC8(buf[3], 2) ! buf[5]) return 3; return 0; }这个流程里ACK 和 NAK 的实现是配合 I2C_ReadByte 使用的。ACK 就是在读完一个字节后主机把 SDA 拉低一个时钟周期NAK 就是主机保持 SDA 高电平一个时钟周期。代码片段里的I2C_ACK()和I2C_NAK()通常这样实现void I2C_ACK(void) { SDA 0; SCL 1; _nop_(); _nop_(); SCL 0; SDA 1; } void I2C_NAK(void) { SDA 1; SCL 1; _nop_(); _nop_(); SCL 0; }这里的顺序不能搞反读数据的时候最后一位必须是 NAK否则 SHT30 会认为主机还要继续读总线状态就会错乱。很多朋友第一次移植 SHT30 驱动时总在最后一个字节读完之后多回一个 ACK导致下一次通信失效表现就是第一次读数正常、第二次数据全乱排查半天找不到原因。CRC 校验函数的实现如下unsigned char SHT30_CRC8(unsigned char *data, unsigned char len) { unsigned char crc 0xFF; unsigned char i, j; for (i 0; i len; i) { crc ^ data[i]; for (j 0; j 8; j) { if (crc 0x80) crc (crc 1) ^ 0x31; else crc 1; } } return crc; }CRC 的实现完全对应前面说的多项式 0x31初始值 0xFF。在校验失败时返回不同的错误码2 表示温度 CRC 失败3 表示湿度 CRC 失败这样在调试时可以通过串口直接知道是哪一项检查没过不用瞎猜。这里也顺便说一句SHT30_ReadTempHum 最前面的三个ret | I2C_WriteByte(...)是在判断器件地址有没有应答。如果 SHT30 没接好或者地址不对I2C_WriteByte返回的 ack 会是 1ret 非零后面的操作直接跳过。这个机制能帮你快速定位接线问题不会带病运行。3.4 数据换算与串口格式化输出数据换算部分前面公式已经提到了但串口输出方面有一个实际经验值得说。C51 环境下直接用printf重定向到串口虽然方便但printf在 Keil C51 里非常占用代码空间和栈空间格式化浮点数据还会带来额外的性能开销。这套例程的做法是拆分整数和小数手动构造字符串发送既不依赖庞大的 printf 系列函数又能精确控制在串口助手上显示的格式。void UART1_SendData(float temp, float humi) { char buf[64]; int temp_int, temp_dec, humi_int, humi_dec; temp_int (int)temp; temp_dec (int)((temp - temp_int) * 100); if (temp_dec 0) temp_dec -temp_dec; humi_int (int)humi; humi_dec (int)((humi - humi_int) * 100); if (humi_dec 0) humi_dec -humi_dec; sprintf(buf, Temp: %d.%02d C, Humi: %d.%02d %%RH\r\n, temp_int, temp_dec, humi_int, humi_dec); UART1_SendString(buf); }sprintf在 C51 下还是会有一定的资源开销但 STC8A8K64S4 有 8KB SRAM开个 64 字节的缓冲区压力不大。如果你用的是更小资源的芯片比如只有 256 字节 RAM 的传统 51sprintf 就要慎用了可以改成逐字节拼接输出。这个取舍在单片机开发里很常见资源换便利或者便利换资源。串口字符串发送函数就是一个简单的字节循环void UART1_SendString(char *str) { while (*str) { SBUF *str; while (!TI); TI 0; } }注意%RH里的百分号在 sprintf 格式化字符串中需要写成%%否则编译器会把%R当成一个不存在的格式说明符输出结果就乱了。这种小问题最容易在改代码时引入我的建议是格式化字符串最好整行复制不要手敲。3.5 串口 1 初始化与 STC-ISP 波特率生成器串口 1 的初始化我特别建议用 STC-ISP 软件里的“波特率计算器”生成。这个功能很多人没注意其实非常好用。打开 STC-ISP选好单片机型号填上目标波特率和系统时钟频率它会直接生成一段完整的串口初始化代码你只需要复制粘贴到工程里就行。选择系统时钟的时候我建议把内部 IRC 频率设为 11.0592MHz。为什么是这个数因为 11.0592MHz 是 51 单片机串口通信的“标准频率”它可以精确分频出 9600、57600、115200 这些常用波特率误差几乎为零。STC8A 内置的高精度 IRC 时钟在常温下的精度在正负 0.3% 左右配合 11.0592MHz 使用 115200 波特率完全没问题不需要外接晶振。烧录的时候也不需要外部晶振STC-ISP 可以选择“使用内部 IRC 时钟”把频率设为 11.0592MHz 即可。注意 STC8A 的下载方式是冷启动下载先在 STC-ISP 里点“下载/编程”然后再给开发板上电这样才能进入 ISP 引导区。如果上电时序不对下载会一直卡在“正在检测目标单片机”。4. 串口助手这侧参数配置与数据观察4.1 串口助手选型SSCOM 和 XCOM 怎么选串口助手这个工具在 Windows 下选择很多我用得最多的是 SSCOM网上搜索“sscom 串口助手”就能找到。它的优点是绿色单文件、体积小、功能齐全支持定时发送、HEX 显示/发送、字符显示、保存日志够用且稳定。XCOM 是正点原子出的界面做得好一些自定义波特率方便适合新手。选哪个都不影响调试关键是串口参数必须和单片机端一致。如果你用的 STC-ISP它自己也带了一个串口调试助手面板集成了下载和串口调试两个功能。这个对于初学者来说最省事因为不用额外装工具烧完程序切到串口调试就能看数据。4.2 关键参数配置波特率、数据位、停止位、校验位这套例程用的是 UART1波特率 1152008 位数据位、1 位停止位、无校验位这就是最常见的 115200-8-N-1。打开串口助手后依次配置波特率选择 115200数据位 8停止位 1校验位 None显示方式选“字符串显示”默认文本模式配置完成后点“打开串口”如果代码运行正常串口助手会以每 500ms 一次的频率持续刷新温湿度数据。如果你看到的是乱码优先检查串口参数和单片机初始化代码是否一致再看电脑的 USB 转串口驱动是否装好。4.3 用 HEX 显示模式验证数据帧串口助手有一个很有用的调试技巧把显示模式切到“HEX 显示”这样你看到的是一串十六进制字节而不是文本。通过 HEX 显示可以直接验证单片机发送的原始数据帧特别是排查格式化字符串是否出错时非常管用。比如正常文本模式下显示Temp: 25.63 CHEX 模式下你会看到对应 ASCII 码的十六进制序列一旦发现某个字符的 ASCII 值不对就说明格式化字符串出了问题。HEX 显示模式还能帮你叠加验证 STC8A 的串口发送代码本身是否正确。比如你发送了字符串Temp:HEX 显示里应该看到54 65 6D 70 3A54 是 T、65 是 e、6D 是 m、70 是 p、3A 是 :。读得懂 HEX 数据你就多了一个排查手段。4.4 串口助手的定时发送与主动请求模式这套例程是单片机主动上报数据不需要电脑端发送任何指令。但如果你在后续开发中希望改成“电脑发指令、单片机才上报”的被动模式串口助手的“定时发送”功能就派上用场了。SSCOM 可以设置定时发送的时间间隔比如每 1000ms 发送一次READ\r\n单片机在串口中断里收到这个指令后再去读取 SHT30 并上报数据。这种交互模式的好处是总线效率高主机想什么时候要数据就什么时候要从机不用一直发。后面做上位机、做数据记录的时候被动模式更可控。串口助手的定时发送在调试这类协议时相当于一个简易的上位机功能虽小但非常实用。5. 实测中绕不开的坑和排查思路5.1 完全没有应答先查上拉电阻和地址第一个典型故障是程序烧进去以后串口一直输出 SHT30 无应答的错误或者压根没有输出。这个问题的排查顺序应该是先看硬件再看地址最后查代码。硬件方面SHT30 模块如果没接上拉电阻I2C 总线就缺少默认高电平通信完全无法进行。买来的模块如果自带 I2C 上拉电阻板上能看到两个 4.7k 或 10k 的贴片电阻那这一步就省了。但你要注意上拉电阻接的是 3.3V 还是 5V如果模块是 3.3V 供电上拉电阻接到了 VCC那 VCC 接 3.3V 就没问题如果模块上电电压实际是 5VSHT30 虽然能承受但 I2C 电平变成了 5VSTC8A 的 GPIO 口如果设置为开漏模式并能承受 5V问题不大但最稳妥的还是让模块 VCC 接 3.3V。地址方面再强调一次SHT30 的 7 位地址是 0x44但 I2C 总线上写地址字节是 0x88、读地址字节是 0x89。如果你把 0x44 写到总线上SHT30 根本不会认这个地址。还有一种情况是 ADDR 引脚悬空后受到干扰地址在 0x44 和 0x45 之间跳变这时可以量一下 ADDR 引脚电平确保它稳定接到地。5.2 CRC 校验失败从时序和电气层面找根因CRC 校验失败的典型表现是串口能收到数据但程序里校验不通过或者偶尔成功偶尔失败。这里我要强调CRC 校验失败说明的不是“校验算法有问题”而是读回去的数据本身就有错误要么是数据在传输过程中翻转了要么是读取时序没对上导致字节错位。先用逻辑分析仪看 SCL 高低电平和 SDA 数据线上的波形。如果波形边沿非常缓、高电平幅度不够八成是上拉电阻太大或者供电电压偏低。杜邦线过长也会引入干扰先换成尽量短的线。软件方面检查读取代码里 ACK/NAK 的顺序前 5 个字节回 ACK最后一个字节回 NAK这个顺序错了最后一个字节就会偏移。如果你的 CRC 校验代码是用字位循环实现的仿真环境下确认多项式 0x31 和初始值 0xFF 没写错。一个快速的验证方法SHT30 数据手册里提供了一组已知的原始值和对应 CRC比如温度数据 0xBE 0xEFCRC 应该是 0x92。把这两个字节喂给校验函数如果算出来是 0x92说明校验函数是对的问题在通信链路。5.3 温湿度数据跳变别急着换传感器SHT30 的稳定性其实很好如果数据在串口助手上频繁跳动先检查工作环境传感器是不是离 STC8A 芯片太近单片机运行时芯片温度会比环境温度高好几度SHT30 如果紧贴着单片机读出来的温度会虚高且波动。实验时让传感器远离发热源或者用杜邦线拉出来悬空放置。供电纹波也是元凶之一。开发板如果用 USB 供电而 USB 口本身质量一般纹波会传导给 SHT30 模块。可以试试点几毫秒的电流纹波之后温湿度原始值是否稳定。SHT30 的内部 ADC 对电源噪声还是敏感的正常情况下呼吸吹气时数值变化很流畅如果数值像随机数一样乱跳就要怀疑供电和采样间隔。软件层面可以做滑动平均滤波。例程里每 500ms 采集一次把最近 5 次温度值与湿度值分别累加求平均这样输出曲线会平滑很多。但这种滤波只对随机噪声有效如果 SHT30 读数随时间漂移很大那是环境或供电问题滤波救不回来。5.4 串口乱码或者完全无输出从时钟和波特率入手串口乱码的排查思路很直接单片机的串口波特率和电脑端设置的波特率不一致。STC8A 如果没有把内部 IRC 频率设置成 11.0592MHz而是用了默认的 24MHz 或者别的频率那么同样的波特率初值算出来的实际波特率就会偏偏差超过 2% 之后就会乱码。碰到乱码先打开 STC-ISP重新设置内部 IRC 频率为 11.0592MHz再烧录一次。然后用 STC-ISP 的波特率计算器生成串口 1 的初始化代码替换原代码。这里需要注意如果你的开发板上带了外部晶振而且 STC-ISP 里设置的是外部晶振模式那系统时钟由外部晶振决定波特率初值要按照外部晶振频率来计算。不要混用。完全无输出的情况除了波特率问题还要检查串口 1 的引脚有没有被复用。STC8A 的串口 1 默认引脚是 P3.0RXD和 P3.1TXD如果你的代码里把 P3.1 配置为了推挽输出串口还是能工作的但如果 P3.1 被复用成了其他外设功能TXD 信号就出不来了。下载程序成功不代表串口一定没问题先用万用表量一下 P3.1 在空闲状态下是不是高电平如果一直是低电平说明引脚配置有问题。6. 从这套例程延伸出去还能怎么玩6.1 加一块 OLED 屏幕变成独立温湿度计串口显示温湿度只能说明通信链路没问题真正要做成一个能独立使用的设备还是得加显示。STC8A 驱动 SSD1306 或者 SSD1315 这类 0.96 寸 OLED 很成熟而且更关键的是 SHT30 和 OLED 都走 I2C可以在同一条总线上连接。SHT30 的地址是 0x44SSD1306 的 I2C 地址通常是 0x3C两者不冲突一条总线上能挂两个设备本文还有配套的精品资源点击获取