"完成了433多数据同时接收的时候的冲突问题,解决了网络未连接会卡死整个程序的问题“

This commit is contained in:
2026-05-08 18:49:05 +08:00
parent 6c56fe8a60
commit 6e2b13dbb3
6 changed files with 71 additions and 43 deletions

View File

@ -73,7 +73,7 @@ extern "C" {
🚀 核心身份标识:烧录不同设备时,请务必修改这个数字! 🚀 核心身份标识:烧录不同设备时,请务必修改这个数字!
比如设备A烧录时改为 0x01设备B烧录时改为 0x02 比如设备A烧录时改为 0x01设备B烧录时改为 0x02
========================================================= */ ========================================================= */
#define MY_DEVICE_ID 0x01 #define MY_DEVICE_ID 0x02
/* USER CODE END EM */ /* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/ /* Exported functions prototypes ---------------------------------------------*/

View File

@ -64,6 +64,8 @@ typedef struct {
uint32_t tx_count; uint32_t tx_count;
uint32_t error_count; uint32_t error_count;
bool initialized; bool initialized;
volatile bool csma_backoff_active;
volatile uint32_t csma_backoff_until;
} uart_port_context_t; } uart_port_context_t;
void MultiUART_Init(void); void MultiUART_Init(void);

View File

@ -127,7 +127,7 @@ void RF433_SendPacket(uint8_t type, const uint8_t *payload, uint8_t len)
frame[frame_idx++] = PROTO_START_BYTE; // AA frame[frame_idx++] = PROTO_START_BYTE; // AA
frame[frame_idx++] = type; // TYPE frame[frame_idx++] = type; // TYPE
frame[frame_idx++] = (uint8_t)(len + 1); // LEN (ID + Payload) frame[frame_idx++] = (uint8_t)(len + 1 + 1); // LEN (ID + Payload + SUM)
frame[frame_idx++] = MY_DEVICE_ID; // ID frame[frame_idx++] = MY_DEVICE_ID; // ID
if (len > 0 && payload != NULL) { if (len > 0 && payload != NULL) {

View File

@ -42,6 +42,16 @@
#define DEBUG_LOG(fmt, ...) #define DEBUG_LOG(fmt, ...)
#endif #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(); __disable_irq();
if (!ring->is_sending && ring->count > 0) { if (!ring->is_sending && ring->count > 0) {
/* --- 核心修复:针对 RF433 (UART1) 执行包级 LBT 检查 --- */
if (port_id == PORT_433) { 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) { 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(); __enable_irq();
return; return;
} }
} }
/* 取出下一个待发送字节 */
byte = ring->buffer[ring->tail]; byte = ring->buffer[ring->tail];
ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE; ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE;
ring->count--; ring->count--;
@ -297,6 +314,10 @@ void MultiUART_Init(void)
ctx->tx_count = 0; ctx->tx_count = 0;
ctx->error_count = 0; ctx->error_count = 0;
ctx->initialized = true; ctx->initialized = true;
/* 初始化 CSMA/CA 随机退避状态 */
ctx->csma_backoff_active = false;
ctx->csma_backoff_until = 0;
} }
DEBUG_LOG("Init OK, %d ports configured", PORT_COUNT); DEBUG_LOG("Init OK, %d ports configured", PORT_COUNT);

View File

@ -2,6 +2,7 @@
#include "wiz_platform.h" #include "wiz_platform.h"
#include "wizchip_conf.h" #include "wizchip_conf.h"
#include "dhcp.h" #include "dhcp.h"
#include "main.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -93,15 +94,18 @@ 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 * You must add this function to your 1ms timer interrupt
* *
*/ */
void wiz_timer_handler(void) void wiz_timer_handler(void)
{ {
static uint32_t last_tick = 0;
uint32_t current_tick = HAL_GetTick();
wiz_delay_ms_count++; if (current_tick != last_tick) {
last_tick = current_tick;
struct wiz_timer *temp = wiz_timer_head; struct wiz_timer *temp = wiz_timer_head;
while (temp != NULL) while (temp != NULL)
{ {
@ -114,36 +118,36 @@ void wiz_timer_handler(void)
temp = temp->next; temp = temp->next;
} }
} }
}
/** /**
* @brief Delay function in milliseconds * @brief Delay function in milliseconds (using HAL_GetTick)
* @param nms :Delay Time * @param nms :Delay Time
*/ */
void wiz_user_delay_ms(uint32_t nms) void wiz_user_delay_ms(uint32_t nms)
{ {
wiz_delay_ms_count = 0; uint32_t start = HAL_GetTick();
while (wiz_delay_ms_count < nms) while ((HAL_GetTick() - start) < nms) {
{
} }
} }
/** /**
* @brief Check the WIZCHIP version * @brief Check the WIZCHIP version (with timeout)
*/ */
void wizchip_version_check(void) void wizchip_version_check(void)
{ {
uint8_t error_count = 0; 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) if (getVERSIONR() != W5500_VERSION)
{ {
error_count++; error_count++;
if (error_count > 5) if (error_count > 5)
{ {
printf("error, W5500 version is 0x%02x, but read W5500 version value = 0x%02x\r\n", W5500_VERSION, getVERSIONR()); printf("WARN: W5500 version check failed, SPI may be disconnected\r\n");
while (1) break;
;
} }
} }
else 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) void wiz_phy_link_check(void)
{ {
uint8_t phy_link_status; 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); ctlwizchip(CW_GET_PHYLINK, (void *)&phy_link_status);
if (phy_link_status == PHY_LINK_ON) if (phy_link_status == PHY_LINK_ON)
{ {
printf("PHY link\r\n"); printf("PHY link\r\n");
wiz_print_phy_info(); 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");
} }
/** /**

View File

@ -13,7 +13,7 @@ AA TYPE LEN ID [PAYLOAD] SUM
| | | | | +-- 校验和:从 AA 到 PAYLOAD 结束的所有字节累加和 (取低8位) | | | | | +-- 校验和:从 AA 到 PAYLOAD 结束的所有字节累加和 (取低8位)
| | | | +---------- 载荷数据:具体的业务数据内容 | | | | +---------- 载荷数据:具体的业务数据内容
| | | +------------------ 设备 ID当前发送设备的唯一标识 (MY_DEVICE_ID) | | | +------------------ 设备 ID当前发送设备的唯一标识 (MY_DEVICE_ID)
| | +---------------------- 长度:指明后续 [ID + PAYLOAD] 的总字节数 | | +---------------------- 长度:指明后续 [ID + PAYLOAD + SUM] 的总字节数
| +--------------------------- 数据类型:区分数据来源 (10, 55, 48, AA) | +--------------------------- 数据类型:区分数据来源 (10, 55, 48, AA)
+-------------------------------- 起始符:固定为 0xAA +-------------------------------- 起始符:固定为 0xAA
``` ```
@ -26,13 +26,13 @@ AA TYPE LEN ID [PAYLOAD] SUM
当板载 4 路数字输入 (DI) 电平发生变化时,立即发送此包。 当板载 4 路数字输入 (DI) 电平发生变化时,立即发送此包。
```text ```text
AA 10 02 ID XX SUM AA 10 03 ID XX SUM
-- -- -- -- -- --- -- -- -- -- -- ---
| | | | | | | | | | | |
| | | | | +-- 校验和 | | | | | +-- 校验和
| | | | +------ I/O 状态位 (Bit0:DI1, Bit1:DI2, Bit2:DI3, Bit3:DI4) | | | | +------ I/O 状态位 (Bit0:DI1, Bit1:DI2, Bit2:DI3, Bit3:DI4)
| | | +---------- 本机设备 ID | | | +---------- 本机设备 ID
| | +-------------- 长度固定为 0x02 (ID + 1字节状态) | | +-------------- 长度固定为 0x03 (ID + 1字节状态 + SUM)
| +------------------ 类型标识0x10 (I/O Data) | +------------------ 类型标识0x10 (I/O Data)
+---------------------- 固定起始符 +---------------------- 固定起始符
``` ```
@ -47,7 +47,7 @@ AA 48 LEN ID [DATA] SUM
| | | | | +-- 校验和 | | | | | +-- 校验和
| | | | +--------- RS485 原始数据内容 | | | | +--------- RS485 原始数据内容
| | | +--------------- 本机设备 ID | | | +--------------- 本机设备 ID
| | +------------------- 长度:(1 + 原始数据长度) | | +------------------- 长度:(1 + 原始数据长度 + SUM)
| +----------------------- 类型标识0x48 (RS485 Data) | +----------------------- 类型标识0x48 (RS485 Data)
+--------------------------- 固定起始符 +--------------------------- 固定起始符
``` ```
@ -62,7 +62,7 @@ AA 55 LEN ID [DATA] SUM
| | | | | +-- 校验和 | | | | | +-- 校验和
| | | | +--------- 网络原始数据内容 | | | | +--------- 网络原始数据内容
| | | +--------------- 本机设备 ID | | | +--------------- 本机设备 ID
| | +------------------- 长度:(1 + 原始数据长度) | | +------------------- 长度:(1 + 原始数据长度 + SUM)
| +----------------------- 类型标识0x55 (Net Data) | +----------------------- 类型标识0x55 (Net Data)
+--------------------------- 固定起始符 +--------------------------- 固定起始符
``` ```
@ -71,14 +71,14 @@ AA 55 LEN ID [DATA] SUM
系统定时上报当前存活状态,包含当前的 I/O 状态及防丢包序列号。 系统定时上报当前存活状态,包含当前的 I/O 状态及防丢包序列号。
```text ```text
AA AA 04 ID [IO] [SEQ_H] [SEQ_L] SUM AA AA 05 ID [IO] [SEQ_H] [SEQ_L] SUM
-- -- -- -- ---- ------- ------- --- -- -- -- -- ---- ------- ------- ---
| | | | | | | | | | | | | | | |
| | | | | | | +-- 校验和 | | | | | | | +-- 校验和
| | | | | +-------+-------- 2字节序列号 (0-65535, 循环自增) | | | | | +-------+-------- 2字节序列号 (0-65535, 循环自增)
| | | | +----------------------- 当前 4 路 I/O 状态位 | | | | +----------------------- 当前 4 路 I/O 状态位
| | | +---------------------------- 本机设备 ID | | | +---------------------------- 本机设备 ID
| | +-------------------------------- 长度固定为 0x04 (ID + 3字节Payload) | | +-------------------------------- 长度固定为 0x05 (ID + 3字节Payload + SUM)
| +------------------------------------ 类型标识0xAA (Heartbeat) | +------------------------------------ 类型标识0xAA (Heartbeat)
+---------------------------------------- 固定起始符 +---------------------------------------- 固定起始符
``` ```