基本完成的所有收发功能

This commit is contained in:
2026-05-07 17:47:52 +08:00
parent 61530dccec
commit f05c3106f1
82 changed files with 3008 additions and 4922 deletions

View File

@ -196,31 +196,28 @@ static void send_di_event(uint8_t channel, uint8_t state)
char msg[32];
uint8_t cs;
/* 构造消息主体channel+1将0-base转换为1-base的用户可见编号 */
int len = snprintf(msg, sizeof(msg), "$DI_EVENT,%d,%d,%d*", channel + 1, state, SOURCE_DI);
/* 计算异或校验和,跳过'$'符号只对正文部分计算 */
cs = calc_checksum(msg + 1, len - 1);
/* 将校验和追加到消息末尾,格式为两位十六进制数 */
snprintf(msg + len, sizeof(msg) - len, "%02X\r\n", cs);
/* 输出调试日志到UART2记录状态变化 */
DEBUG_LOG("CH%d -> %s", channel + 1, state ? "HIGH" : "LOW");
/*----------------------------------------------------------
* 向UART1(RF433模块)发送状态变化事件
* 这是IO事件的主要路由通道用于无线上报到上位机
*----------------------------------------------------------*/
MultiUART_SendString(PORT_UART1, msg);
/* ==========================================================
🚀 核心修改:不再直接发送 msg而是套上 [0xAA] 和 [ID] 的外衣
========================================================== */
uint8_t rf_tx_buf[64];
rf_tx_buf[0] = 0xAA; // 贴上魔法帧头
rf_tx_buf[1] = MY_DEVICE_ID; // 贴上本机的身份证号 (来自 main.h)
uint16_t msg_len = strlen(msg);
memcpy(&rf_tx_buf[2], msg, msg_len); // 把真正的 DI 消息塞到第 2 个字节后面
/* 将带 ID 的完整包裹发送给 433 模块 */
MultiUART_Send(PORT_UART1, rf_tx_buf, msg_len + 2);
/* ========================================================== */
/* 输出完整消息到UART2方便调试查看 */
DEBUG_LOG("RF433 TX: \"%s\"", msg);
/*----------------------------------------------------------
* 如果设置了回调函数,也通过回调发送
* 用于支持额外的自定义处理逻辑
*----------------------------------------------------------*/
if (g_event_callback != NULL) {
g_event_callback(channel, state, msg);
}

View File

@ -89,7 +89,7 @@ static volatile uint32_t u1_last_rx_time = 0;
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;
/* W5500 variables */
#if USE_W5500
#define SOCKET_ID 0
@ -233,62 +233,77 @@ int main(void)
#if USE_W5500
loopback_udps(SOCKET_ID, ethernet_buf, local_port);
#endif
// /* 强行拉低 M0 和 M1叫醒 433 模块处于透传模式! */
// HAL_GPIO_WritePin(M0_GPIO_Port, M0_Pin, GPIO_PIN_RESET);
// HAL_GPIO_WritePin(GPIOB, M1_Pin, GPIO_PIN_RESET);
// /* ⚠️ 致命修复:网络被注释后,单片机启动太快。
// 433模块从休眠到唤醒至少需要几百毫秒。
// 必须改成 1000 毫秒,给硬件足够的缓冲时间! */
// HAL_Delay(1000);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* ==========================================================
第一部分:恢复系统的核心驱动引擎 (解决网络和端口不传数据的问题)
========================================================== */
UART2_Print_Task(); // 引擎负责把串口2的缓存发出去
MultiUART_Task(); // 引擎:负责网络分发、多串口异步发送 (极其重要!)
IO_Monitor_Task();
/* 如果你的网络指令需要解析,取消下面两行的注释 */
// CmdRouter_Task();
// CmdParser_Task();
/* === 1. 恢复系统的核心驱动引擎 === */
UART2_Print_Task();
MultiUART_Task();
IO_Monitor_Task();
/* ==========================================================
第二部分:网络轮询任务
========================================================== */
/* === 2. 网络轮询任务 === */
#if USE_W5500
loopback_udps(SOCKET_ID, ethernet_buf, local_port);
#endif
/* ==========================================================
第三部分:非阻塞无乱码透传 (解决485卡顿漏数据的问题)
========================================================== */
/* === 3. 极速无乱码透传 === */
/* 1. 从 433 收到无线数据 -> 给 485 */
/* === 方案 A从 433 收到无线数据 -> 拆包提取ID -> 纯净透传给 485 === */
if (u1_rx_len > 0 && (HAL_GetTick() - u1_last_rx_time > 20))
{
/* 改用 MultiUART_Send它会把数据瞬间丢进发送队列耗时0毫秒绝不卡顿单片机 */
MultiUART_Send(PORT_UART3, (uint8_t*)u1_rx_buffer, u1_rx_len);
/* 顺便发给串口2监控 */
MultiUART_Send(PORT_UART2, (uint8_t*)u1_rx_buffer, u1_rx_len);
u1_rx_len = 0; /* 清空缓存 */
static uint8_t temp_buf1[256];
__disable_irq();
uint16_t len = u1_rx_len;
memcpy(temp_buf1, (uint8_t*)u1_rx_buffer, len);
u1_rx_len = 0;
__enable_irq();
/* 🚀 解析“快递单”检查数据长度并且第0个字节必须是我们定义的魔法帧头 0xAA */
if (len >= 2 && temp_buf1[0] == 0xAA)
{
uint8_t sender_id = temp_buf1[1]; // 提取发件人的身份证
uint16_t real_len = len - 2; // 扒掉2个字节的衣服后真实数据的长度
uint8_t* real_data = &temp_buf1[2]; // 真实数据的起始指针
/* 【追踪器】打印出来:知道是哪个设备发来的! */
printf("\r\n[DEBUG] 收到来自 设备[%d] 的消息, 有效数据长度: %d 字节!\r\n", sender_id, real_len);
/* 只把干净的真实数据发给 485 设备,绝不能把 0xAA 和 ID 发给 485否则外部设备会乱码 */
if (real_len > 0) {
MultiUART_Send(PORT_UART3, real_data, real_len);
MultiUART_Send(PORT_UART2, real_data, real_len); // 电脑监控原始数据
}
}
else
{
/* 如果没有匹配上帧头(比如收到了环境干扰乱码),直接按原样丢弃或透传 */
MultiUART_Send(PORT_UART3, temp_buf1, len);
MultiUART_Send(PORT_UART2, temp_buf1, len);
}
}
/* 2. 从 485 收到设备数据 -> 通过 433 无线发射 */
/* === 方案 B从 485 收到设备数据 -> 穿上包装(附加ID) -> 通过 433 无线发射 === */
if (u3_rx_len > 0 && (HAL_GetTick() - u3_last_rx_time > 20))
{
MultiUART_Send(PORT_UART1, (uint8_t*)u3_rx_buffer, u3_rx_len);
/* 【可选进阶】如果你希望网络端比如电脑上的UDP助手也能收到485传来的数据
你可以在这里调用你的网络发送函数,把 u3_rx_buffer 发给网口 */
u3_rx_len = 0; /* 清空缓存 */
static uint8_t temp_buf3[512];
__disable_irq();
uint16_t len = u3_rx_len;
memcpy(temp_buf3, (uint8_t*)u3_rx_buffer, len);
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 发射到空气中 (长度要 +2) */
MultiUART_Send(PORT_UART1, rf_tx_buf, len + 2);
}
/* USER CODE END WHILE */
@ -349,6 +364,7 @@ void SystemClock_Config(void)
/* USER CODE BEGIN 4 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) {
@ -357,8 +373,11 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
HAL_UART_Receive_IT(&huart1, &rf433_uart_rx_tmp, 1);
}
else if (huart->Instance == USART3) {
if (u3_rx_len < sizeof(u3_rx_buffer)) u3_rx_buffer[u3_rx_len++] = uart3_rx_byte;
u3_last_rx_time = HAL_GetTick();
/* 🚀 核心生效区:只有当单片机没有在发送数据时(度过屏蔽期),才允许接收 */
if (HAL_GetTick() >= u3_ignore_until) {
if (u3_rx_len < sizeof(u3_rx_buffer)) u3_rx_buffer[u3_rx_len++] = uart3_rx_byte;
u3_last_rx_time = HAL_GetTick();
}
HAL_UART_Receive_IT(&huart3, &uart3_rx_byte, 1);
}
else if (huart->Instance == USART2) {

View File

@ -100,7 +100,7 @@ void MX_USART3_UART_Init(void)
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200; /* 从 9600 修改为 115200 */
huart3.Init.BaudRate = 4800; /* 从 9600 修改为 115200 */
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;