一、准备
接线参考了文章(树莓派接温湿度传感器显示温度湿度):

**DHT11:**接收温湿度
MQTT 部分 :在 main 函数中初始化 MQTT 客户端,并在每次成功读取到温度后,将数据打包成 JSON 格式(如 {"temp": 28, "humi": 60})发送到 EMQX。
LED 逻辑:保留了温度超过 30 度闪烁的功能。
新建一个文件,例如 main.c,并将以下代码完整复制进去。
#include <wiringPi.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h> // 用于 sleep
#include <stdlib.h>
// 引入 Paho MQTT 库头文件
#include "MQTTClient.h"
// --- 硬件引脚定义 ---
#define DHT_PIN 7
#define LED_PIN 0
#define TEMP_THRESHOLD 30 // 报警温度阈值
// --- MQTT 配置 ---
#define ADDRESS "tcp://localhost:1883" // 如果EMQX在本地,用localhost;如果是远程,填IP
#define CLIENTID "RPI_DHT11_Sensor"
#define TOPIC "sensor/dht11_data"
#define QOS 1
#define TIMEOUT 10000L
// --- DHT11 读取函数 ---
int readDHT11(int *temperature, int *humidity) {
uint8_t data[5] = {0}; // DHT11 返回 5 字节数据
uint8_t lastState = HIGH;
uint8_t counter = 0;
uint8_t j = 0;
pinMode(DHT_PIN, OUTPUT);
digitalWrite(DHT_PIN, LOW);
delay(18);
digitalWrite(DHT_PIN, HIGH);
delayMicroseconds(40);
pinMode(DHT_PIN, INPUT);
// 等待响应信号
for(int i=0; i<85; i++){
counter = 0;
while(digitalRead(DHT_PIN) == lastState){
counter++;
delayMicroseconds(1);
if(counter == 255) break;
}
lastState = digitalRead(DHT_PIN);
if(counter == 255) break;
// 解析数据位 (从第4个脉冲开始是数据)
if((i >= 4) && (i % 2 == 0)){
data[j/8] <<= 1;
if(counter > 50){
data[j/8] |= 1;
}
j++;
}
}
// 校验数据完整性
if((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xff))){
*humidity = data[0];
*temperature = data[2];
return 0; // 成功
} else {
return -1; // 失败
}
}
// --- LED 闪烁函数 ---
void blink_led(int times, int delay_ms){
for(int i=0; i<times; i++){
digitalWrite(LED_PIN, HIGH);
delay(delay_ms);
digitalWrite(LED_PIN, LOW);
delay(delay_ms);
}
}
int main(void) {
int temperature = 0;
int humidity = 0;
// 1. 初始化 WiringPi
if(wiringPiSetup() == -1){
printf("WiringPi Setup Error!\n");
return -1;
}
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// 2. 初始化 MQTT 客户端
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
printf("Connecting to EMQX at %s...\n", ADDRESS);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Connected to EMQX successfully.\n");
// 3. 主循环:读取传感器 -> 发送 MQTT
while(1) {
if(readDHT11(&temperature, &humidity) == 0) {
printf("Read Success -> Temp: %d C, Humi: %d %%\n", temperature, humidity);
// LED 报警逻辑
if(temperature >= TEMP_THRESHOLD){
blink_led(3, 300);
}
// --- MQTT 发送逻辑 ---
char payload[100];
// 将数据格式化为 JSON 字符串
sprintf(payload, "{\"temperature\": %d, \"humidity\": %d}", temperature, humidity);
pubmsg.payload = payload;
pubmsg.payloadlen = (int)strlen(payload);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Message sent to topic %s: %s\n", TOPIC, payload);
// 等待消息发送完成
MQTTClient_waitForCompletion(client, token, TIMEOUT);
} else {
printf("Sensor read failed, retrying...\n");
}
// 间隔 2 秒
sleep(2);
}
// 断开连接并清理
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return 0;
}
这里我是用vs code 远程连接的,这样方便看,好修改,不用在nano里黑灯瞎火的写了。如果有需要的小伙伴,我是看了这篇 VS Code远程连接树莓派超详细教程(图文),写得特别好,而且操作简单,很好配置,大家可以自行选择。

二、编译代码
由于使用了 wiringPi 和 paho-mqtt-c 两个库,编译时需要同时链接它们。
在终端执行以下命令(假设你的代码文件名为 main.c)
bash
gcc main.c -o dht_mqtt -lwiringPi -lpaho-mqtt3c
-lwiringPi:链接 GPIO 控制库。-lpaho-mqtt3c:链接 Paho MQTT C 客户端库。

这里提个醒,因为我是重新写了镜像,所有很多东西来不及配置,都忘记了,所以只能边写边添加,要什么就加什么。这里我报错是因为没有配置Paho MQTT C 库。
所以如果也有这种情况的小伙伴,就输入:
bash
sudo apt-get install libpaho-mqtt-dev
添加即可,然后记得编译哦。
三、运行程序
bash
sudo ./dht_mqtt
四、验证结果

这里我是用mqttx工具,比较方便的看到数据情况。
也可以使用EMQX:
打开浏览器访问你的 EMQX 管理后台(通常是
http://树莓派IP:18083)。进入 WebSocket 工具页面。
订阅主题
sensor/dht11_data。应该能实时看到树莓派发送过来的 JSON 数据。
这里只是使用了简单的温湿度传感器,大家可以自行添加更加复杂的传感器,编写代码,制作项目。( •̀ ω •́ )y