本次重构完成了 433MHz 全链路协议统一:实现了 AA TYPE LEN ID PAYLOAD SUM 统一帧格式;引入了基于 AUX 的 LBT 避让与 TX 优先调度,确保高频发送稳定;完成了端口语义化重命名;并成功集成了 IO 监控、RS485 及 W5500 以太网 的标准化打包转发,实现了多源数据的高效、稳定透传。
This commit is contained in:
209
Core/Src/main.c
209
Core/Src/main.c
@ -85,11 +85,89 @@ static uint8_t u1_rx_buffer[256];
|
||||
static volatile uint16_t u1_rx_len = 0;
|
||||
static volatile uint32_t u1_last_rx_time = 0;
|
||||
|
||||
/* === 485 设备的接收缓存 (UART3) 增加这三行!=== */
|
||||
/* === 485 设备的接收缓存 (UART3) === */
|
||||
static uint8_t u3_rx_buffer[512];
|
||||
static volatile uint16_t u3_rx_len = 0;
|
||||
static volatile uint32_t u3_last_rx_time = 0;
|
||||
static volatile uint32_t u3_ignore_until = 0;
|
||||
|
||||
/* === 协议处理全局变量 === */
|
||||
static uint16_t g_hb_seq = 0; /* 心跳序列号 */
|
||||
static uint32_t g_last_hb_tick = 0; /* 上次心跳时间 */
|
||||
static uint8_t g_last_io_state = 0xFF; /* 上次记录的 IO 状态,用于变化检测 */
|
||||
|
||||
/* === W5500 外部变量声明 === */
|
||||
#if USE_W5500
|
||||
extern uint16_t local_port;
|
||||
extern uint8_t ethernet_buf[];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 判断单片机与 433 模块连接的串口是否正忙于传输
|
||||
* @return bool: true=串口引擎忙(需避让), false=串口空闲
|
||||
*/
|
||||
bool RF433_UART_Is_Busy(void)
|
||||
{
|
||||
// 仅查询 UART1 的引擎状态,不关心模块 AUX
|
||||
return MultiUART_IsBusy(PORT_433);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算并发送 RF433 协议数据包
|
||||
|
||||
* @param type: 协议类型 (0x10, 0x55, 0x48, 0xAA)
|
||||
* @param payload: 载荷数据指针
|
||||
* @param len: 载荷长度
|
||||
*/
|
||||
void RF433_SendPacket(uint8_t type, const uint8_t *payload, uint8_t len)
|
||||
{
|
||||
uint8_t frame[260];
|
||||
uint16_t frame_idx = 0;
|
||||
uint8_t checksum = 0;
|
||||
|
||||
frame[frame_idx++] = PROTO_START_BYTE; // AA
|
||||
frame[frame_idx++] = type; // TYPE
|
||||
frame[frame_idx++] = (uint8_t)(len + 1); // LEN (ID + Payload)
|
||||
frame[frame_idx++] = MY_DEVICE_ID; // ID
|
||||
|
||||
if (len > 0 && payload != NULL) {
|
||||
memcpy(&frame[frame_idx], payload, len);
|
||||
frame_idx += len;
|
||||
}
|
||||
|
||||
/* 计算校验和 (Sum8) */
|
||||
for (uint16_t i = 0; i < frame_idx; i++) {
|
||||
checksum += frame[i];
|
||||
}
|
||||
frame[frame_idx++] = checksum;
|
||||
|
||||
/* 通过 MultiUART 发送 */
|
||||
MultiUART_Send(PORT_433, frame, frame_idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查 433 无线信道是否忙碌 (发送保护区)
|
||||
* @return bool: true=忙碌(需避让), false=空闲
|
||||
*/
|
||||
bool RF433_Is_Air_Busy(void)
|
||||
{
|
||||
return (HAL_GPIO_ReadPin(AUX_GPIO_Port, AUX_Pin) == GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读取当前 4 路 DI 的合并状态
|
||||
* @return uint8_t: Bit0-3 对应 DI1-4
|
||||
*/
|
||||
uint8_t IO_Get_Current_State(void)
|
||||
{
|
||||
uint8_t state = 0;
|
||||
if (HAL_GPIO_ReadPin(MCU_DI1_GPIO_Port, MCU_DI1_Pin) == GPIO_PIN_SET) state |= (1 << 0);
|
||||
if (HAL_GPIO_ReadPin(MCU_DI2_GPIO_Port, MCU_DI2_Pin) == GPIO_PIN_SET) state |= (1 << 1);
|
||||
if (HAL_GPIO_ReadPin(MCU_DI3_GPIO_Port, MCU_DI3_Pin) == GPIO_PIN_SET) state |= (1 << 2);
|
||||
if (HAL_GPIO_ReadPin(MCU_DI4_GPIO_Port, MCU_DI4_Pin) == GPIO_PIN_SET) state |= (1 << 3);
|
||||
return state;
|
||||
}
|
||||
|
||||
/* W5500 variables */
|
||||
#if USE_W5500
|
||||
#define SOCKET_ID 0
|
||||
@ -240,74 +318,36 @@ int main(void)
|
||||
/* USER CODE BEGIN WHILE */
|
||||
while (1)
|
||||
{
|
||||
/* === 1. 恢复系统的核心驱动引擎 === */
|
||||
/* === 1. 核心通信驱动引擎 (最高优先级) === */
|
||||
UART2_Print_Task();
|
||||
MultiUART_Task();
|
||||
IO_Monitor_Task();
|
||||
|
||||
/* === 2. 网络轮询任务 === */
|
||||
#if USE_W5500
|
||||
loopback_udps(SOCKET_ID, ethernet_buf, local_port);
|
||||
#endif
|
||||
|
||||
/* === 3. 极速无乱码透传 === */
|
||||
|
||||
/* === 方案 A:从 433 收到无线数据 -> 给上位机解析 === */
|
||||
/* === 2. 无线接收透传 (433 -> 485/Debug) === */
|
||||
#if (RF433_MODE == RF433_MODE_RX) || (RF433_MODE == RF433_MODE_BOTH)
|
||||
// 如果 433 收到无线数据,直接透传输出,不进行解码
|
||||
if (u1_rx_len > 0 && (HAL_GetTick() - u1_last_rx_time > 20))
|
||||
{
|
||||
static uint8_t temp_buf1[256];
|
||||
__disable_irq();
|
||||
__disable_irq();
|
||||
uint16_t len = u1_rx_len;
|
||||
memcpy(temp_buf1, (uint8_t*)u1_rx_buffer, len);
|
||||
u1_rx_len = 0;
|
||||
u1_rx_len = 0;
|
||||
__enable_irq();
|
||||
|
||||
MultiUART_Send(PORT_RS485, (uint8_t*)u1_rx_buffer, len);
|
||||
MultiUART_Send(PORT_DEBUG, (uint8_t*)u1_rx_buffer, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 🚀 终极上位机协议:[0xAA帧头] + [设备ID] + [来源接口] + [数据长度] + [纯净数据] */
|
||||
if (len >= 2 && temp_buf1[0] == 0xAA)
|
||||
{
|
||||
uint8_t sender_id = temp_buf1[1];
|
||||
uint16_t payload_len = len - 2;
|
||||
uint8_t* payload_data = &temp_buf1[2];
|
||||
|
||||
/* 默认 0x03 为 RS485 透传数据 */
|
||||
uint8_t source_type = 0x03;
|
||||
|
||||
/* 判断是不是 $DI 标签 */
|
||||
if (payload_len >= 3 && payload_data[0] == '$' && payload_data[1] == 'D' && payload_data[2] == 'I')
|
||||
{
|
||||
source_type = 0x01; /* 也是 DI 口数据,但不砍标签了,直接全发过去 */
|
||||
}
|
||||
/* 判断是不是网口 [NET] 标签 */
|
||||
else if (payload_len >= 5 && payload_data[0] == '[' && payload_data[1] == 'N' && payload_data[2] == 'E' && payload_data[3] == 'T' && payload_data[4] == ']')
|
||||
{
|
||||
source_type = 0x02; /* 0x02 代表是 网络口 收到的数据 */
|
||||
payload_data += 5; /* 砍掉 "[NET]" 标签 */
|
||||
payload_len -= 5;
|
||||
}
|
||||
/* ========================================================== */
|
||||
/* === 3. 核心发送保护区 (TX 优先调度) === */
|
||||
// 只有当我们单片机正在往 433 模块灌数时,才进行避让
|
||||
// 只要单片机串口引擎一空闲,主循环就立刻开始处理后续采集任务
|
||||
if (RF433_UART_Is_Busy()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (payload_len > 0) {
|
||||
/* 重新组装终极协议帧 */
|
||||
uint8_t upper_buf[260];
|
||||
upper_buf[0] = 0xAA; // Byte 0: 魔法帧头
|
||||
upper_buf[1] = sender_id; // Byte 1: 发送设备 ID
|
||||
upper_buf[2] = source_type; // Byte 2: 数据来源 (1=DI, 2=NET, 3=485)
|
||||
upper_buf[3] = (uint8_t)payload_len; // Byte 3: 真实数据长度
|
||||
memcpy(&upper_buf[4], payload_data, payload_len); // Byte 4~末尾: 绝对纯净的数据
|
||||
|
||||
/* 发送给 485 和电脑上位机 */
|
||||
MultiUART_Send(PORT_UART3, upper_buf, payload_len + 4);
|
||||
MultiUART_Send(PORT_UART2, upper_buf, payload_len + 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 普通无帧头干扰数据,按原样透传 */
|
||||
MultiUART_Send(PORT_UART3, temp_buf1, len);
|
||||
MultiUART_Send(PORT_UART2, temp_buf1, len);
|
||||
}
|
||||
|
||||
/* === 方案 B:从 485 收到设备数据 -> 穿上包装(附加ID) -> 通过 433 无线发射 === */
|
||||
/* === 4. 实时数据采集与上报 (仅在非发射状态运行) === */
|
||||
|
||||
// (A) 485 来源数据处理 (Type 0x48)
|
||||
#if USE_RS485
|
||||
if (u3_rx_len > 0 && (HAL_GetTick() - u3_last_rx_time > 20))
|
||||
{
|
||||
static uint8_t temp_buf3[512];
|
||||
@ -317,20 +357,45 @@ int main(void)
|
||||
u3_rx_len = 0;
|
||||
__enable_irq();
|
||||
|
||||
/* 🚀 制作“快递包”:在最前面加上 [0xAA] 和 [本机ID] */
|
||||
static uint8_t rf_tx_buf[515];
|
||||
rf_tx_buf[0] = 0xAA; // 贴上魔法帧头
|
||||
rf_tx_buf[1] = MY_DEVICE_ID; // 贴上本机的身份证号
|
||||
memcpy(&rf_tx_buf[2], temp_buf3, len); // 把 485 收到的真实数据塞进后面
|
||||
|
||||
/* 把带有身份证的完整包裹,通过 433 发射到空气中 */
|
||||
MultiUART_Send(PORT_UART1, rf_tx_buf, len + 2);
|
||||
RF433_SendPacket(PROTO_TYPE_485, temp_buf3, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
// (B) I/O 状态监控与变化上报 (Type 0x10)
|
||||
#if USE_IO_MONITOR
|
||||
IO_Monitor_Task(); // 执行去抖扫描
|
||||
uint8_t current_io = IO_Monitor_GetAllStates();
|
||||
if (current_io != g_last_io_state) {
|
||||
if (g_last_io_state == 0xFF) {
|
||||
g_last_io_state = current_io;
|
||||
} else {
|
||||
g_last_io_state = current_io;
|
||||
RF433_SendPacket(PROTO_TYPE_IO, ¤t_io, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// (C) 30秒系统心跳包 (Type 0xAA)
|
||||
#if USE_IO_MONITOR
|
||||
if (HAL_GetTick() - g_last_hb_tick >= 30000) {
|
||||
g_last_hb_tick = HAL_GetTick();
|
||||
uint8_t hb_payload[3];
|
||||
hb_payload[0] = IO_Monitor_GetAllStates();
|
||||
hb_payload[1] = (uint8_t)(g_hb_seq >> 8);
|
||||
hb_payload[2] = (uint8_t)(g_hb_seq & 0xFF);
|
||||
g_hb_seq++;
|
||||
|
||||
RF433_SendPacket(PROTO_TYPE_HB, hb_payload, 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
// (D) W5500 以太网轮询处理 (Type 0x55)
|
||||
#if USE_W5500
|
||||
loopback_udps(SOCKET_ID, ethernet_buf, local_port);
|
||||
#endif
|
||||
|
||||
/* USER CODE END WHILE */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* USER CODE END 3 */
|
||||
/**
|
||||
* @brief System Clock Configuration
|
||||
@ -433,7 +498,7 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
/* 调用多UART路由器的UART1发送完成回调 */
|
||||
MultiUART_TxCpltCallback(PORT_UART1);
|
||||
MultiUART_TxCpltCallback(PORT_433);
|
||||
}
|
||||
else if (huart->Instance == USART2)
|
||||
{
|
||||
@ -444,7 +509,7 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
|
||||
/* 调用多UART路由器的UART3发送完成回调 */
|
||||
MultiUART_TxCpltCallback(PORT_UART3);
|
||||
MultiUART_TxCpltCallback(PORT_RS485);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user