- #include "dht11.h"
- // DHT11 IO
- #define GPIO_DATA GPIO_PIN_3
- // 复位DHT11
- void DHT11_Rst(void)
- {
- DHT11_IO_OUT(); //SET OUTPUT
- gpio_bit_reset(GPIOA, GPIO_DATA); //拉低DQ
- sys_us_delay(20000); //拉低至少18ms
- gpio_bit_set(GPIOA, GPIO_DATA); //DQ=1
- sys_us_delay(30); //主机拉高20~40us
- }
- // 等待DHT11的回应
- // 返回1: 未检测到DHT11的存在
- // 返回0: 存在
- uint8_t DHT11_Check(void)
- {
- uint8_t retry=0;
- DHT11_IO_IN();//SET INPUT
- while (gpio_input_bit_get(GPIOA, GPIO_DATA)&&retry<100)//DHT11会拉低40~80us
- {
- retry++;
- sys_us_delay(1);
- };
- if(retry>=100)return 1;
- else retry=0;
- while (!gpio_input_bit_get(GPIOA, GPIO_DATA)&&retry<100)//DHT11拉低后会再次拉高40~80us
- {
- retry++;
- sys_us_delay(1);
- };
- if(retry>=100)return 1;
- return 0;
- }
- // 从DHT11读取一个位
- uint8_t DHT11_Read_Bit(void)
- {
- uint8_t retry=0;
- while(gpio_input_bit_get(GPIOA, GPIO_DATA)&&retry<100)//等待变为低电平
- {
- retry++;
- sys_us_delay(1);
- }
- retry=0;
- while(!gpio_input_bit_get(GPIOA, GPIO_DATA)&&retry<100)//等待变高电平
- {
- retry++;
- sys_us_delay(1);
- }
- sys_us_delay(40);//等待40us
- if(gpio_input_bit_get(GPIOA, GPIO_DATA))return 1;
- else return 0;
- }
- // 从DHT11读取一个字节
- uint8_t DHT11_Read_Byte(void)
- {
- uint8_t i,dat;
- dat=0;
- for (i=0;i<8;i++)
- {
- dat<<=1;
- dat|=DHT11_Read_Bit();
- }
- return dat;
- }
- // 从DHT11读取一次数据
- // temp: 温度值(范围:0~50°)
- // humi: 湿度值(范围:20%~90%)
- // 返回: 0, 正常; 1, 读取失败
- uint8_t DHT11_Read_Data(uint8_t *temp,uint8_t *humi)
- {
- uint8_t buf[5];
- uint8_t i;
- DHT11_Rst();
- if(DHT11_Check()==0)
- {
- for(i=0;i<5;i++)//读取40位数据
- {
- buf[i]=DHT11_Read_Byte();
- }
- if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
- {
- *humi=buf[0];
- *temp=buf[2];
- }
- }
- else return 1;
- return 0;
- }
- // 初始化DHT11, 同时检测DHT11的存在
- // 返回1: 不存在
- // 返回0: 存在
- uint8_t DHT11_Init(void)
- {
- rcu_periph_clock_enable(RCU_GPIOA);
- gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
- DHT11_Rst(); //复位DHT11
- return DHT11_Check();//等待DHT11的回应
- }
dht11.h
- #ifndef DHT11_H
- #define DHT11_H
- #include "gd32vw55x.h"
- #include "sys.h"
- // DHT11 IO
- #define GPIO_DATA GPIO_PIN_3
- #define DHT11_IO_IN() {gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_DATA);}
- #define DHT11_IO_OUT() {gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_DATA);}
- uint8_t DHT11_Init(void);
- uint8_t DHT11_Read_Data(uint8_t *temp,uint8_t *humi);
- uint8_t DHT11_Read_Byte(void);
- uint8_t DHT11_Read_Bit(void);
- uint8_t DHT11_Check(void);
- void DHT11_Rst(void);
- #endif
使用 MQTT 上报数据打开 MDK MQTT Demo 的 /main/mqtt_client_main.c,可以直接在这里编写代码(可以直接删除内容)
引入头文件和定义常量、全局变量
- #include <stdint.h>
- #include <stdio.h>
- #include "app_cfg.h"
- #include "gd32vw55x_platform.h"
- #include "wifi_management.h"
- #include "wifi_init.h"
- #include "lwip/apps/mqtt.h"
- #include "lwip/apps/mqtt5.h"
- #include "lwip/apps/mqtt_priv.h"
- #include "mqtt5_client_config.c"
- #include "oled.h"
- #include "dht11.h"
- #define SSID "SSID"
- #define PASSWORD "PASSWORD"
- #define SERVER_PORT 1883
- ip_addr_t sever_ip_addr = IPADDR4_INIT_BYTES(192,168,0,2);
- static char client_id[] = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- struct mqtt_connect_client_info_t client_info = {
- .client_id = client_id,
- .client_user = NULL,
- .client_pass = NULL,
- .keep_alive = 120,
- .will_topic = NULL,
- .will_topic = NULL,
- .will_qos = 0,
- .will_retain = 0
- };
- char* topic_pub = "dht11/topic";
- static mqtt_client_t *mqtt_client = NULL;
- int16_t connect_fail_reason = -1;
- uint8_t temp;
- uint8_t humi;
MQTT 任务相关函数
- struct mqtt_connect_client_info_t* get_client_param_data_get(void)
- {
- return &client_info;
- }
- // 断开并释放MQTT连接
- void mqtt_connect_free(void)
- {
- connect_fail_reason = -1;
- if (mqtt_client == NULL)
- return;
- mqtt5_disconnect(mqtt_client);
- mqtt5_param_delete(mqtt_client);
- mqtt_client_free(mqtt_client);
- mqtt_client = NULL;
- }
- // 断开连接或连接异常回调函数
- void mqtt_connect_callback(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
- {
- char *prefix = NULL;
- char *reason = NULL;
- if ((status == MQTT_CONNECT_ACCEPTED) ||
- (status == MQTT_CONNECT_REFUSED_PROTOCOL_VERSION)) {
- return;;
- }
- prefix = "MQTT: client will be closed, reason is ";
- switch (status) {
- case MQTT_CONNECT_DISCONNECTED:
- reason = "remote has closed connection";
- break;
- case MQTT_CONNECT_TIMEOUT:
- reason = "connect attempt to server timed out";
- break;
- default:
- reason = "others";
- break;
- }
- printf("%s%s, id is %d.\r\n", prefix, reason, status);
- }
- // 解析错误码
- void mqtt_fail_reason_display(mqtt_connect_return_res_t fail_reason)
- {
- char *prefix = "MQTT mqtt_client: connection refused reason is ";
- char *reason = NULL;
- switch(fail_reason) {
- case MQTT_CONNECTION_REFUSE_PROTOCOL:
- reason = "Bad protocol";
- break;
- case MQTT_CONNECTION_REFUSE_ID_REJECTED:
- reason = "ID rejected";
- break;
- case MQTT_CONNECTION_REFUSE_SERVER_UNAVAILABLE:
- reason = "Server unavailable";
- break;
- case MQTT_CONNECTION_REFUSE_BAD_USERNAME:
- reason = "Bad username or password";
- break;
- case MQTT_CONNECTION_REFUSE_NOT_AUTHORIZED:
- reason = "Not authorized";
- break;
- default:
- reason = "Unknown reason";
- break;
- }
- printf("%s%s, id is %d.\r\n", prefix, reason, fail_reason);
- return;
- }
- // 与服务器建立连接
- static int client_connect(void)
- {
- err_t ret = ERR_OK;
- uint32_t connect_time = 0;
- mqtt_client = mqtt_client_new();
- printf("MQTT: start link server...\r\n");
- if (mqtt5_param_cfg(mqtt_client)) {
- printf("MQTT: Configuration MQTT parameters failed, stop connection.\r\n");
- return -2;
- }
- connect_time = sys_current_time_get();
- ret = mqtt5_client_connect(mqtt_client, &sever_ip_addr, SERVER_PORT, mqtt_connect_callback, NULL, &client_info,
- &(mqtt_client->mqtt5_config->connect_property_info),
- &(mqtt_client->mqtt5_config->will_property_info));
- if (ret != ERR_OK) {
- printf("MQTT mqtt_client: connect to server failed.\r\n");
- return ret;
- }
- // 等待连接成功
- while (mqtt_client_is_connected(mqtt_client) == false) {
- // 超时
- if ((sys_current_time_get() - connect_time) > 5000) {
- printf("MQTT mqtt_client: connect to server timeout.\r\n");
- return -3;
- }
- // 异常
- if (connect_fail_reason == MQTT_CONNECTION_REFUSE_PROTOCOL) {
- mqtt5_disconnect(mqtt_client);
- mqtt5_param_delete(mqtt_client);
- printf("MQTT: The server does not support version 5.0, now switch to version 3.1.1.\r\n");
- connect_fail_reason = -1;
- break;
- } else if (connect_fail_reason > 0) {
- mqtt5_fail_reason_display((mqtt5_connect_return_res_t)connect_fail_reason);
- return connect_fail_reason;
- }
- sys_yield();
- }
- printf("MQTT: Successfully connected to server.\r\n");
- return 0;
- }
- // 发布回调函数
- void mqtt_pub_cb(void *arg, err_t status)
- {
- switch (status) {
- case ERR_OK:
- printf("topic publish success.\r\n");
- break;
- case ERR_TIMEOUT:
- printf("topic publish time out.\r\n");
- break;
- default:
- printf("topic publish failed.\r\n");
- break;
- }
- return;
- }
- // 发布
- static int client_publish(char *topic, char *context, uint16_t length)
- {
- err_t ret = ERR_OK;
- ret = mqtt5_msg_publish(mqtt_client, topic, context, length, 1, 1, mqtt_pub_cb, NULL, mqtt_client->mqtt5_config->publish_property_info,
- mqtt_client->mqtt5_config->server_resp_property_info.response_info);
- return ret;
- }
- // MQTT主函数
- static void mqtt_client_demo(void)
- {
- if (client_connect() != 0) {
- printf("MQTT connect server failed.\r\n");
- goto exit;
- }
- while(1) {
- sys_msleep(5000);
- char context[256] = {'\0'};
- DHT11_Read_Data(&temp,&humi);
- OLED_ShowNum(64, 6, temp, 2, 16, 1);
- OLED_ShowNum(64, 26, humi, 2, 16, 1);
- OLED_Refresh();
- int len = snprintf(context, sizeof(context), "{"temp": %d, "humi": %d}", temp, humi);
- if(client_publish(topic_pub, context, len) == ERR_OK) {
- printf("topic: %s\r\npayload: %s\r\n", topic_pub, context);
- }
- }
- exit:
- printf("MQTT: close mqtt connection.\r\n");
- mqtt_connect_free();
- return;
- }
- // 任务函数
- static void mqtt_client_task(void *param)
- {
- int status = 0;
- char *ssid = SSID;
- char *password = PASSWORD;
- struct mac_scan_result candidate;
- if (ssid == NULL) {
- printf("ssid can not be NULL!\r\n");
- goto exit;
- }
- /*
- * 1. Start Wi-Fi scan
- */
- printf("Start Wi-Fi scan.\r\n");
- status = wifi_management_scan(1, ssid);
- if (status != 0) {
- printf("Wi-Fi scan failed.\r\n");
- goto exit;
- }
- sys_memset(&candidate, 0, sizeof(struct mac_scan_result));
- status = wifi_netlink_candidate_ap_find(WIFI_VIF_INDEX_DEFAULT, NULL, ssid, &candidate);
- if (status != 0) {
- goto exit;
- }
- /*
- * 2. Start Wi-Fi connection
- */
- printf("Start Wi-Fi connection.\r\n");
- if (wifi_management_connect(ssid, password, 1) != 0) {
- printf("Wi-Fi connection failed\r\n");
- goto exit;
- }
- /*
- * 3. Start MQTT client
- */
- printf("Start MQTT client.\r\n");
- mqtt_client_demo();
- /*
- * 4. Stop Wi-Fi connection
- */
- printf("Stop Wi-Fi connection.\r\n");
- wifi_management_disconnect();
- exit:
- printf("The test has ended.\r\n");
- sys_task_delete(NULL);
- }
主函数
- int main(void)
- {
- platform_init();
- // 初始化 OLED
- OLED_Init();
- OLED_ColorTurn(0);
- OLED_DisplayTurn(0);
- OLED_ShowString(6, 6, (uint8_t *)"Temp:", 16, 1);
- OLED_ShowString(6, 26, (uint8_t *)"Humi:", 16, 1);
- OLED_Refresh();
- if (wifi_init()) {
- printf("wifi init failed.\r\n");
- }
- while(DHT11_Init())
- {
- printf("DHT11 Error \r\n");
- sys_us_delay(1000000);
- }
- sys_task_create_dynamic((const uint8_t *)"MQTT Client", 4096, OS_TASK_PRIORITY(0), mqtt_client_task, NULL);
- sys_os_start();
- for ( ; ; );
- }
烧录程序使用 Type-C 数据线将 GD32VW553-IoT V2 开发板连接到电脑,拨动拨码开关“1”到“ON”侧,按下按钮 K1 进入下载模式
打开 GD32 All In One Programmer 软件,按照下图配置后即可直接烧录
GD32 All In One Programmer 中勾选 Jump to run the App program 烧录程序后即可自动运行
使用 MQTT 客户端订阅消息获取数据