DX-CT511N-B STM32 HAL 驱动代码例程 - 头文件与驱动实现

知识库
知识库文档
/firmware/通信模块/DX-CT511N-B/DX-CT511N-B STM32 HAL 驱动代码例程 - 头文件与驱动实现.md

文档

DX-CT511N-B STM32 HAL 驱动代码例程

环境说明

项目 说明
MCU STM32F103C8T6(兼容全系列 STM32)
HAL 库 STM32Cube_FW_F1
IDE Keil MDK / STM32CubeIDE
模块串口 USART2 (PA2-TX / PA3-RX),115200bps
调试串口 USART1 (PA9-TX / PA10-RX)
PWRKEY PB9

1. 头文件 module_4g.h

#ifndef __MODULE_4G_H__
#define __MODULE_4G_H__

#include "stm32f1xx_hal.h"
#include <stdbool.h>
#include <stdint.h>

/* ============== 宏定义 ============== */

#define UART4G_RX_BUF_SIZE      1024
#define AT_TIMEOUT              3000
#define AT_LONG_TIMEOUT         15000

#define SERVER_HOST             "mqtt.your-broker.com"
#define SERVER_PORT             1883
#define HTTP_API_BASE           "http://api.your-server.com/register"

#define PWRKEY_PORT             GPIOB
#define PWRKEY_PIN              GPIO_PIN_9

/* ============== 设备状态结构体 ============== */

typedef struct {
    char     mac_addr[18];
    char     device_id[32];
    bool     network_ready;
    bool     mqtt_connected;
    uint32_t last_mqtt_ping;
    uint32_t last_gps_fix;
} device_ctx_t;

/* ============== API 接口 ============== */

int  Module4G_Init(void);
int  Module4G_Reset(void);
int  AT_SendRaw(const char *cmd);
int  AT_SendCmd(const char *cmd, char *resp, uint16_t resp_size,
                uint32_t timeout, const char *expect);
int  MQTT_Connect(const char *host, uint16_t port,
                  const char *client_id, uint16_t keepalive);
int  MQTT_Disconnect(void);
int  MQTT_Publish(const char *topic, const char *payload);
int  MQTT_Subscribe(const char *topic);
int  MQTT_Unsubscribe(const char *topic);
bool MQTT_HasMessage(char *topic_out, uint16_t topic_size,
                     char *payload_out, uint16_t payload_size);
int  HTTP_Post(const char *url, const char *body,
               char *resp, uint16_t resp_size);
int  HTTP_Get(const char *url, char *resp, uint16_t resp_size);
int  GPS_Enable(void);
int  GPS_Disable(void);
int  GPS_GetPosition(float *lat, float *lon, float *alt,
                     float *speed, float *course);
int  Network_GetSignalQuality(int *rssi, int *ber);
int  Network_GetIP(char *ip, uint16_t size);
void Module4G_Poll(void);

#endif /* __MODULE_4G_H__ */

2. 驱动实现 module_4g.c(上篇:串口 + AT指令 + MQTT)

#include "module_4g.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart1;

device_ctx_t g_device;

/* ---- 环形缓冲区 ---- */
static uint8_t  uart4g_rx_buf[UART4G_RX_BUF_SIZE];
static volatile uint16_t uart4g_rx_wr = 0;
static volatile uint16_t uart4g_rx_rd = 0;
static char at_resp_buf[UART4G_RX_BUF_SIZE];

#ifdef DEBUG_ENABLE
#define LOG(fmt, ...)  do { \
    char _log[128]; \
    snprintf(_log, sizeof(_log), "[4G] " fmt "\r\n", ##__VA_ARGS__); \
    HAL_UART_Transmit(&huart1, (uint8_t*)_log, strlen(_log), 100); \
} while(0)
#else
#define LOG(fmt, ...)
#endif

/* ============== 串口中断处理 ============== */

static void UART4G_StartReceive(void)
{
    HAL_UART_Receive_IT(&huart2,
                        &uart4g_rx_buf[uart4g_rx_wr], 1);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2) {
        uart4g_rx_wr = (uart4g_rx_wr + 1) % UART4G_RX_BUF_SIZE;
        HAL_UART_Receive_IT(&huart2,
                            &uart4g_rx_buf[uart4g_rx_wr], 1);
    }
}

static uint16_t UART4G_ReadAll(uint8_t *buf, uint16_t buf_size)
{
    uint16_t idx = 0;
    __disable_irq();
    while (uart4g_rx_rd != uart4g_rx_wr && idx < buf_size - 1) {
        buf[idx++] = uart4g_rx_buf[uart4g_rx_rd];
        uart4g_rx_rd = (uart4g_rx_rd + 1) % UART4G_RX_BUF_SIZE;
    }
    __enable_irq();
    buf[idx] = '\0';
    return idx;
}

static void UART4G_Flush(void)
{
    __disable_irq();
    uart4g_rx_wr = 0;
    uart4g_rx_rd = 0;
    __enable_irq();
}

/* ============== AT 指令底层 ============== */

int AT_SendRaw(const char *cmd)
{
    HAL_StatusTypeDef ret = HAL_UART_Transmit(&huart2,
                              (uint8_t *)cmd, strlen(cmd), 500);
    return (ret == HAL_OK) ? 0 : -1;
}

int AT_SendCmd(const char *cmd, char *resp, uint16_t resp_size,
               uint32_t timeout, const char *expect)
{
    UART4G_Flush();
    char send_buf[256];
    int len = snprintf(send_buf, sizeof(send_buf), "%s\r\n", cmd);
    if (len < 0) return -1;
    HAL_UART_Transmit(&huart2, (uint8_t *)send_buf, len, 500);

    uint32_t start = HAL_GetTick();
    uint16_t total = 0;
    uint8_t  tmp[128];

    while ((HAL_GetTick() - start) < timeout) {
        uint16_t n = UART4G_ReadAll(tmp, sizeof(tmp));
        if (n > 0) {
            if ((total + n) >= resp_size) n = resp_size - total - 1;
            if (n > 0) {
                memcpy(resp + total, tmp, n);
                total += n;
                resp[total] = '\0';
            }
            if (expect != NULL && strstr(resp, expect) != NULL)
                return 0;
            if (strstr(resp, "ERROR") != NULL) {
                LOG("AT ERROR: %s", cmd);
                return -1;
            }
        }
        HAL_Delay(10);
    }
    if (total > 0 && expect == NULL) return 0;
    LOG("AT TIMEOUT: %s", cmd);
    return -1;
}

/* ============== MQTT 操作 ============== */

int MQTT_Connect(const char *host, uint16_t port,
                 const char *client_id, uint16_t keepalive)
{
    char cmd[256];
    snprintf(cmd, sizeof(cmd),
             "AT+MQTTCONN=0,\"%s\",%d,\"%s\",%d",
             host, port, client_id, keepalive);
    return AT_SendCmd(cmd, at_resp_buf, sizeof(at_resp_buf),
                      AT_LONG_TIMEOUT, "OK");
}

int MQTT_Disconnect(void)
{
    return AT_SendCmd("AT+MQTTDISC=0", at_resp_buf,
                      sizeof(at_resp_buf), AT_TIMEOUT, "OK");
}

int MQTT_Publish(const char *topic, const char *payload)
{
    char cmd[512];
    snprintf(cmd, sizeof(cmd),
             "AT+MQTTPUB=0,\"%s\",\"%s\",0,0", topic, payload);
    return AT_SendCmd(cmd, at_resp_buf, sizeof(at_resp_buf),
                      AT_TIMEOUT, "OK");
}

int MQTT_Subscribe(const char *topic)
{
    char cmd[256];
    snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=0,\"%s\",0", topic);
    return AT_SendCmd(cmd, at_resp_buf, sizeof(at_resp_buf),
                      AT_TIMEOUT, "OK");
}

int MQTT_Unsubscribe(const char *topic)
{
    char cmd[256];
    snprintf(cmd, sizeof(cmd), "AT+MQTTUNSUB=0,\"%s\"", topic);
    return AT_SendCmd(cmd, at_resp_buf, sizeof(at_resp_buf),
                      AT_TIMEOUT, "OK");
}

bool MQTT_HasMessage(char *topic_out, uint16_t topic_size,
                     char *payload_out, uint16_t payload_size)
{
    uint8_t buf[512];
    uint16_t n = UART4G_ReadAll(buf, sizeof(buf));
    if (n == 0) return false;

    char *p = strstr((char *)buf, "+MQTTSUBRECV:");
    if (p == NULL) return false;

    char *t1 = strchr(p, '"');
    if (t1 == NULL) return false;
    char *t2 = strchr(t1 + 1, '"');
    if (t2 == NULL) return false;
    uint16_t tlen = (uint16_t)(t2 - t1 - 1);
    if (tlen >= topic_size) tlen = topic_size - 1;
    memcpy(topic_out, t1 + 1, tlen);
    topic_out[tlen] = '\0';

    char *p1 = strchr(t2 + 1, '"');
    if (p1 == NULL) return false;
    char *p2 = strchr(p1 + 1, '"');
    if (p2 == NULL) return false;
    uint16_t plen = (uint16_t)(p2 - p1 - 1);
    if (plen >= payload_size) plen = payload_size - 1;
    memcpy(payload_out, p1 + 1, plen);
    payload_out[plen] = '\0';

    LOG("MQTT RX [%s]: %s", topic_out, payload_out);
    return true;
}

信息

路径
/firmware/通信模块/DX-CT511N-B/DX-CT511N-B STM32 HAL 驱动代码例程 - 头文件与驱动实现.md
更新时间
2026/5/26