我的第一个 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...

相关推荐
青衫嵌入式2 小时前
FreeRTOS中断优先级配置不对也会HardFault?这次用一个血的教训讲明白
嵌入式
论迹复利4 小时前
多平台移植 BTBLE Stack 的思路与踩坑实战——从 Ceva IP 到厂商适配层的迁移指南
嵌入式硬件·物联网·架构
XTIOT6666 小时前
零部件 DPM 码扫码枪生产厂家:工业 DPM 设备多工位组网与 MES/ERP 数据集成方案
网络·单片机·嵌入式硬件·物联网·计算机视觉
JERRY. LIU7 小时前
VS CODE进行NRF CONNECT项目开发出现变量无法链接跳转问题及解决方法
数据库·嵌入式硬件·物联网·iot·嵌入式实时数据库
久爱物联网20 小时前
个人站点(博客)开发案例 - 功能齐全,在线客服-即时通讯-物联网控制、广告位管理、按钮级权限控制
物联网·个人博客·即时通讯在线客服·物联网控制·博客发布系统·新闻发布系统
兆龙电子单片机设计21 小时前
【STM32项目开源】STM32单片机语音分类垃圾桶-蓝牙APP
stm32·单片机·嵌入式硬件·物联网·开源·自动化·毕业设计
零涂毕业设计1 天前
毕业设计模块开发-OLED显示屏(IIC协议0.96寸)STM32 ESP32 FPGA Linux驱动免费分享
linux·stm32·单片机·嵌入式·esp32·fpga·oled
厦门辰迈智慧科技1 天前
管网遥测终端机赋能城市安全的核心价值
物联网·遥测终端机·管网遥测终端机·排水管网遥测终端·管网遥测终端
七仔啊1 天前
modbus快速入门
物联网
wdfk_prog1 天前
嵌入式面试真题第 13 题:单硬件 Timer 下的高精度多路软件定时器架构设计
c语言·开发语言·面试·职场和发展·嵌入式