From 6e2b13dbb3682a75ee204d93d0136e8ead94db59 Mon Sep 17 00:00:00 2001 From: zhongxuanzhen Date: Fri, 8 May 2026 18:49:05 +0800 Subject: [PATCH] =?UTF-8?q?"=E5=AE=8C=E6=88=90=E4=BA=86433=E5=A4=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=90=8C=E6=97=B6=E6=8E=A5=E6=94=B6=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=80=99=E7=9A=84=E5=86=B2=E7=AA=81=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E8=A7=A3=E5=86=B3=E4=BA=86=E7=BD=91=E7=BB=9C=E6=9C=AA?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E4=BC=9A=E5=8D=A1=E6=AD=BB=E6=95=B4=E4=B8=AA?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=9A=84=E9=97=AE=E9=A2=98=E2=80=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Inc/main.h | 2 +- Core/Inc/multi_uart_router.h | 2 + Core/Src/main.c | 8 ++-- Core/Src/multi_uart_router.c | 27 +++++++++++-- User/wiz_interface/wiz_interface.c | 61 ++++++++++++++++-------------- docs/报文.md | 14 +++---- 6 files changed, 71 insertions(+), 43 deletions(-) diff --git a/Core/Inc/main.h b/Core/Inc/main.h index 5397fbd..5729154 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -73,7 +73,7 @@ extern "C" { 🚀 核心身份标识:烧录不同设备时,请务必修改这个数字! 比如:设备A烧录时改为 0x01,设备B烧录时改为 0x02 ========================================================= */ -#define MY_DEVICE_ID 0x01 +#define MY_DEVICE_ID 0x02 /* USER CODE END EM */ /* Exported functions prototypes ---------------------------------------------*/ diff --git a/Core/Inc/multi_uart_router.h b/Core/Inc/multi_uart_router.h index 113e6dc..d9f0e87 100644 --- a/Core/Inc/multi_uart_router.h +++ b/Core/Inc/multi_uart_router.h @@ -64,6 +64,8 @@ typedef struct { uint32_t tx_count; uint32_t error_count; bool initialized; + volatile bool csma_backoff_active; + volatile uint32_t csma_backoff_until; } uart_port_context_t; void MultiUART_Init(void); diff --git a/Core/Src/main.c b/Core/Src/main.c index 9d5ac97..e75c85b 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -125,10 +125,10 @@ void RF433_SendPacket(uint8_t type, const uint8_t *payload, uint8_t len) 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 + frame[frame_idx++] = PROTO_START_BYTE; // AA + frame[frame_idx++] = type; // TYPE + frame[frame_idx++] = (uint8_t)(len + 1 + 1); // LEN (ID + Payload + SUM) + frame[frame_idx++] = MY_DEVICE_ID; // ID if (len > 0 && payload != NULL) { memcpy(&frame[frame_idx], payload, len); diff --git a/Core/Src/multi_uart_router.c b/Core/Src/multi_uart_router.c index 1114952..4a7bfe0 100644 --- a/Core/Src/multi_uart_router.c +++ b/Core/Src/multi_uart_router.c @@ -42,6 +42,16 @@ #define DEBUG_LOG(fmt, ...) #endif +/*============================================================================== + * CSMA/CA 随机退避相关 + *============================================================================*/ +static uint32_t csma_rand(uint32_t seed) +{ + // static uint32_t seed = 12345; + seed = seed * 1103515245 + 12345; + return (seed >> 16) & 0x7FFF; +} + /*============================================================================== * 全局变量定义 *============================================================================*/ @@ -235,16 +245,23 @@ static void tx_kickoff(port_id_t port_id) __disable_irq(); if (!ring->is_sending && ring->count > 0) { - /* --- 核心修复:针对 RF433 (UART1) 执行包级 LBT 检查 --- */ if (port_id == PORT_433) { - // 如果 AUX 为低电平,说明信道忙(接收中或正在发送前一包),暂缓起步 + if (ctx->csma_backoff_active) { + if ((int32_t)(HAL_GetTick() - ctx->csma_backoff_until) < 0) { + __enable_irq(); + return; + } + ctx->csma_backoff_active = false; + } + if (HAL_GPIO_ReadPin(AUX_GPIO_Port, AUX_Pin) == GPIO_PIN_RESET) { + ctx->csma_backoff_active = true; + ctx->csma_backoff_until = HAL_GetTick() + (csma_rand(HAL_GetTick()) % 1000) + 1; __enable_irq(); return; } } - /* 取出下一个待发送字节 */ byte = ring->buffer[ring->tail]; ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE; ring->count--; @@ -297,6 +314,10 @@ void MultiUART_Init(void) ctx->tx_count = 0; ctx->error_count = 0; ctx->initialized = true; + + /* 初始化 CSMA/CA 随机退避状态 */ + ctx->csma_backoff_active = false; + ctx->csma_backoff_until = 0; } DEBUG_LOG("Init OK, %d ports configured", PORT_COUNT); diff --git a/User/wiz_interface/wiz_interface.c b/User/wiz_interface/wiz_interface.c index ddb216c..62e2d23 100644 --- a/User/wiz_interface/wiz_interface.c +++ b/User/wiz_interface/wiz_interface.c @@ -2,6 +2,7 @@ #include "wiz_platform.h" #include "wizchip_conf.h" #include "dhcp.h" +#include "main.h" #include #include #include @@ -93,57 +94,60 @@ void wiz_delete_timer(void (*func)(void)) } /** - * @brief wiz timer event handler + * @brief wiz timer event handler (using HAL_GetTick) * * You must add this function to your 1ms timer interrupt * */ void wiz_timer_handler(void) { + static uint32_t last_tick = 0; + uint32_t current_tick = HAL_GetTick(); - wiz_delay_ms_count++; - struct wiz_timer *temp = wiz_timer_head; - while (temp != NULL) - { - temp->count_time++; - if (temp->count_time >= temp->trigger_time) + if (current_tick != last_tick) { + last_tick = current_tick; + struct wiz_timer *temp = wiz_timer_head; + while (temp != NULL) { - temp->count_time = 0; - temp->func(); + temp->count_time++; + if (temp->count_time >= temp->trigger_time) + { + temp->count_time = 0; + temp->func(); + } + temp = temp->next; } - temp = temp->next; } } /** - * @brief Delay function in milliseconds + * @brief Delay function in milliseconds (using HAL_GetTick) * @param nms :Delay Time */ void wiz_user_delay_ms(uint32_t nms) { - wiz_delay_ms_count = 0; - while (wiz_delay_ms_count < nms) - { + uint32_t start = HAL_GetTick(); + while ((HAL_GetTick() - start) < nms) { } } /** - * @brief Check the WIZCHIP version + * @brief Check the WIZCHIP version (with timeout) */ void wizchip_version_check(void) { uint8_t error_count = 0; - while (1) + uint32_t start_tick = HAL_GetTick(); + while ((HAL_GetTick() - start_tick) < 5000) { - wiz_user_delay_ms(1000); + wiz_user_delay_ms(100); if (getVERSIONR() != W5500_VERSION) { error_count++; if (error_count > 5) { - printf("error, W5500 version is 0x%02x, but read W5500 version value = 0x%02x\r\n", W5500_VERSION, getVERSIONR()); - while (1) - ; + printf("WARN: W5500 version check failed, SPI may be disconnected\r\n"); + break; } } else @@ -165,25 +169,26 @@ void wiz_print_phy_info(void) } /** - * @brief Ethernet Link Detection + * @brief Ethernet Link Detection (with timeout) */ void wiz_phy_link_check(void) { uint8_t phy_link_status; - do + uint32_t start_tick = HAL_GetTick(); + + while ((HAL_GetTick() - start_tick) < 10000) { - wiz_user_delay_ms(1000); + wiz_user_delay_ms(500); ctlwizchip(CW_GET_PHYLINK, (void *)&phy_link_status); if (phy_link_status == PHY_LINK_ON) { printf("PHY link\r\n"); wiz_print_phy_info(); + return; } - else - { - printf("PHY no link\r\n"); - } - } while (phy_link_status == PHY_LINK_OFF); + } + + printf("WARN: PHY link timeout, using static config\r\n"); } /** diff --git a/docs/报文.md b/docs/报文.md index 44cc1b5..d384efd 100644 --- a/docs/报文.md +++ b/docs/报文.md @@ -13,7 +13,7 @@ AA TYPE LEN ID [PAYLOAD] SUM | | | | | +-- 校验和:从 AA 到 PAYLOAD 结束的所有字节累加和 (取低8位) | | | | +---------- 载荷数据:具体的业务数据内容 | | | +------------------ 设备 ID:当前发送设备的唯一标识 (MY_DEVICE_ID) - | | +---------------------- 长度:指明后续 [ID + PAYLOAD] 的总字节数 + | | +---------------------- 长度:指明后续 [ID + PAYLOAD + SUM] 的总字节数 | +--------------------------- 数据类型:区分数据来源 (10, 55, 48, AA) +-------------------------------- 起始符:固定为 0xAA ``` @@ -26,13 +26,13 @@ AA TYPE LEN ID [PAYLOAD] SUM 当板载 4 路数字输入 (DI) 电平发生变化时,立即发送此包。 ```text -AA 10 02 ID XX SUM +AA 10 03 ID XX SUM -- -- -- -- -- --- | | | | | | | | | | | +-- 校验和 | | | | +------ I/O 状态位 (Bit0:DI1, Bit1:DI2, Bit2:DI3, Bit3:DI4) | | | +---------- 本机设备 ID - | | +-------------- 长度固定为 0x02 (ID + 1字节状态) + | | +-------------- 长度固定为 0x03 (ID + 1字节状态 + SUM) | +------------------ 类型标识:0x10 (I/O Data) +---------------------- 固定起始符 ``` @@ -47,7 +47,7 @@ AA 48 LEN ID [DATA] SUM | | | | | +-- 校验和 | | | | +--------- RS485 原始数据内容 | | | +--------------- 本机设备 ID - | | +------------------- 长度:(1 + 原始数据长度) + | | +------------------- 长度:(1 + 原始数据长度 + SUM) | +----------------------- 类型标识:0x48 (RS485 Data) +--------------------------- 固定起始符 ``` @@ -62,7 +62,7 @@ AA 55 LEN ID [DATA] SUM | | | | | +-- 校验和 | | | | +--------- 网络原始数据内容 | | | +--------------- 本机设备 ID - | | +------------------- 长度:(1 + 原始数据长度) + | | +------------------- 长度:(1 + 原始数据长度 + SUM) | +----------------------- 类型标识:0x55 (Net Data) +--------------------------- 固定起始符 ``` @@ -71,14 +71,14 @@ AA 55 LEN ID [DATA] SUM 系统定时上报当前存活状态,包含当前的 I/O 状态及防丢包序列号。 ```text -AA AA 04 ID [IO] [SEQ_H] [SEQ_L] SUM +AA AA 05 ID [IO] [SEQ_H] [SEQ_L] SUM -- -- -- -- ---- ------- ------- --- | | | | | | | | | | | | | | | +-- 校验和 | | | | | +-------+-------- 2字节序列号 (0-65535, 循环自增) | | | | +----------------------- 当前 4 路 I/O 状态位 | | | +---------------------------- 本机设备 ID - | | +-------------------------------- 长度固定为 0x04 (ID + 3字节Payload) + | | +-------------------------------- 长度固定为 0x05 (ID + 3字节Payload + SUM) | +------------------------------------ 类型标识:0xAA (Heartbeat) +---------------------------------------- 固定起始符 ```