实现了WF24对WIFI的连接和MQTT的订阅与发布
This commit is contained in:
@@ -1,365 +1,555 @@
|
||||
#include "dx_wf_24.h"
|
||||
#include "elog.h"
|
||||
#include <string.h>
|
||||
#include "cmsis_os.h"
|
||||
#include "stdio.h"
|
||||
/* 发送缓冲区 */
|
||||
#define WIFI_TX_BUF_SIZE 512
|
||||
#include "cmsis_os2.h"
|
||||
#include "elog.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ================= 配置 ================= */
|
||||
|
||||
#define WIFI_TX_BUF_SIZE 512
|
||||
#define TAG "WIFI"
|
||||
|
||||
/* ================= 全局变量 ================= */
|
||||
|
||||
static uint8_t wifi_tx_buffer[WIFI_TX_BUF_SIZE];
|
||||
static volatile uint8_t wifi_tx_busy = 0;
|
||||
|
||||
/* WiFi 全局结构体 */
|
||||
WIFI_HandleTypeDef wifi = {0};
|
||||
|
||||
/* 日志标签 */
|
||||
#define TAG "WIFI"
|
||||
/* MQTT 状态 */
|
||||
static volatile uint8_t mqtt_connected = 0;
|
||||
static MQTT_State_t mqtt_state = MQTT_STATE_IDLE;
|
||||
|
||||
static void Generate_Random_ClientID(char *out_id, uint16_t max_len) {
|
||||
// 获取系统运行时间
|
||||
uint32_t tick = HAL_GetTick();
|
||||
|
||||
// 获取设备唯一标识(使用STM32的UID)
|
||||
uint32_t *uid = (uint32_t *)UID_BASE;
|
||||
uint32_t uid_hash = uid[0] ^ uid[1] ^ uid[2]; // 混合UID各部分
|
||||
|
||||
// 组合多个随机源
|
||||
uint32_t random_seed = tick ^ uid_hash ^ (tick >> 16);
|
||||
|
||||
// 计算时间戳各位数字之和
|
||||
uint32_t temp = tick;
|
||||
uint32_t sum = 0;
|
||||
while (temp > 0) {
|
||||
sum += temp % 10;
|
||||
temp /= 10;
|
||||
}
|
||||
|
||||
// 生成最终ID,包含时间戳、随机种子和校验和
|
||||
snprintf(out_id, max_len, "SmartPetFeeder_%lu_%lu_%lu", tick, random_seed,
|
||||
sum);
|
||||
}
|
||||
|
||||
/* ================= DMA RX 初始化 ================= */
|
||||
|
||||
/**
|
||||
* @brief 初始化 WiFi DMA 接收(空闲中断方式)
|
||||
* @retval HAL_StatusTypeDef
|
||||
* @note 在 main 中调用此函数初始化
|
||||
*/
|
||||
HAL_StatusTypeDef WIFI_RECV_DMA_Init(void) {
|
||||
/* 清空缓冲区 */
|
||||
memset(&wifi, 0, sizeof(wifi));
|
||||
|
||||
/* 停止可能正在进行的 DMA */
|
||||
HAL_UART_DMAStop(&huart1);
|
||||
|
||||
/* 启动 DMA 接收(环形缓冲区模式) */
|
||||
HAL_StatusTypeDef status = HAL_UART_Receive_DMA(&huart1, wifi.rx_buffer, WIFI_RX_BUF_SIZE);
|
||||
|
||||
if (status == HAL_OK) {
|
||||
/* 启用空闲中断 - 关键! */
|
||||
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
|
||||
elog_i(TAG, "WiFi DMA RX init OK");
|
||||
} else {
|
||||
elog_e(TAG, "WiFi DMA RX init failed: %d", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
memset(&wifi, 0, sizeof(wifi));
|
||||
|
||||
HAL_UART_DMAStop(&huart1);
|
||||
|
||||
HAL_StatusTypeDef status =
|
||||
HAL_UART_Receive_DMA(&huart1, wifi.rx_buffer, WIFI_RX_BUF_SIZE);
|
||||
|
||||
if (status == HAL_OK) {
|
||||
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
|
||||
elog_i(TAG, "WiFi串口DMA接收初始化成功");
|
||||
} else {
|
||||
elog_e(TAG, "WiFi串口DMA初始化失败");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 串口空闲中断回调(在 USART1_IRQHandler 中调用)
|
||||
* @param huart 串口句柄
|
||||
* @note 当串口空闲时触发,表示一帧数据接收完成
|
||||
*/
|
||||
/* ================= UART IDLE 回调 ================= */
|
||||
|
||||
void WIFI_UART_IDLE_Callback(UART_HandleTypeDef *huart) {
|
||||
if (huart->Instance != USART1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* 清除 IDLE 标志(必须先读 SR 再读 DR) */
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
|
||||
/* 停止 DMA 传输,获取已接收数据长度 */
|
||||
HAL_UART_DMAStop(huart);
|
||||
|
||||
/* 计算本次接收的数据长度 */
|
||||
uint16_t recv_len = WIFI_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);
|
||||
|
||||
if (recv_len > 0 && recv_len < WIFI_RX_BUF_SIZE) {
|
||||
wifi.rx_len = recv_len;
|
||||
wifi.rx_buffer[recv_len] = '\0'; // 添加字符串结束符
|
||||
wifi.rx_flag = 1; // 标记接收完成
|
||||
|
||||
elog_d(TAG, "RX[%d]: %s", recv_len, wifi.rx_buffer);
|
||||
}
|
||||
|
||||
/* 重新启动 DMA 接收 */
|
||||
HAL_UART_Receive_DMA(&huart1, wifi.rx_buffer, WIFI_RX_BUF_SIZE);
|
||||
if (huart->Instance != USART1)
|
||||
return;
|
||||
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
HAL_UART_DMAStop(huart);
|
||||
|
||||
uint16_t recv_len = WIFI_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);
|
||||
|
||||
if (recv_len > 0 && recv_len < WIFI_RX_BUF_SIZE) {
|
||||
wifi.rx_len = recv_len;
|
||||
wifi.rx_buffer[recv_len] = '\0';
|
||||
wifi.rx_flag = 1;
|
||||
}
|
||||
|
||||
HAL_UART_Receive_DMA(&huart1, wifi.rx_buffer, WIFI_RX_BUF_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取接收到的数据
|
||||
* @param buffer 输出缓冲区
|
||||
* @param len 缓冲区大小
|
||||
* @retval int 实际复制长度,0表示无数据
|
||||
*/
|
||||
int WIFI_Get_Received_Data(uint8_t *buffer, uint16_t len) {
|
||||
if (!wifi.rx_flag || buffer == NULL || len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t copy_len = (wifi.rx_len < len) ? wifi.rx_len : (len - 1);
|
||||
memcpy(buffer, wifi.rx_buffer, copy_len);
|
||||
buffer[copy_len] = '\0';
|
||||
|
||||
wifi.rx_flag = 0; // 清除标志
|
||||
return copy_len;
|
||||
}
|
||||
/* ================= DMA 发送 ================= */
|
||||
|
||||
/**
|
||||
* @brief 通过 DMA 发送 WiFi 数据(非阻塞)
|
||||
* @param data 要发送的字符串
|
||||
* @retval HAL_StatusTypeDef 发送状态
|
||||
*/
|
||||
HAL_StatusTypeDef WIFI_SEND_DMA(const char *data) {
|
||||
if (data == NULL) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
if (!data)
|
||||
return HAL_ERROR;
|
||||
|
||||
size_t len = strlen(data);
|
||||
if (len == 0) {
|
||||
return HAL_OK;
|
||||
}
|
||||
size_t len = strlen(data);
|
||||
if (len == 0 || len >= WIFI_TX_BUF_SIZE)
|
||||
return HAL_ERROR;
|
||||
if (wifi_tx_busy)
|
||||
return HAL_BUSY;
|
||||
|
||||
if (len >= WIFI_TX_BUF_SIZE) {
|
||||
elog_w(TAG, "TX data too long: %d", len);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
memcpy(wifi_tx_buffer, data, len);
|
||||
wifi_tx_busy = 1;
|
||||
|
||||
if (wifi_tx_busy) {
|
||||
return HAL_BUSY;
|
||||
}
|
||||
HAL_StatusTypeDef ret = HAL_UART_Transmit_DMA(&huart1, wifi_tx_buffer, len);
|
||||
|
||||
memcpy(wifi_tx_buffer, data, len);
|
||||
wifi_tx_busy = 1;
|
||||
|
||||
HAL_StatusTypeDef status = HAL_UART_Transmit_DMA(&huart1, wifi_tx_buffer, len);
|
||||
if (status != HAL_OK) {
|
||||
wifi_tx_busy = 0;
|
||||
elog_e(TAG, "TX DMA failed: %d", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
if (ret != HAL_OK)
|
||||
wifi_tx_busy = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* DMA 发送完成回调 */
|
||||
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
if (huart->Instance == USART1) {
|
||||
wifi_tx_busy = 0;
|
||||
elog_d(TAG, "TX complete");
|
||||
}
|
||||
if (huart->Instance == USART1) {
|
||||
wifi_tx_busy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* DMA 接收完成回调(半传输/全传输) */
|
||||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
if (huart->Instance == USART1) {
|
||||
/* 缓冲区满,标记接收完成 */
|
||||
wifi.rx_len = WIFI_RX_BUF_SIZE;
|
||||
wifi.rx_flag = 1;
|
||||
elog_w(TAG, "RX buffer full!");
|
||||
/* ================= 等待事件 ================= */
|
||||
|
||||
uint8_t WIFI_WaitEvent(const char *ok_str, const char *fail_str,
|
||||
uint32_t timeout_ms) {
|
||||
uint32_t start = HAL_GetTick();
|
||||
|
||||
while (HAL_GetTick() - start < timeout_ms) {
|
||||
if (wifi.rx_flag) {
|
||||
wifi.rx_flag = 0;
|
||||
|
||||
char *buf = (char *)wifi.rx_buffer;
|
||||
|
||||
elog_i(TAG, "接收到WiFi模块数据: %s", buf);
|
||||
|
||||
/* ===== 优先处理断线事件 ===== */
|
||||
if (strstr(buf, "+MQTTDISCONNECTED")) {
|
||||
mqtt_connected = 0;
|
||||
elog_e(TAG, "MQTT已断开");
|
||||
}
|
||||
|
||||
/* ===== 处理连接成功 ===== */
|
||||
if (strstr(buf, "+MQTTCONNECTED")) {
|
||||
mqtt_connected = 1;
|
||||
elog_i(TAG, "MQTT服务器连接成功");
|
||||
}
|
||||
|
||||
/* ===== 处理 ERROR=xxx ===== */
|
||||
if (strstr(buf, "ERROR=")) {
|
||||
elog_e(TAG, "模块返回错误: %s", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===== 处理普通ERROR ===== */
|
||||
if (fail_str && strstr(buf, fail_str)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===== 处理OK ===== */
|
||||
if (ok_str && strstr(buf, ok_str)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
osDelay(10);
|
||||
}
|
||||
|
||||
elog_e(TAG, "等待事件超时");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检测 WiFi 应答(同步阻塞式)
|
||||
* @param cmd 要发送的 AT 指令
|
||||
* @param expect 期望的应答字符串(如 "OK", "READY")
|
||||
* @param timeout_ms 超时时间(毫秒)
|
||||
* @retval 1-收到期望应答, 0-超时或失败
|
||||
* @note 此函数会阻塞等待应答,建议在初始化阶段使用
|
||||
* @warning 如果在 FreeRTOS 中使用,确保 configUSE_PREEMPTION 已启用
|
||||
*
|
||||
* @example
|
||||
* // 检测模块是否就绪
|
||||
* if (WIFI_CheckAck("AT\r\n", "OK", 1000)) {
|
||||
* elog_i(TAG, "WiFi module ready");
|
||||
* }
|
||||
*/
|
||||
uint8_t WIFI_CheckAck(const char *cmd, const char *expect, uint32_t timeout_ms)
|
||||
{
|
||||
char recv_buf[WIFI_RX_BUF_SIZE];
|
||||
|
||||
if (cmd == NULL || expect == NULL) {
|
||||
elog_e(TAG, "Invalid parameters");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 清空之前的接收标志
|
||||
wifi.rx_flag = 0;
|
||||
|
||||
// 发送指令
|
||||
HAL_StatusTypeDef status = WIFI_SEND_DMA(cmd);
|
||||
if (status != HAL_OK) {
|
||||
elog_e(TAG, "Send failed: %d", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_d(TAG, "Wait for: %s", expect);
|
||||
|
||||
// 等待应答(轮询方式)
|
||||
uint32_t start_tick = HAL_GetTick();
|
||||
while ((HAL_GetTick() - start_tick) < timeout_ms) {
|
||||
|
||||
// 检查是否接收到数据
|
||||
if (wifi.rx_flag) {
|
||||
// 获取数据并清零标志
|
||||
int len = WIFI_Get_Received_Data((uint8_t *)recv_buf, sizeof(recv_buf));
|
||||
|
||||
if (len > 0) {
|
||||
elog_d(TAG, "Recv: %s", recv_buf);
|
||||
|
||||
// 检查是否包含期望应答
|
||||
if (strstr(recv_buf, expect) != NULL) {
|
||||
elog_i(TAG, "Ack matched: %s", expect);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 检查是否包含错误应答
|
||||
if (strstr(recv_buf, "ERROR") != NULL) {
|
||||
elog_w(TAG, "Got ERROR response");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 小延时,避免忙等
|
||||
HAL_Delay(1);
|
||||
}
|
||||
|
||||
elog_w(TAG, "Ack timeout, expect: %s", expect);
|
||||
/* ================= ACK ================= */
|
||||
|
||||
uint8_t WIFI_CheckAck(const char *cmd, const char *expect,
|
||||
uint32_t timeout_ms) {
|
||||
wifi.rx_flag = 0;
|
||||
|
||||
if (cmd && strlen(cmd)) {
|
||||
if (WIFI_SEND_DMA(cmd) != HAL_OK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return WIFI_WaitEvent(expect, "ERROR", timeout_ms);
|
||||
}
|
||||
|
||||
/* ================= WiFi连接 ================= */
|
||||
|
||||
uint8_t WIFI_Connect_WiFi(const char *ssid, const char *password,
|
||||
uint32_t timeout_ms) {
|
||||
char cmd[128];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "AT+CWJAP=%s,%s\r\n", ssid, password);
|
||||
|
||||
elog_i(TAG, "正在连接WiFi: %s", ssid);
|
||||
elog_i(TAG, "发送命令: %s", cmd);
|
||||
|
||||
if (WIFI_SEND_DMA(cmd) != HAL_OK) {
|
||||
elog_e(TAG, "WiFi命令发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "等待WiFi基础连接响应...");
|
||||
if (!WIFI_WaitEvent("OK", "ERROR", 3000)) {
|
||||
elog_e(TAG, "WiFi基础连接失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "等待WiFi详细连接结果...");
|
||||
if (!WIFI_WaitEvent("+CWJAP:1", "+CWJAP:0", timeout_ms)) {
|
||||
elog_e(TAG, "WiFi详细连接失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "WiFi连接成功");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 连接MQTT服务器(完整流程,支持用户名密码认证)
|
||||
* @param wifi_ssid WiFi名称
|
||||
* @param wifi_pass WiFi密码
|
||||
* @param mqtt_broker MQTT服务器地址
|
||||
* @param mqtt_port MQTT端口
|
||||
* @param client_id MQTT客户端ID
|
||||
* @param mqtt_user MQTT用户名(可为NULL表示不需要认证)
|
||||
* @param mqtt_pass MQTT密码(可为NULL表示不需要认证)
|
||||
* @param sub_topic 订阅的主题
|
||||
* @retval 1-连接成功, 0-失败
|
||||
* @note 每一步都有重试机制,失败后不会卡死
|
||||
*
|
||||
* @example
|
||||
* // 连接到MQTT服务器(无需认证)
|
||||
* if (WIFI_Connect_MQTT("MyWiFi", "12345678",
|
||||
* "broker.emqx.io", 1883,
|
||||
* "PetFeeder-001", NULL, NULL, "pet/control")) {
|
||||
* elog_i(TAG, "MQTT connected");
|
||||
* }
|
||||
*
|
||||
* // 连接到MQTT服务器(需要认证)
|
||||
* if (WIFI_Connect_MQTT("MyWiFi", "12345678",
|
||||
* "broker.emqx.io", 1883,
|
||||
* "PetFeeder-001", "user1", "pass123", "pet/control")) {
|
||||
* elog_i(TAG, "MQTT connected");
|
||||
* }
|
||||
*/
|
||||
uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
|
||||
const char *mqtt_broker, uint16_t mqtt_port,
|
||||
const char *client_id, const char *mqtt_user,
|
||||
const char *mqtt_pass, const char *sub_topic)
|
||||
{
|
||||
char cmd_buf[128];
|
||||
uint8_t retry_count = 0;
|
||||
const uint8_t max_retry = 3;
|
||||
|
||||
elog_i(TAG, "=== Starting MQTT Connection ===");
|
||||
|
||||
/* 步骤1: 清理环境 */
|
||||
elog_d(TAG, "Step 1: Clean MQTT environment");
|
||||
if (!WIFI_CheckAck("AT+MQTTCLEAN\r\n", "OK", 2000)) {
|
||||
elog_w(TAG, "MQTTCLEAN failed, continue...");
|
||||
}
|
||||
|
||||
/* ================= MQTT连接 ================= */
|
||||
uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
|
||||
const char *mqtt_host, uint16_t mqtt_port,
|
||||
const char *client_id, const char *user,
|
||||
const char *pass) {
|
||||
char cmd[256];
|
||||
|
||||
|
||||
/* 步骤3: AT测试 */
|
||||
elog_d(TAG, "Step 3: AT test");
|
||||
retry_count = 0;
|
||||
while (retry_count < max_retry) {
|
||||
if (WIFI_CheckAck("AT\r\n", "OK", 1000)) {
|
||||
break;
|
||||
elog_i(TAG, "开始MQTT连接流程");
|
||||
|
||||
elog_i(TAG, "断开 MQTT 连接(如果已连接)");
|
||||
|
||||
if (!WIFI_CheckAck("AT+MQTTCLEAN\r\n", "OK", 2000)) {
|
||||
elog_e(TAG, "MQTTCLEAN 失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 等待真正断开事件 */
|
||||
WIFI_WaitEvent("+MQTTDISCONNECTED", NULL, 2000);
|
||||
|
||||
/* 稍微延时,避免状态机还没稳定 */
|
||||
osDelay(200);
|
||||
|
||||
elog_i(TAG, "1. 检查模块响应...");
|
||||
if (!WIFI_CheckAck("AT\r\n", "OK", 1000)) {
|
||||
elog_e(TAG, "模块无响应");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "2. 设置WiFi模式...");
|
||||
if (!WIFI_CheckAck("AT+CWMODE=0\r\n", "OK", 2000)) {
|
||||
elog_e(TAG, "WiFi模式设置失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "3. 连接WiFi网络...");
|
||||
if (!WIFI_Connect_WiFi(wifi_ssid, wifi_pass, 15000)) {
|
||||
elog_e(TAG, "WiFi连接失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mqtt_state = MQTT_STATE_WIFI_CONNECTED;
|
||||
elog_i(TAG, "WiFi连接完成,状态: %d", mqtt_state);
|
||||
|
||||
elog_i(TAG, "4. 设置MQTT客户端ID: %s", client_id);
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTLONGCLIENTID=%s\r\n", client_id);
|
||||
if (!WIFI_CheckAck(cmd, "OK", 2000)) {
|
||||
elog_e(TAG, "MQTT客户端ID设置失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "5. 设置MQTT用户名: %s", user);
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTLONGUSERNAME=%s\r\n", user);
|
||||
if (!WIFI_CheckAck(cmd, "OK", 2000)) {
|
||||
elog_e(TAG, "MQTT用户名设置失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "6. 设置MQTT密码");
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTLONGPASSWORD=%s\r\n", pass);
|
||||
if (!WIFI_CheckAck(cmd, "OK", 2000)) {
|
||||
elog_e(TAG, "MQTT密码设置失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "7. 连接MQTT服务器并新建会话 %s:%d", mqtt_host, mqtt_port);
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTCONN=%s,%d,0\r\n", mqtt_host, mqtt_port);
|
||||
|
||||
if (WIFI_SEND_DMA(cmd) != HAL_OK) {
|
||||
elog_e(TAG, "MQTT连接命令发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "等待MQTT服务器连接响应...");
|
||||
if (!WIFI_WaitEvent("+MQTTCONNECTED", "FAIL", 10000)) {
|
||||
elog_e(TAG, "MQTT服务器连接失败");
|
||||
elog_i(TAG, "接收到的模块响应: %s", wifi.rx_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mqtt_connected = 1;
|
||||
mqtt_state = MQTT_STATE_SERVER_CONNECTED;
|
||||
elog_i(TAG, "MQTT服务器连接成功,状态: %d", mqtt_state);
|
||||
|
||||
/* ===== 双订阅:使用自定义等待逻辑以兼容 ALREADY SUBSCRIBE ===== */
|
||||
|
||||
// 订阅 control 主题
|
||||
elog_i(TAG, "8. 订阅control主题");
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=petfeeder/control,0\r\n");
|
||||
wifi.rx_flag = 0;
|
||||
if (WIFI_SEND_DMA(cmd) != HAL_OK) {
|
||||
elog_e(TAG, "control主题订阅命令发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t start = HAL_GetTick();
|
||||
uint8_t subscribed = 0;
|
||||
while (HAL_GetTick() - start < 5000) {
|
||||
if (wifi.rx_flag) {
|
||||
wifi.rx_flag = 0;
|
||||
elog_i(TAG, "接收到订阅响应: %s", wifi.rx_buffer);
|
||||
if (strstr((char *)wifi.rx_buffer, "+MQTTSUB") ||
|
||||
strstr((char *)wifi.rx_buffer, "ALREADY SUBSCRIBE") ||
|
||||
strstr((char *)wifi.rx_buffer, "OK")) {
|
||||
subscribed = 1;
|
||||
break;
|
||||
}
|
||||
retry_count++;
|
||||
elog_w(TAG, "AT test retry %d/%d", retry_count, max_retry);
|
||||
osDelay(500);
|
||||
}
|
||||
if (retry_count >= max_retry) {
|
||||
elog_e(TAG, "AT test failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 步骤4: 设置STA模式 */
|
||||
elog_d(TAG, "Step 4: Set STA mode");
|
||||
if (!WIFI_CheckAck("AT+CWMODE=1\r\n", "OK", 2000)) {
|
||||
elog_e(TAG, "Set STA mode failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 步骤5: 连接WiFi */
|
||||
elog_d(TAG, "Step 5: Connect to WiFi: %s", wifi_ssid);
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "AT+CWJAP=\"%s\",\"%s\"\r\n", wifi_ssid, wifi_pass);
|
||||
|
||||
retry_count = 0;
|
||||
while (retry_count < max_retry) {
|
||||
if (WIFI_CheckAck(cmd_buf, "WIFI GOT IP", 10000)) {
|
||||
elog_i(TAG, "WiFi connected successfully");
|
||||
break;
|
||||
if (strstr((char *)wifi.rx_buffer, "ERROR") ||
|
||||
strstr((char *)wifi.rx_buffer, "FAIL")) {
|
||||
break;
|
||||
}
|
||||
retry_count++;
|
||||
elog_w(TAG, "WiFi connect retry %d/%d", retry_count, max_retry);
|
||||
osDelay(2000);
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
if (retry_count >= max_retry) {
|
||||
elog_e(TAG, "WiFi connect failed");
|
||||
return 0;
|
||||
if (!subscribed) {
|
||||
elog_e(TAG, "control主题订阅失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 步骤6: 配置MQTT用户参数(用户名和密码) */
|
||||
if (mqtt_user != NULL && mqtt_pass != NULL) {
|
||||
elog_d(TAG, "Step 6: Configure MQTT user authentication");
|
||||
// 配置MQTT用户参数:LinkID=0, scheme=1, client_id, username, password
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",
|
||||
client_id, mqtt_user, mqtt_pass);
|
||||
if (!WIFI_CheckAck(cmd_buf, "OK", 3000)) {
|
||||
elog_e(TAG, "MQTT user configuration failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 订阅 config 主题
|
||||
elog_i(TAG, "9. 订阅config主题");
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=petfeeder/config,0\r\n");
|
||||
wifi.rx_flag = 0;
|
||||
if (WIFI_SEND_DMA(cmd) != HAL_OK) {
|
||||
elog_e(TAG, "config主题订阅命令发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t start = HAL_GetTick();
|
||||
uint8_t subscribed = 0;
|
||||
while (HAL_GetTick() - start < 5000) {
|
||||
if (wifi.rx_flag) {
|
||||
wifi.rx_flag = 0;
|
||||
elog_i(TAG, "接收到订阅响应: %s", wifi.rx_buffer);
|
||||
if (strstr((char *)wifi.rx_buffer, "+MQTTSUB") ||
|
||||
strstr((char *)wifi.rx_buffer, "ALREADY SUBSCRIBE") ||
|
||||
strstr((char *)wifi.rx_buffer, "OK")) {
|
||||
subscribed = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
elog_d(TAG, "Step 6: Configure MQTT without authentication");
|
||||
// 无认证模式
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "AT+MQTTUSERCFG=0,1,\"%s\",\"\",\"\",0,0,\"\"\r\n", client_id);
|
||||
if (!WIFI_CheckAck(cmd_buf, "OK", 3000)) {
|
||||
elog_e(TAG, "MQTT configuration failed");
|
||||
return 0;
|
||||
if (strstr((char *)wifi.rx_buffer, "ERROR") ||
|
||||
strstr((char *)wifi.rx_buffer, "FAIL")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
|
||||
/* 步骤7: 连接MQTT服务器 */
|
||||
elog_d(TAG, "Step 7: Connect to MQTT broker: %s:%d", mqtt_broker, mqtt_port);
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "AT+MQTTCONN=0,\"%s\",%d,0\r\n", mqtt_broker, mqtt_port);
|
||||
|
||||
retry_count = 0;
|
||||
while (retry_count < max_retry) {
|
||||
if (WIFI_CheckAck(cmd_buf, "MQTTCONNECTED:", 5000)) {
|
||||
elog_i(TAG, "MQTT broker connected");
|
||||
break;
|
||||
}
|
||||
retry_count++;
|
||||
elog_w(TAG, "MQTT connect retry %d/%d", retry_count, max_retry);
|
||||
osDelay(1000);
|
||||
if (!subscribed) {
|
||||
elog_e(TAG, "config主题订阅失败");
|
||||
return 0;
|
||||
}
|
||||
if (retry_count >= max_retry) {
|
||||
elog_e(TAG, "MQTT connect failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 步骤8: 订阅主题 */
|
||||
elog_d(TAG, "Step 8: Subscribe topic: %s", sub_topic);
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "AT+MQTTSUB=0,\"%s\",0\r\n", sub_topic);
|
||||
if (!WIFI_CheckAck(cmd_buf, "OK", 3000)) {
|
||||
elog_e(TAG, "Subscribe failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 步骤9: 发布上线消息 */
|
||||
elog_d(TAG, "Step 9: Publish online message");
|
||||
const char *online_topic = "device/online";
|
||||
const char *online_msg = "{\"device\":\"PetFeeder\",\"status\":\"online\"}";
|
||||
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "AT+MQTTPUB=0,\"%s\",\"%s\",0,0\r\n", online_topic, online_msg);
|
||||
if (!WIFI_CheckAck(cmd_buf, "OK", 2000)) {
|
||||
elog_w(TAG, "Publish online message failed, continue...");
|
||||
}
|
||||
|
||||
elog_i(TAG, "=== MQTT Connection Completed Successfully ===");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mqtt_state = MQTT_STATE_SUBSCRIBED;
|
||||
elog_i(TAG, "MQTT双主题订阅完成,最终状态: %d", mqtt_state);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================= MQTT发布函数 ================= */
|
||||
|
||||
uint8_t WIFI_MQTT_Publish_RAW(const char *topic, const uint8_t *payload,
|
||||
uint16_t length, uint8_t qos, uint8_t retain) {
|
||||
if (!mqtt_connected) {
|
||||
elog_e(TAG, "MQTT未连接,无法发布消息");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!topic || !payload || length == 0) {
|
||||
elog_e(TAG, "发布参数无效: topic=%p, payload=%p, length=%d", topic, payload,
|
||||
length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (length > 1000) {
|
||||
elog_e(TAG, "发布数据过长: %d bytes", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
|
||||
/* 1️⃣ 发送发布命令 */
|
||||
snprintf(cmd, sizeof(cmd), "AT+MQTTPUBRAW=%s,%d,%d,%d\r\n", topic, length,
|
||||
qos, retain);
|
||||
elog_i(TAG, "准备发布到主题: %s, 长度: %d, QoS: %d", topic, length, qos);
|
||||
|
||||
if (WIFI_SEND_DMA(cmd) != HAL_OK) {
|
||||
elog_e(TAG, "发布命令发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 2️⃣ 等待 > 提示符 */
|
||||
elog_i(TAG, "等待发布提示符>");
|
||||
if (!WIFI_WaitEvent(">", "ERROR", 3000)) {
|
||||
elog_e(TAG, "未收到发布提示符>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 3️⃣ 发送实际数据(不能带\r\n) */
|
||||
elog_i(TAG, "发送MQTT负载数据 (%d bytes)", length);
|
||||
if (HAL_UART_Transmit(&huart1, (uint8_t *)payload, length, 3000) != HAL_OK) {
|
||||
elog_e(TAG, "MQTT负载数据发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 4️⃣ 等待发布成功 */
|
||||
elog_i(TAG, "等待发布确认");
|
||||
if (!WIFI_WaitEvent("+MQTTPUB:OK", "FAIL", 5000)) {
|
||||
elog_e(TAG, "MQTT发布失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "MQTT发布成功到主题: %s", topic);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================= MQTT接收任务 ================= */
|
||||
|
||||
void wifi_task_mqtt(void *argument) {
|
||||
MQTT_Message_t msg;
|
||||
|
||||
elog_i(TAG, "启动WiFi MQTT任务");
|
||||
WIFI_RECV_DMA_Init();
|
||||
osDelay(3000);
|
||||
|
||||
char client_id[64] = {0};
|
||||
|
||||
// 生成唯一ClientID
|
||||
Generate_Random_ClientID(client_id, sizeof(client_id));
|
||||
|
||||
elog_i(TAG, "生成ClientID: %s", client_id);
|
||||
|
||||
elog_i(TAG, "开始MQTT连接...");
|
||||
if (!WIFI_Connect_MQTT("WIFI_TEST", "88888888", "www.beihong.wang", 1883,
|
||||
client_id, "STM32_MQTT", "123456")) {
|
||||
elog_e(TAG, "MQTT连接失败,任务退出");
|
||||
vTaskDelete(NULL); // 删除自身任务
|
||||
}
|
||||
|
||||
elog_i(TAG, "发布设备上线状态");
|
||||
WIFI_MQTT_Publish_Status("{\"status\":\"online\"}");
|
||||
|
||||
elog_i(TAG, "进入MQTT消息处理循环");
|
||||
for (;;) {
|
||||
if (wifi.rx_flag) {
|
||||
wifi.rx_flag = 0;
|
||||
|
||||
elog_i(TAG, "收到WiFi数据: %s", wifi.rx_buffer);
|
||||
|
||||
if (WIFI_Parse_MQTT_Message((char *)wifi.rx_buffer, &msg)) {
|
||||
elog_i(TAG, "解析MQTT消息成功");
|
||||
elog_i(TAG, "收到主题: %s", msg.topic);
|
||||
elog_i(TAG, "内容: %s", msg.payload);
|
||||
|
||||
/* ===== control主题 ===== */
|
||||
if (strcmp(msg.topic, "petfeeder/control") == 0) {
|
||||
elog_i(TAG, "处理control主题消息");
|
||||
if (strstr(msg.payload, "feed")) {
|
||||
elog_i(TAG, "执行喂食动作");
|
||||
// 执行喂食函数
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== config主题 ===== */
|
||||
else if (strcmp(msg.topic, "petfeeder/config") == 0) {
|
||||
elog_i(TAG, "处理config主题消息");
|
||||
elog_i(TAG, "更新配置参数");
|
||||
// 更新参数逻辑
|
||||
}
|
||||
} else {
|
||||
elog_w(TAG, "MQTT消息解析失败");
|
||||
}
|
||||
}
|
||||
|
||||
osDelay(20);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t WIFI_Parse_MQTT_Message(char *input, MQTT_Message_t *msg) {
|
||||
if (!input || !msg)
|
||||
return 0;
|
||||
|
||||
char *start = strstr(input, "+MQTTSUBRECV:");
|
||||
if (!start)
|
||||
return 0;
|
||||
|
||||
start += strlen("+MQTTSUBRECV:");
|
||||
|
||||
/* ========= 1. 解析 topic ========= */
|
||||
char *comma1 = strchr(start, ',');
|
||||
if (!comma1)
|
||||
return 0;
|
||||
|
||||
uint16_t topic_len = comma1 - start;
|
||||
if (topic_len >= sizeof(msg->topic))
|
||||
return 0;
|
||||
|
||||
memcpy(msg->topic, start, topic_len);
|
||||
msg->topic[topic_len] = '\0';
|
||||
|
||||
/* ========= 2. 解析 length ========= */
|
||||
char *comma2 = strchr(comma1 + 1, ',');
|
||||
if (!comma2)
|
||||
return 0;
|
||||
|
||||
char len_str[10] = {0};
|
||||
uint16_t len_field_len = comma2 - (comma1 + 1);
|
||||
|
||||
if (len_field_len >= sizeof(len_str))
|
||||
return 0;
|
||||
|
||||
memcpy(len_str, comma1 + 1, len_field_len);
|
||||
len_str[len_field_len] = '\0';
|
||||
|
||||
uint16_t payload_len = atoi(len_str);
|
||||
|
||||
if (payload_len == 0 || payload_len >= sizeof(msg->payload))
|
||||
return 0;
|
||||
|
||||
/* ========= 3. 解析 payload ========= */
|
||||
char *payload_start = comma2 + 1;
|
||||
|
||||
if (strlen(payload_start) < payload_len)
|
||||
return 0; // 数据还没收完整
|
||||
|
||||
memcpy(msg->payload, payload_start, payload_len);
|
||||
msg->payload[payload_len] = '\0';
|
||||
|
||||
msg->payload_len = payload_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t WIFI_MQTT_Publish_Sensor(const char *json) {
|
||||
return WIFI_MQTT_Publish_RAW("petfeeder/sensor", (uint8_t *)json,
|
||||
strlen(json), 0, 0);
|
||||
}
|
||||
|
||||
uint8_t WIFI_MQTT_Publish_Status(const char *json) {
|
||||
return WIFI_MQTT_Publish_RAW("petfeeder/status", (uint8_t *)json,
|
||||
strlen(json), 0, 1);
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/* 默认超时时间(毫秒) */
|
||||
#define WIFI_DEFAULT_TIMEOUT 1000
|
||||
#define WIFI_DEFAULT_TIMEOUT 1000
|
||||
|
||||
/* WiFi 接收缓冲区大小 */
|
||||
#define WIFI_RX_BUF_SIZE 512
|
||||
#define WIFI_RX_BUF_SIZE 1024
|
||||
|
||||
/* WiFi 数据结构体 */
|
||||
typedef struct {
|
||||
@@ -19,19 +19,44 @@ typedef struct {
|
||||
|
||||
extern WIFI_HandleTypeDef wifi;
|
||||
|
||||
/* MQTT消息结构体 */
|
||||
typedef struct {
|
||||
char topic[128];
|
||||
char payload[256];
|
||||
uint16_t payload_len;
|
||||
} MQTT_Message_t;
|
||||
|
||||
/* 解析函数 */
|
||||
uint8_t WIFI_Parse_MQTT_Message(char *input, MQTT_Message_t *msg);
|
||||
|
||||
/* MQTT运行状态 */
|
||||
typedef enum {
|
||||
MQTT_STATE_IDLE = 0,
|
||||
MQTT_STATE_WIFI_CONNECTED,
|
||||
MQTT_STATE_SERVER_CONNECTED,
|
||||
MQTT_STATE_SUBSCRIBED
|
||||
} MQTT_State_t;
|
||||
|
||||
/* 函数声明 */
|
||||
HAL_StatusTypeDef WIFI_SEND_DMA(const char *data);
|
||||
HAL_StatusTypeDef WIFI_RECV_DMA_Init(void);
|
||||
void WIFI_UART_IDLE_Callback(UART_HandleTypeDef *huart);
|
||||
int WIFI_Get_Received_Data(uint8_t *buffer, uint16_t len);
|
||||
// int WIFI_Get_Received_Data(uint8_t *buffer, uint16_t len);
|
||||
|
||||
/* 同步应答检测函数 */
|
||||
uint8_t WIFI_CheckAck(const char *cmd, const char *expect, uint32_t timeout_ms);
|
||||
|
||||
/* MQTT连接函数 */
|
||||
uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
|
||||
const char *mqtt_broker, uint16_t mqtt_port,
|
||||
const char *client_id, const char *mqtt_user,
|
||||
const char *mqtt_pass, const char *sub_topic);
|
||||
uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
|
||||
const char *mqtt_host, uint16_t mqtt_port,
|
||||
const char *client_id, const char *user,
|
||||
const char *pass);
|
||||
|
||||
uint8_t WIFI_MQTT_Publish_RAW(const char *topic, const uint8_t *payload,
|
||||
uint16_t length, uint8_t qos, uint8_t retain);
|
||||
|
||||
void wifi_task_mqtt(void *argument);
|
||||
uint8_t WIFI_MQTT_Publish_Sensor(const char *json);
|
||||
uint8_t WIFI_MQTT_Publish_Status(const char *json);
|
||||
|
||||
#endif /* __DX_WF_24_H__ */
|
||||
|
||||
@@ -55,7 +55,7 @@ void DebugMon_Handler(void);
|
||||
void DMA1_Channel4_IRQHandler(void);
|
||||
void DMA1_Channel5_IRQHandler(void);
|
||||
void USART1_IRQHandler(void);
|
||||
void TIM8_UP_IRQHandler(void);
|
||||
void TIM5_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
@@ -60,7 +60,7 @@ const osThreadAttr_t defaultTask_attributes = {
|
||||
osThreadId_t wifi_mqttHandle;
|
||||
const osThreadAttr_t wifi_mqtt_attributes = {
|
||||
.name = "wifi_mqtt",
|
||||
.stack_size = 1024 * 4,
|
||||
.stack_size = 3000 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh,
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@ const osThreadAttr_t wifi_mqtt_attributes = {
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
void StartDefaultTask(void *argument);
|
||||
void wifi_task_mqtt(void *argument);
|
||||
extern void wifi_task_mqtt(void *argument);
|
||||
|
||||
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
||||
|
||||
@@ -133,72 +133,11 @@ void StartDefaultTask(void *argument)
|
||||
for (;;) {
|
||||
|
||||
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
|
||||
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
|
||||
HAL_GPIO_TogglePin(MOTOR_GPIO_Port, MOTOR_Pin);
|
||||
osDelay(1000);
|
||||
}
|
||||
/* USER CODE END StartDefaultTask */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_wifi_task_mqtt */
|
||||
/**
|
||||
* @brief Function implementing the wifi_mqtt thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_wifi_task_mqtt */
|
||||
void wifi_task_mqtt(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN wifi_task_mqtt */
|
||||
WIFI_RECV_DMA_Init(); // 初始化 WiFi DMA 接收
|
||||
|
||||
/* 等待模块启动 */
|
||||
elog_i(TAG, "Waiting for WiFi module to start...");
|
||||
osDelay(3000);
|
||||
|
||||
/* 连接MQTT服务器 */
|
||||
uint8_t connect_success = WIFI_Connect_MQTT(
|
||||
"ChinaNet_WBH", // WiFi名称
|
||||
"88888888", // WiFi密码
|
||||
"broker.emqx.io", // MQTT服务器
|
||||
1883, // MQTT端口
|
||||
"STM32_MQTT", // 客户端ID
|
||||
NULL, // MQTT用户名(NULL表示无需认证)
|
||||
NULL, // MQTT密码(NULL表示无需认证)
|
||||
"pet/control" // 订阅主题
|
||||
);
|
||||
|
||||
|
||||
if (connect_success) {
|
||||
elog_i(TAG, "MQTT connection successful!");
|
||||
} else {
|
||||
elog_e(TAG, "MQTT connection failed!");
|
||||
// 可以在这里添加失败处理,如重启模块或重试
|
||||
}
|
||||
|
||||
uint8_t rx_data[WIFI_RX_BUF_SIZE];
|
||||
/* Infinite loop */
|
||||
for (;;) {
|
||||
/* 检查并处理接收数据 */
|
||||
if (wifi.rx_flag) {
|
||||
int len = WIFI_Get_Received_Data(rx_data, sizeof(rx_data));
|
||||
if (len > 0) {
|
||||
// 处理 WiFi 返回数据
|
||||
elog_d(TAG, "WiFi response: %s", rx_data);
|
||||
|
||||
// 检查MQTT消息
|
||||
if (strstr((char*)rx_data, "+MQTTPUBLISH")) {
|
||||
elog_i(TAG, "Received MQTT message!");
|
||||
// TODO: 解析并处理MQTT消息
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osDelay(100);
|
||||
}
|
||||
/* USER CODE END wifi_task_mqtt */
|
||||
}
|
||||
|
||||
/* Private application code --------------------------------------------------*/
|
||||
/* USER CODE BEGIN Application */
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ void MX_GPIO_Init(void)
|
||||
|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED1_Pin, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED1_Pin, GPIO_PIN_SET);
|
||||
|
||||
/*Configure GPIO pins : KEY1_Pin KEY2_Pin KEY3_Pin KEY3C3_Pin */
|
||||
GPIO_InitStruct.Pin = KEY1_Pin|KEY2_Pin|KEY3_Pin|KEY3C3_Pin;
|
||||
|
||||
@@ -182,7 +182,7 @@ void SystemClock_Config(void)
|
||||
|
||||
/**
|
||||
* @brief Period elapsed callback in non blocking mode
|
||||
* @note This function is called when TIM8 interrupt took place, inside
|
||||
* @note This function is called when TIM5 interrupt took place, inside
|
||||
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
|
||||
* a global variable "uwTick" used as application time base.
|
||||
* @param htim : TIM handle
|
||||
@@ -193,7 +193,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
||||
/* USER CODE BEGIN Callback 0 */
|
||||
|
||||
/* USER CODE END Callback 0 */
|
||||
if (htim->Instance == TIM8) {
|
||||
if (htim->Instance == TIM5) {
|
||||
HAL_IncTick();
|
||||
}
|
||||
/* USER CODE BEGIN Callback 1 */
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
TIM_HandleTypeDef htim8;
|
||||
TIM_HandleTypeDef htim5;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void TIM8_IRQHandler(void);
|
||||
void TIM5_IRQHandler(void);
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the TIM8 as a time base source.
|
||||
* @brief This function configures the TIM5 as a time base source.
|
||||
* The time source is configured to have 1ms time base with a dedicated
|
||||
* Tick interrupt priority.
|
||||
* @note This function is called automatically at the beginning of program after
|
||||
@@ -42,55 +42,64 @@ void TIM8_IRQHandler(void);
|
||||
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
RCC_ClkInitTypeDef clkconfig;
|
||||
uint32_t uwTimclock = 0U;
|
||||
uint32_t uwTimclock, uwAPB1Prescaler = 0U;
|
||||
|
||||
uint32_t uwPrescalerValue = 0U;
|
||||
uint32_t pFLatency;
|
||||
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Enable TIM8 clock */
|
||||
__HAL_RCC_TIM8_CLK_ENABLE();
|
||||
/* Enable TIM5 clock */
|
||||
__HAL_RCC_TIM5_CLK_ENABLE();
|
||||
|
||||
/* Get clock configuration */
|
||||
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
|
||||
|
||||
/* Compute TIM8 clock */
|
||||
uwTimclock = HAL_RCC_GetPCLK2Freq();
|
||||
/* Get APB1 prescaler */
|
||||
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
|
||||
/* Compute TIM5 clock */
|
||||
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
|
||||
{
|
||||
uwTimclock = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
else
|
||||
{
|
||||
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
/* Compute the prescaler value to have TIM8 counter clock equal to 1MHz */
|
||||
/* Compute the prescaler value to have TIM5 counter clock equal to 1MHz */
|
||||
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
|
||||
|
||||
/* Initialize TIM8 */
|
||||
htim8.Instance = TIM8;
|
||||
/* Initialize TIM5 */
|
||||
htim5.Instance = TIM5;
|
||||
|
||||
/* Initialize TIMx peripheral as follow:
|
||||
|
||||
+ Period = [(TIM8CLK/1000) - 1]. to have a (1/1000) s time base.
|
||||
+ Period = [(TIM5CLK/1000) - 1]. to have a (1/1000) s time base.
|
||||
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
|
||||
+ ClockDivision = 0
|
||||
+ Counter direction = Up
|
||||
*/
|
||||
htim8.Init.Period = (1000000U / 1000U) - 1U;
|
||||
htim8.Init.Prescaler = uwPrescalerValue;
|
||||
htim8.Init.ClockDivision = 0;
|
||||
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
htim5.Init.Period = (1000000U / 1000U) - 1U;
|
||||
htim5.Init.Prescaler = uwPrescalerValue;
|
||||
htim5.Init.ClockDivision = 0;
|
||||
htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
|
||||
status = HAL_TIM_Base_Init(&htim8);
|
||||
status = HAL_TIM_Base_Init(&htim5);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Start the TIM time Base generation in interrupt mode */
|
||||
status = HAL_TIM_Base_Start_IT(&htim8);
|
||||
status = HAL_TIM_Base_Start_IT(&htim5);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the TIM8 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM8_UP_IRQn);
|
||||
/* Enable the TIM5 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM5_IRQn);
|
||||
/* Configure the SysTick IRQ priority */
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
/* Configure the TIM IRQ priority */
|
||||
HAL_NVIC_SetPriority(TIM8_UP_IRQn, TickPriority, 0U);
|
||||
HAL_NVIC_SetPriority(TIM5_IRQn, TickPriority, 0U);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
@@ -106,25 +115,25 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note Disable the tick increment by disabling TIM8 update interrupt.
|
||||
* @note Disable the tick increment by disabling TIM5 update interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable TIM8 update Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(&htim8, TIM_IT_UPDATE);
|
||||
/* Disable TIM5 update Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(&htim5, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling TIM8 update interrupt.
|
||||
* @note Enable the tick increment by Enabling TIM5 update interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
/* Enable TIM8 Update interrupt */
|
||||
__HAL_TIM_ENABLE_IT(&htim8, TIM_IT_UPDATE);
|
||||
/* Enable TIM5 Update interrupt */
|
||||
__HAL_TIM_ENABLE_IT(&htim5, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
extern DMA_HandleTypeDef hdma_usart1_tx;
|
||||
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern TIM_HandleTypeDef htim8;
|
||||
extern TIM_HandleTypeDef htim5;
|
||||
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
@@ -210,17 +210,17 @@ void USART1_IRQHandler(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM8 update interrupt.
|
||||
* @brief This function handles TIM5 global interrupt.
|
||||
*/
|
||||
void TIM8_UP_IRQHandler(void)
|
||||
void TIM5_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN TIM8_UP_IRQn 0 */
|
||||
/* USER CODE BEGIN TIM5_IRQn 0 */
|
||||
|
||||
/* USER CODE END TIM8_UP_IRQn 0 */
|
||||
HAL_TIM_IRQHandler(&htim8);
|
||||
/* USER CODE BEGIN TIM8_UP_IRQn 1 */
|
||||
/* USER CODE END TIM5_IRQn 0 */
|
||||
HAL_TIM_IRQHandler(&htim5);
|
||||
/* USER CODE BEGIN TIM5_IRQn 1 */
|
||||
|
||||
/* USER CODE END TIM8_UP_IRQn 1 */
|
||||
/* USER CODE END TIM5_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
20
hahha.ioc
20
hahha.ioc
@@ -25,7 +25,7 @@ Dma.USART1_TX.0.Priority=DMA_PRIORITY_VERY_HIGH
|
||||
Dma.USART1_TX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
|
||||
FREERTOS.FootprintOK=true
|
||||
FREERTOS.IPParameters=Tasks01,FootprintOK,configTOTAL_HEAP_SIZE
|
||||
FREERTOS.Tasks01=defaultTask,24,256,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;wifi_mqtt,40,1024,wifi_task_mqtt,Default,NULL,Dynamic,NULL,NULL
|
||||
FREERTOS.Tasks01=defaultTask,24,256,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;wifi_mqtt,40,3000,wifi_task_mqtt,As external,NULL,Dynamic,NULL,NULL
|
||||
FREERTOS.configTOTAL_HEAP_SIZE=30000
|
||||
File.Version=6
|
||||
GPIO.groupedBy=Group By Peripherals
|
||||
@@ -75,7 +75,7 @@ Mcu.Pin32=PD2
|
||||
Mcu.Pin33=PB6
|
||||
Mcu.Pin34=PB7
|
||||
Mcu.Pin35=VP_FREERTOS_VS_CMSIS_V2
|
||||
Mcu.Pin36=VP_SYS_VS_tim8
|
||||
Mcu.Pin36=VP_SYS_VS_tim5
|
||||
Mcu.Pin4=PC0
|
||||
Mcu.Pin5=PC1
|
||||
Mcu.Pin6=PC2
|
||||
@@ -103,9 +103,9 @@ NVIC.SavedPendsvIrqHandlerGenerated=true
|
||||
NVIC.SavedSvcallIrqHandlerGenerated=true
|
||||
NVIC.SavedSystickIrqHandlerGenerated=true
|
||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
|
||||
NVIC.TIM8_UP_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
|
||||
NVIC.TimeBase=TIM8_UP_IRQn
|
||||
NVIC.TimeBaseIP=TIM8
|
||||
NVIC.TIM5_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
|
||||
NVIC.TimeBase=TIM5_IRQn
|
||||
NVIC.TimeBaseIP=TIM5
|
||||
NVIC.USART1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||
PA10.Mode=Asynchronous
|
||||
@@ -141,13 +141,15 @@ PB10.Mode=Asynchronous
|
||||
PB10.Signal=USART3_TX
|
||||
PB11.Mode=Asynchronous
|
||||
PB11.Signal=USART3_RX
|
||||
PB12.GPIOParameters=GPIO_Label
|
||||
PB12.GPIOParameters=PinState,GPIO_Label
|
||||
PB12.GPIO_Label=LED2
|
||||
PB12.Locked=true
|
||||
PB12.PinState=GPIO_PIN_SET
|
||||
PB12.Signal=GPIO_Output
|
||||
PB13.GPIOParameters=GPIO_Label
|
||||
PB13.GPIOParameters=PinState,GPIO_Label
|
||||
PB13.GPIO_Label=LED1
|
||||
PB13.Locked=true
|
||||
PB13.PinState=GPIO_PIN_SET
|
||||
PB13.Signal=GPIO_Output
|
||||
PB14.GPIOParameters=GPIO_Label
|
||||
PB14.GPIO_Label=HC-SR505_IO
|
||||
@@ -287,7 +289,7 @@ USART3.IPParameters=VirtualMode
|
||||
USART3.VirtualMode=VM_ASYNC
|
||||
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
||||
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
||||
VP_SYS_VS_tim8.Mode=TIM8
|
||||
VP_SYS_VS_tim8.Signal=SYS_VS_tim8
|
||||
VP_SYS_VS_tim5.Mode=TIM5
|
||||
VP_SYS_VS_tim5.Signal=SYS_VS_tim5
|
||||
board=custom
|
||||
rtos.0.ip=FREERTOS
|
||||
|
||||
Reference in New Issue
Block a user