我的第一个 TinyGo 项目:ESP32-C3 + DHT11 + SSD1306

我的第一个 TinyGo 项目:ESP32-C3 + DHT11 + SSD1306

前言

最近开始学习 TinyGo,这是我的第一个 TinyGo 嵌入式项目。作为一个 Go 语言爱好者,能用熟悉的语法来编写嵌入式程序,这种感觉非常奇妙。项目已开源在 Gitee 上:gitee.com/magic_drago...

为什么选择 TinyGo?

TinyGo 是 Go 语言的一个编译器子集,专门针对微控制器和 WebAssembly 等资源受限环境。相比 C/C++,它有这些吸引我的地方:

  • 语法熟悉 --- 如果你已经会 Go,上手几乎零成本
  • 垃圾回收 --- 不用手动管理内存,嵌入式开发也能享受 GC 的便利
  • Goroutine --- 虽然在 MCU 上用得不多,但并发模型依然可用
  • 丰富的驱动库 --- tinygo.org/x/drivers 提供了大量常见传感器的驱动

项目简介

这个项目使用 ESP32-C3 开发板,搭配 DHT11 温湿度传感器和 SSD1306 OLED 显示屏,实现了一个简单的环境监测小装置:

  • 每 2 秒读取一次 DHT11 的温度和湿度数据
  • 将温湿度及 LED 状态实时显示在 OLED 屏幕上
  • 通过按钮中断控制 LED 开关,带软件消抖

硬件连接

外设 ESP32-C3 引脚 说明
LED GPIO2 通过 330Ω 电阻接 LED 正极
按钮 GPIO3 一端接 GPIO3,另一端接 GND
DHT11 DAT GPIO4 DHT11 模块的数据引脚
OLED SDA GPIO5 I2C 数据线
OLED SCL GPIO6 I2C 时钟线

核心代码解读

1. I2C 总线与 OLED 初始化

go 复制代码
i2c.Configure(machine.I2CConfig{
    SCL:       machine.GPIO6,
    SDA:       machine.GPIO5,
    Frequency: 400_000,
})

disp = ssd1306.NewI2C(i2c)
disp.Configure(ssd1306.Config{
    Width:   128,
    Height:  64,
    Address: 0x3C,
})

SSD1306 通过 I2C 总线通信,配置为 400kHz 快速模式。128x64 分辨率的屏幕使用 0x3C 地址。

2. DHT11 传感器读取

go 复制代码
dhtSensor = dht.New(machine.GPIO4, dht.DHT11)
dhtSensor.Configure(dht.UpdatePolicy{
    UpdateTime:          2 * time.Second,
    UpdateAutomatically: true,
})

DHT11 数据手册要求最小读取间隔为 2 秒,设置 UpdateAutomatically 后调用 TemperatureFloat / HumidityFloat 会自动触发读取,非常方便。

3. 按钮中断与消抖

go 复制代码
button.SetInterrupt(machine.PinFalling, func(p machine.Pin) {
    if time.Since(lastPress) < 50*time.Millisecond {
        return
    }
    lastPress = time.Now()
    led.Set(!led.Get())
})

机械按钮按下时触点会弹跳,产生多次快速电平变化。通过记录上次触发时间,忽略 50ms 内的重复触发,实现软件消抖。

4. 超级循环模式

go 复制代码
for {
    err := dhtSensor.ReadMeasurements()
    if err != nil {
        show("DHT11 Error", "", "")
    } else {
        temp, _ := dhtSensor.TemperatureFloat(dht.C)
        hum, _ := dhtSensor.HumidityFloat()
        show(
            fmt.Sprintf("T:%.1fC", temp),
            fmt.Sprintf("H:%.1f%%", hum),
            fmt.Sprintf("LED:%v", led.Get()),
        )
    }
    time.Sleep(2 * time.Second)
}

嵌入式程序的核心结构:无限循环中不断读取传感器、处理数据、刷新显示。注意 main 函数不能退出,否则设备会重启。

踩坑记录

  1. DHT11 读取间隔 --- 刚开始频繁读取导致数据全是错误,后来才注意到数据手册要求至少间隔 2 秒
  2. OLED 地址 --- 128x64 的屏幕地址是 0x3C,128x32 是 0x3D,搞混了屏幕不会亮
  3. 按钮消抖 --- 不加消抖逻辑的话,按一次按钮 LED 会翻转多次,50ms 的消抖阈值实测效果不错
  4. main 不能退出 --- 嵌入式程序的 main 函数必须保持运行,退出后芯片会自动重启

编译与烧录

bash 复制代码
# 编译并烧录到 ESP32-C3
tinygo flash -target=esp32c3 .

# 仅编译生成固件
tinygo build -target=esp32c3 -o firmware.bin .

总结

作为第一个 TinyGo 项目,虽然功能简单,但覆盖了嵌入式开发的几个核心知识点:GPIO 控制、I2C 通信、传感器驱动、中断处理。TinyGo 的开发体验确实不错,Go 的简洁语法让嵌入式编程也变得优雅起来。

接下来打算尝试:

  • 接入 WiFi,把温湿度数据上报到服务器
  • 尝试 MQTT 协议
  • 用 Goroutine 实现更复杂的并发逻辑

如果你也对 TinyGo 感兴趣,欢迎交流!

项目地址 :gitee.com/magic_drago...

相关推荐
voipmaker6 小时前
GB28181 对接踩坑实录:注册不上、目录不全、流卡顿,一次说清(附 2022 版变更清单)
物联网·音视频·实时音视频·信息与通信·iot·gb28181·国标gb28181
Chery11407 小时前
高速ADC与精密DAC怎么选?DP9230D与DP8532D应用解析
嵌入式硬件·物联网·射频工程
小李不想当小白10 小时前
SPI通信外设与W25Q64 (硬件SPI)(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
Zwawa14 小时前
从 printf 到曲线:把数据送上 VOFA+
c语言·单片机·嵌入式
TDengine (老段)15 小时前
TDengine IDMP 十大实用功能(3)
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
实验室管理云平台15 小时前
面向高职院校实训场景:实训实验室管理平台整体方案分享
大数据·科技·物联网·自动化
wtblszn16 小时前
热水机组物联网远程监控系统方案
物联网
悟天特斯17 小时前
安防一体化:从“各管各的“到“全局联动“
java·大数据·网络·人工智能·物联网
河北乐讯通物联网服务商17 小时前
工业自动控制系统到底是个什么东西?从 PLC 到物联网卡的演进
物联网·物联网卡·工业自动控制系统装置制造
stefan124017 小时前
中越跨境生鲜冷链的物联网实践:四点测温、弱网上报与数据闭环
物联网·架构设计