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;
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();
}
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;
}
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;
}