[研电赛技术支持] GD32+ESP32物联网实战:MQTT通信方案

[复制链接]
146|0
Zuocidian 发表于 2025-11-6 15:22 | 显示全部楼层 |阅读模式
以下是基于GD32F103ZE和ESP32-C3的MQTT案例代码,实现物联网数据传输功能:

系统架构和配置
#include "gd32f10x.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// ESP32-C3连接定义
#define ESP32_UART            USART2
#define ESP32_UART_CLK        RCU_USART2
#define ESP32_UART_TX_PIN     GPIO_PIN_2  // PA2
#define ESP32_UART_RX_PIN     GPIO_PIN_3  // PA3
#define ESP32_UART_GPIO_PORT  GPIOA
#define ESP32_UART_GPIO_CLK   RCU_GPIOA

#define ESP32_EN_PIN          GPIO_PIN_4  // PE4
#define ESP32_EN_GPIO_PORT    GPIOE
#define ESP32_EN_GPIO_CLK     RCU_GPIOE

// MQTT配置
#define MQTT_BROKER           "mqtt.broker.com"  // 替换为实际MQTT服务器
#define MQTT_PORT             "1883"
#define MQTT_CLIENT_ID        "GD32_Client_001"
#define MQTT_USERNAME         "user"             // 如果需要认证
#define MQTT_PASSWORD         "pass"

// 主题定义
#define TOPIC_TEMPERATURE     "sensor/temperature"
#define TOPIC_HUMIDITY        "sensor/humidity"
#define TOPIC_LED_CONTROL     "device/led/control"
#define TOPIC_STATUS          "device/status"

// 系统状态
typedef enum {
    MQTT_DISCONNECTED = 0,
    MQTT_CONNECTING,
    MQTT_CONNECTED,
    MQTT_ERROR
} mqtt_state_t;

volatile mqtt_state_t mqtt_state = MQTT_DISCONNECTED;

// 数据缓冲区
#define MQTT_BUFFER_SIZE 256
uint8_t mqtt_rx_buffer[MQTT_BUFFER_SIZE];
uint8_t mqtt_rx_index = 0;
volatile uint8_t mqtt_data_ready = 0;

// 系统滴答计时
volatile uint32_t system_tick = 0;

// 传感器数据
typedef struct {
    float temperature;
    float humidity;
    uint8_t led_state;
} sensor_data_t;

sensor_data_t sensor_data = {0};




系统初始化
// 系统时钟配置
void system_clock_config(void)
{
    rcu_deinit();
    rcu_pll_config(RCU_PLLSRC_HXTAL, RCU_PLL_MUL9);
    rcu_osc_on(RCU_HXTAL);
    rcu_osc_ready_int_config(RCU_HXTAL, ENABLE);

    rcu_pll_enable();
    while(rcu_flag_get(RCU_FLAG_PLLSTB) == RESET);

    rcu_system_clock_source_config(RCU_CKSYSSRC_PLL);
    while(rcu_system_clock_source_get() != RCU_SCSS_PLL);

    SystemCoreClock = 72000000;
}

// GPIO初始化
void gpio_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOE);
    rcu_periph_clock_enable(RCU_AF);

    // ESP32使能引脚
    gpio_init(ESP32_EN_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, ESP32_EN_PIN);

    // 默认禁用ESP32
    GPIO_BC(ESP32_EN_GPIO_PORT) = ESP32_EN_PIN;

    // LED指示灯
    rcu_periph_clock_enable(RCU_GPIOC);
    gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
}

// 系统滴答定时器
void systick_config(void)
{
    if(SysTick_Config(SystemCoreClock / 1000)) {
        while(1);
    }
}

void SysTick_Handler(void)
{
    system_tick++;
}

uint32_t get_tick_count(void)
{
    return system_tick;
}

// 延时函数
void delay_ms(uint32_t ms)
{
    uint32_t start_tick = system_tick;
    while((system_tick - start_tick) < ms);
}


ESP32-C3 MQTT驱动
// ESP32控制函数
void esp32_enable(uint8_t enable)
{
    if(enable) {
        GPIO_BOP(ESP32_EN_GPIO_PORT) = ESP32_EN_PIN;  // 使能
        delay_ms(1000); // 等待ESP32启动
        printf("ESP32 enabled\r\n");
    } else {
        GPIO_BC(ESP32_EN_GPIO_PORT) = ESP32_EN_PIN;   // 禁用
        printf("ESP32 disabled\r\n");
    }
}

// UART初始化
void esp32_uart_config(void)
{
    rcu_periph_clock_enable(ESP32_UART_CLK);
    rcu_periph_clock_enable(ESP32_UART_GPIO_CLK);

    // 配置UART引脚
    gpio_init(ESP32_UART_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, ESP32_UART_TX_PIN);
    gpio_init(ESP32_UART_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, ESP32_UART_RX_PIN);

    // 配置UART
    usart_deinit(ESP32_UART);
    usart_baudrate_set(ESP32_UART, 115200U);
    usart_word_length_set(ESP32_UART, USART_WL_8BIT);
    usart_stop_bit_set(ESP32_UART, USART_STB_1BIT);
    usart_parity_config(ESP32_UART, USART_PM_NONE);
    usart_hardware_flow_rts_config(ESP32_UART, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(ESP32_UART, USART_CTS_DISABLE);
    usart_receive_config(ESP32_UART, USART_RECEIVE_ENABLE);
    usart_transmit_config(ESP32_UART, USART_TRANSMIT_ENABLE);
    usart_enable(ESP32_UART);

    // 使能接收中断
    usart_interrupt_enable(ESP32_UART, USART_INT_RBNE);
    nvic_irq_enable(USART2_IRQn, 1, 0);
}

// UART发送函数
void esp32_send_data(uint8_t *data, uint16_t len)
{
    for(uint16_t i = 0; i < len; i++) {
        usart_data_transmit(ESP32_UART, data);
        while(usart_flag_get(ESP32_UART, USART_FLAG_TBE) == RESET);
    }
}

void esp32_send_string(const char *str)
{
    esp32_send_data((uint8_t*)str, strlen(str));
}

// UART中断服务函数
void USART2_IRQHandler(void)
{
    if(usart_interrupt_flag_get(ESP32_UART, USART_INT_FLAG_RBNE) != RESET) {
        uint8_t data = usart_data_receive(ESP32_UART);

        // 处理接收数据
        if(data == '\n') {
            if(mqtt_rx_index > 0) {
                mqtt_rx_buffer[mqtt_rx_index] = '\0';
                mqtt_data_ready = 1;
                mqtt_rx_index = 0;
            }
        } else if(mqtt_rx_index < MQTT_BUFFER_SIZE - 1) {
            mqtt_rx_buffer[mqtt_rx_index++] = data;
        }
    }
}



Wi-Fi连接管理
// Wi-Fi配置
typedef struct {
    char ssid[32];
    char password[64];
} wifi_config_t;

wifi_config_t wifi_config = {
    "Your_WiFi_SSID",    // 替换为实际Wi-Fi名称
    "Your_WiFi_Password" // 替换为实际Wi-Fi密码
};

// AT命令处理
typedef enum {
    AT_OK = 0,
    AT_ERROR,
    AT_TIMEOUT
} at_status_t;

at_status_t esp32_send_at_command(const char *cmd, const char *expected_response, uint32_t timeout)
{
    uint32_t start_time = get_tick_count();

    printf("AT Command: %s\r\n", cmd);

    // 清空接收缓冲区
    mqtt_rx_index = 0;
    mqtt_data_ready = 0;

    // 发送AT命令
    esp32_send_string(cmd);
    esp32_send_string("\r\n");

    // 等待响应
    while((get_tick_count() - start_time) < timeout) {
        if(mqtt_data_ready) {
            mqtt_data_ready = 0;
            printf("AT Response: %s\r\n", mqtt_rx_buffer);

            // 检查是否包含预期响应
            if(strstr((char*)mqtt_rx_buffer, expected_response) != NULL) {
                return AT_OK;
            }

            // 检查错误响应
            if(strstr((char*)mqtt_rx_buffer, "ERROR") != NULL) {
                return AT_ERROR;
            }
        }
        delay_ms(10);
    }

    printf("AT Timeout\r\n");
    return AT_TIMEOUT;
}

// Wi-Fi连接
at_status_t esp32_wifi_connect(void)
{
    printf("Connecting to Wi-Fi...\r\n");

    // 设置Wi-Fi模式
    if(esp32_send_at_command("AT+CWMODE=1", "OK", 3000) != AT_OK) {
        return AT_ERROR;
    }

    // 连接Wi-Fi
    char wifi_cmd[128];
    snprintf(wifi_cmd, sizeof(wifi_cmd), "AT+CWJAP=\"%s\",\"%s\"",
             wifi_config.ssid, wifi_config.password);

    if(esp32_send_at_command(wifi_cmd, "WIFI GOT IP", 15000) != AT_OK) {
        return AT_ERROR;
    }

    printf("Wi-Fi connected successfully\r\n");
    return AT_OK;
}

// 获取IP地址
at_status_t esp32_get_ip_address(char *ip_buffer, uint32_t buffer_size)
{
    mqtt_rx_index = 0;
    mqtt_data_ready = 0;

    esp32_send_string("AT+CIFSR\r\n");

    uint32_t start_time = get_tick_count();
    while((get_tick_count() - start_time) < 5000) {
        if(mqtt_data_ready) {
            // 解析IP地址 (示例响应: +CIFSR:STAIP,"192.168.1.100")
            char *ip_start = strstr((char*)mqtt_rx_buffer, "STAIP,\"");
            if(ip_start) {
                ip_start += 7; // 跳过 "STAIP,\""
                char *ip_end = strchr(ip_start, '\"');
                if(ip_end) {
                    uint32_t ip_len = ip_end - ip_start;
                    if(ip_len < buffer_size) {
                        strncpy(ip_buffer, ip_start, ip_len);
                        ip_buffer[ip_len] = '\0';
                        return AT_OK;
                    }
                }
            }
            mqtt_data_ready = 0;
        }
        delay_ms(10);
    }

    return AT_TIMEOUT;
}



MQTT客户端实现
// MQTT连接
at_status_t esp32_mqtt_connect(void)
{
    printf("Connecting to MQTT broker...\r\n");

    // 设置MQTT版本
    if(esp32_send_at_command("AT+MQTTCLEAN=1", "OK", 3000) != AT_OK) {
        return AT_ERROR;
    }

    // 配置MQTT服务器
    char mqtt_cmd[256];
    snprintf(mqtt_cmd, sizeof(mqtt_cmd),
             "AT+MQTTCONN=\"%s\",%s,\"%s\",0,0,\"%s\",\"%s\"",
             MQTT_BROKER, MQTT_PORT, MQTT_CLIENT_ID,
             MQTT_USERNAME, MQTT_PASSWORD);

    if(esp32_send_at_command(mqtt_cmd, "+MQTTCONN:0,0", 10000) != AT_OK) {
        return AT_ERROR;
    }

    mqtt_state = MQTT_CONNECTED;
    printf("MQTT connected successfully\r\n");

    // 订阅主题
    esp32_mqtt_subscribe(TOPIC_LED_CONTROL);

    return AT_OK;
}

// MQTT发布
at_status_t esp32_mqtt_publish(const char *topic, const char *message, uint8_t qos)
{
    char publish_cmd[256];
    snprintf(publish_cmd, sizeof(publish_cmd),
             "AT+MQTTPUB=\"%s\",\"%s\",%d,0", topic, message, qos);

    return esp32_send_at_command(publish_cmd, "OK", 5000);
}

// MQTT订阅
at_status_t esp32_mqtt_subscribe(const char *topic)
{
    char subscribe_cmd[128];
    snprintf(subscribe_cmd, sizeof(subscribe_cmd),
             "AT+MQTTSUB=\"%s\",1", topic);

    at_status_t status = esp32_send_at_command(subscribe_cmd, "OK", 5000);
    if(status == AT_OK) {
        printf("Subscribed to topic: %s\r\n", topic);
    }
    return status;
}

// MQTT取消订阅
at_status_t esp32_mqtt_unsubscribe(const char *topic)
{
    char unsubscribe_cmd[128];
    snprintf(unsubscribe_cmd, sizeof(unsubscribe_cmd),
             "AT+MQTTUNSUB=\"%s\"", topic);

    return esp32_send_at_command(unsubscribe_cmd, "OK", 5000);
}

// 处理MQTT接收消息
void process_mqtt_message(const char *message)
{
    printf("MQTT Message: %s\r\n", message);

    // 解析消息格式: +MQTTSUBRECV:0,"topic","message"
    char *topic_start = strchr(message, '\"');
    if(topic_start) {
        char *topic_end = strchr(topic_start + 1, '\"');
        if(topic_end) {
            char topic[64];
            uint32_t topic_len = topic_end - topic_start - 1;
            strncpy(topic, topic_start + 1, topic_len);
            topic[topic_len] = '\0';

            char *msg_start = strchr(topic_end + 1, '\"');
            if(msg_start) {
                char *msg_end = strchr(msg_start + 1, '\"');
                if(msg_end) {
                    char msg[128];
                    uint32_t msg_len = msg_end - msg_start - 1;
                    strncpy(msg, msg_start + 1, msg_len);
                    msg[msg_len] = '\0';

                    handle_mqtt_command(topic, msg);
                }
            }
        }
    }
}

// 处理MQTT命令
void handle_mqtt_command(const char *topic, const char *message)
{
    printf("Command - Topic: %s, Message: %s\r\n", topic, message);

    if(strcmp(topic, TOPIC_LED_CONTROL) == 0) {
        // 控制LED
        if(strcmp(message, "ON") == 0) {
            GPIO_BC(GPIOC) = GPIO_PIN_13; // LED亮
            sensor_data.led_state = 1;
            printf("LED turned ON\r\n");
        } else if(strcmp(message, "OFF") == 0) {
            GPIO_BOP(GPIOC) = GPIO_PIN_13; // LED灭
            sensor_data.led_state = 0;
            printf("LED turned OFF\r\n");
        }

        // 发布状态更新
        char status_msg[32];
        snprintf(status_msg, sizeof(status_msg), "{\"led\":%d}", sensor_data.led_state);
        esp32_mqtt_publish(TOPIC_STATUS, status_msg, 0);
    }
}



传感器数据采集和发布
// 模拟传感器数据采集
void read_sensor_data(void)
{
    // 这里可以替换为真实的传感器读取代码
    // 模拟温度数据 (20.0 - 30.0)
    sensor_data.temperature = 20.0 + (rand() % 100) / 10.0;

    // 模拟湿度数据 (40.0 - 80.0)
    sensor_data.humidity = 40.0 + (rand() % 400) / 10.0;
}

// 发布传感器数据
void publish_sensor_data(void)
{
    char temp_msg[64], humid_msg[64];

    // 发布温度数据
    snprintf(temp_msg, sizeof(temp_msg),
             "{\"device\":\"%s\",\"temperature\":%.1f,\"timestamp\":%lu}",
             MQTT_CLIENT_ID, sensor_data.temperature, get_tick_count() / 1000);
    esp32_mqtt_publish(TOPIC_TEMPERATURE, temp_msg, 0);

    // 发布湿度数据
    snprintf(humid_msg, sizeof(humid_msg),
             "{\"device\":\"%s\",\"humidity\":%.1f,\"timestamp\":%lu}",
             MQTT_CLIENT_ID, sensor_data.humidity, get_tick_count() / 1000);
    esp32_mqtt_publish(TOPIC_HUMIDITY, humid_msg, 0);

    printf("Sensor data published - Temp: %.1fC, Humid: %.1f%%\r\n",
           sensor_data.temperature, sensor_data.humidity);
}

// 网络状态监测
at_status_t check_network_connection(void)
{
    return esp32_send_at_command("AT+CIPSTATUS", "STATUS:3", 3000); // STATUS:3表示已连接
}


主应用程序
// 调试串口初始化 (USART0用于printf输出)
void debug_uart_config(void)
{
    rcu_periph_clock_enable(RCU_USART0);
    rcu_periph_clock_enable(RCU_GPIOA);

    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);  // TX
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // RX

    usart_deinit(USART0);
    usart_baudrate_set(USART0, 115200U);
    usart_word_length_set(USART0, USART_WL_8BIT);
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);
}

// 重定向printf到串口
int _put_char(int ch)
{
    usart_data_transmit(USART0, (uint8_t)ch);
    while(usart_flag_get(USART0, USART_FLAG_TBE) == RESET);
    return ch;
}

// 主函数
int main(void)
{
    // 系统初始化
    system_clock_config();
    systick_config();
    gpio_config();
    debug_uart_config();

    printf("\r\nGD32F103ZE MQTT IoT Demo Started\r\n");
    printf("System Clock: %lu Hz\r\n", SystemCoreClock);

    // 初始化ESP32
    esp32_uart_config();
    esp32_enable(1);

    // 等待ESP32启动
    delay_ms(3000);

    // 测试ESP32通信
    if(esp32_send_at_command("AT", "OK", 3000) != AT_OK) {
        printf("ESP32 not responding! Check connection.\r\n");
        while(1);
    }

    printf("ESP32 initialized successfully\r\n");

    // 连接Wi-Fi
    if(esp32_wifi_connect() != AT_OK) {
        printf("Wi-Fi connection failed!\r\n");
        while(1);
    }

    // 显示IP地址
    char ip_address[16];
    if(esp32_get_ip_address(ip_address, sizeof(ip_address)) == AT_OK) {
        printf("IP Address: %s\r\n", ip_address);
    }

    // 连接MQTT
    if(esp32_mqtt_connect() != AT_OK) {
        printf("MQTT connection failed!\r\n");
        while(1);
    }

    printf("MQTT IoT System Ready!\r\n");

    // 主循环
    uint32_t last_sensor_publish = 0;
    uint32_t last_network_check = 0;
    uint32_t connection_retries = 0;

    while(1) {
        uint32_t current_time = get_tick_count();

        // 处理接收到的MQTT消息
        if(mqtt_data_ready) {
            process_mqtt_message((char*)mqtt_rx_buffer);
            mqtt_data_ready = 0;
        }

        // 定期发布传感器数据 (每10秒)
        if((current_time - last_sensor_publish) > 10000) {
            last_sensor_publish = current_time;
            read_sensor_data();
            publish_sensor_data();
        }

        // 定期检查网络连接 (每30秒)
        if((current_time - last_network_check) > 30000) {
            last_network_check = current_time;

            if(check_network_connection() != AT_OK) {
                printf("Network connection lost! Reconnecting...\r\n");
                mqtt_state = MQTT_DISCONNECTED;
                connection_retries++;

                // 尝试重新连接
                if(esp32_wifi_connect() == AT_OK &&
                   esp32_mqtt_connect() == AT_OK) {
                    printf("Reconnected successfully\r\n");
                    connection_retries = 0;
                } else if(connection_retries > 3) {
                    printf("Multiple reconnection failures, resetting ESP32...\r\n");
                    esp32_enable(0);
                    delay_ms(1000);
                    esp32_enable(1);
                    delay_ms(5000);
                    connection_retries = 0;
                }
            }
        }

        // 心跳指示灯
        static uint32_t last_led_toggle = 0;
        if((current_time - last_led_toggle) > 1000) {
            last_led_toggle = current_time;
            gpio_bit_write(GPIOC, GPIO_PIN_13,
                          (BitAction)(1 - gpio_input_bit_get(GPIOC, GPIO_PIN_13)));
        }

        delay_ms(100);
    }
}



高级功能扩展
// OTA固件更新检查
void check_ota_update(void)
{
    char ota_topic[] = "device/ota/command";
    char version_msg[128];

    snprintf(version_msg, sizeof(version_msg),
             "{\"device\":\"%s\",\"version\":\"1.0\",\"timestamp\":%lu}",
             MQTT_CLIENT_ID, get_tick_count() / 1000);

    esp32_mqtt_publish("device/version", version_msg, 1);
    esp32_mqtt_subscribe(ota_topic);
}

// 设备配置管理
void save_device_config(void)
{
    // 保存配置到EEPROM或Flash
    // 这里可以添加配置保存逻辑
}

void load_device_config(void)
{
    // 从EEPROM或Flash加载配置
    // 这里可以添加配置加载逻辑
}

// QoS级别管理
typedef enum {
    QOS0 = 0,
    QOS1 = 1,
    QOS2 = 2
} mqtt_qos_t;

void publish_with_qos(const char *topic, const char *message, mqtt_qos_t qos)
{
    char qos_cmd[256];
    snprintf(qos_cmd, sizeof(qos_cmd),
             "AT+MQTTPUB=\"%s\",\"%s\",%d,0", topic, message, qos);

    esp32_send_at_command(qos_cmd, "OK", 10000);
}


项目配置文件
Makefile
TARGET = gd32_mqtt_demo
MCU = GD32F103ZE

CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy

CFLAGS = -mcpu=cortex-m3 -mthumb -std=gnu11 -O2 -g
CFLAGS += -fdata-sections -ffunction-sections
CFLAGS += -DGD32F10X_HD -DUSE_STDPERIPH_DRIVER

INCLUDES = -I. -IGD32F10x_Firmware_Library

SOURCES = main.c \
          system_gd32f10x.c \
          gd32f10x_gpio.c \
          gd32f10x_rcu.c \
          gd32f10x_usart.c \
          gd32f10x_misc.c

all: $(TARGET).bin

$(TARGET).bin: $(TARGET).elf
        $(OBJCOPY) -O binary $< $@

$(TARGET).elf: $(SOURCES)
        $(CC) $(CFLAGS) $(INCLUDES) $^ -T GD32F10x_HD.ld -o $@ -lc -lm -lnosys

clean:
        rm -f $(TARGET).elf $(TARGET).bin



这个完整的MQTT案例提供了:

Wi-Fi连接 - 自动连接配置的Wi-Fi网络
MQTT通信 - 完整的发布/订阅功能
数据采集 - 传感器数据读取和发布
设备控制 - 通过MQTT远程控制设备
网络恢复 - 自动检测和恢复网络连接
状态监控 - 实时设备状态监测
使用前请确保:

更新Wi-Fi SSID和密码
配置正确的MQTT服务器地址
根据实际硬件调整GPIO引脚
ESP32-C3需要烧录支持MQTT的AT固件
这个系统可以轻松扩展支持更多的传感器和更复杂的物联网应用场景。
————————————————
版权声明:本文为CSDN博主「Shylock_Mister」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Shylock_Mister/article/details/153748980

您需要登录后才可以回帖 登录 | 注册

本版积分规则

97

主题

300

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部