修复多连接的问题
This commit is contained in:
42
App/app_cfg.h
Normal file
42
App/app_cfg.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 模块名称:Application Configuration
|
||||
* 模块功能:应用层全局配置宏,控制功能模块的编译开关
|
||||
* 适用平台:STM32F407ZGTx
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __APP_CFG_H
|
||||
#define __APP_CFG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 系统时钟源选择
|
||||
* 0 - DWT CYCCNT(默认,0 外设开销)
|
||||
* 1 - TIM2(32-bit 定时器,独立于 DWT)
|
||||
*/
|
||||
#define APP_SYS_TIME_SRC 0
|
||||
|
||||
/*
|
||||
* 时间戳输出使能
|
||||
* 定义后在日志行首自动追加 [T ssssss.uuuuuu] 微秒时间戳
|
||||
*/
|
||||
#define APP_TIMESTAMP_ENABLE
|
||||
|
||||
/*
|
||||
* 功能模块使能开关
|
||||
*/
|
||||
#define APP_NET_ENABLE
|
||||
#define APP_ADC_ENABLE
|
||||
#define APP_RS485_ENABLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __APP_CFG_H */
|
||||
47
App/app_main.c
Normal file
47
App/app_main.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 模块名称:Application Main Entry
|
||||
* 模块功能:应用初始化流程编排、各模块启动、主循环
|
||||
* 适用平台:STM32F407ZGTx
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "app_main.h"
|
||||
#include "app_cfg.h"
|
||||
#include "sys_time.h"
|
||||
|
||||
#define DBG_TAG "[APP]"
|
||||
#include "dbg_log.h"
|
||||
|
||||
/*
|
||||
* 函数功能:应用层初始化
|
||||
* 入口参数:无
|
||||
* 返 回 值:0 - 成功,-1 - 失败
|
||||
* 限定条件:CubeMX 外设初始化已完成
|
||||
* 函数说明:在 CubeMX 外设初始化之后、FreeRTOS 调度器启动之前调用
|
||||
*/
|
||||
int app_main_init(void)
|
||||
{
|
||||
if (sys_time_init() != 0) {
|
||||
DBG_ERROR("sys_time_init failed");
|
||||
return -1;
|
||||
}
|
||||
DBG_INFO("App init OK");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:应用主循环
|
||||
* 入口参数:无
|
||||
* 返 回 值:无
|
||||
* 限定条件:FreeRTOS 调度器启动后不再返回
|
||||
* 函数说明:空闲任务可调用的应用层处理入口
|
||||
*/
|
||||
void app_main_run(void)
|
||||
{
|
||||
for (;;) {
|
||||
/* 应用层空闲处理 */
|
||||
}
|
||||
}
|
||||
27
App/app_main.h
Normal file
27
App/app_main.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 模块名称:Application Main Entry
|
||||
* 模块功能:应用层入口,由 main.c 调用完成所有应用初始化与启动
|
||||
* 适用平台:STM32F407ZGTx
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __APP_MAIN_H
|
||||
#define __APP_MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int app_main_init(void);
|
||||
void app_main_run(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __APP_MAIN_H */
|
||||
0
App/protocol/.gitkeep
Normal file
0
App/protocol/.gitkeep
Normal file
107
App/sys_time.c
Normal file
107
App/sys_time.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 模块名称:System Timer
|
||||
* 模块功能:DWT CYCCNT 实现 64-bit 微秒级时间戳
|
||||
* 在 SysTick 中断中检测 CYCCNT 溢出以扩展至 64-bit
|
||||
* 适用平台:STM32F407ZGTx (168MHz)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
*
|
||||
* 限定条件:
|
||||
* - CPU 主频 168MHz(若更改须同步 SYS_TIME_CYCLE_PER_US 宏)
|
||||
* - 须在 FreeRTOS 启动前调用 sys_time_init()
|
||||
* - sys_time_systick_hook() 须在 SysTick 中断中调用
|
||||
*
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "sys_time.h"
|
||||
#include "app_cfg.h"
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
/*
|
||||
* 每微秒 CPU 周期数(168MHz → 168 cycles/µs)
|
||||
*/
|
||||
#define SYS_TIME_CYCLE_PER_US 168UL
|
||||
|
||||
/*
|
||||
* CYCCNT 每溢出一次代表的微秒数(2^32 / 168 ≈ 25,564,904 µs ≈ 25.56s)
|
||||
*/
|
||||
#define SYS_TIME_OVERFLOW_US (uint64_t)(((uint64_t)1 << 32) / SYS_TIME_CYCLE_PER_US)
|
||||
|
||||
static volatile uint32_t s_overflow_cnt;
|
||||
|
||||
/*
|
||||
* 函数功能:初始化 DWT CYCCNT
|
||||
* 入口参数:无
|
||||
* 返 回 值:0 - 成功
|
||||
* 限定条件:须在 FreeRTOS 启动前调用
|
||||
* 函数说明:启用 DWT 和 CYCCNT 计数器,计数器从 0 开始
|
||||
*/
|
||||
int sys_time_init(void)
|
||||
{
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
DWT->CYCCNT = 0;
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
|
||||
s_overflow_cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取微秒级时间戳
|
||||
* 入口参数:无
|
||||
* 返 回 值:64 位微秒时间戳
|
||||
* 函数说明:由当前 CYCCNT 值与溢出计数合成 64-bit 周期数再转换
|
||||
*/
|
||||
uint64_t sys_time_us(void)
|
||||
{
|
||||
uint32_t cyccnt = 0;
|
||||
uint64_t ticks = 0;
|
||||
uint32_t ov = 0;
|
||||
uint32_t ov2 = 0;
|
||||
|
||||
/*
|
||||
* 原子读取溢出计数与 CYCCNT,处理潜在的读取竞争
|
||||
* 若两次读取溢出计数不一致则重读 CYCCNT
|
||||
*/
|
||||
do {
|
||||
ov = s_overflow_cnt;
|
||||
cyccnt = DWT->CYCCNT;
|
||||
ov2 = s_overflow_cnt;
|
||||
} while (ov != ov2);
|
||||
|
||||
ticks = ((uint64_t)ov << 32) | cyccnt;
|
||||
return ticks / SYS_TIME_CYCLE_PER_US;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取毫秒级时间戳
|
||||
* 入口参数:无
|
||||
* 返 回 值:64 位毫秒时间戳
|
||||
* 限定条件:sys_time_init() 已成功调用
|
||||
* 函数说明:通过对 sys_time_us() 取整实现
|
||||
*/
|
||||
uint64_t sys_time_ms(void)
|
||||
{
|
||||
return sys_time_us() / 1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:SysTick 中断钩子,检测 CYCCNT 溢出
|
||||
* 入口参数:无
|
||||
* 返 回 值:无
|
||||
* 函数说明:必须在 SysTick_Handler() 中调用
|
||||
* 每 1ms 检查一次 CYCCNT 是否已回绕
|
||||
*/
|
||||
void sys_time_systick_hook(void)
|
||||
{
|
||||
static uint32_t s_last_cyccnt = 0;
|
||||
uint32_t cyccnt = DWT->CYCCNT;
|
||||
|
||||
if (cyccnt < s_last_cyccnt) {
|
||||
s_overflow_cnt++;
|
||||
}
|
||||
s_last_cyccnt = cyccnt;
|
||||
}
|
||||
29
App/sys_time.h
Normal file
29
App/sys_time.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 模块名称:System Timer
|
||||
* 模块功能:基于 DWT CYCCNT + SysTick 溢出的 64 位微秒级时间戳
|
||||
* 适用平台:STM32F407ZGTx (Cortex-M4 FPU)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __SYS_TIME_H
|
||||
#define __SYS_TIME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int sys_time_init(void);
|
||||
uint64_t sys_time_us(void);
|
||||
uint64_t sys_time_ms(void);
|
||||
void sys_time_systick_hook(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYS_TIME_H */
|
||||
45
App/task/adc_task.c
Normal file
45
App/task/adc_task.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 模块名称:ADC Sampling Task
|
||||
* 模块功能:TPAFE5160 8 通道同步采样,数据缓存与通知
|
||||
* 适用平台:STM32F407ZGTx + TPAFE5160
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "adc_task.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "tpafe5160.h"
|
||||
|
||||
#define DBG_TAG "[ADC_TASK]"
|
||||
#include "dbg_log.h"
|
||||
|
||||
/*
|
||||
* 函数功能:ADC 任务初始化
|
||||
* 入口参数:无
|
||||
* 返 回 值:0 - 成功,-1 - 失败
|
||||
* 限定条件:TPAFE5160 硬件已上电
|
||||
* 函数说明:配置采样参数,准备数据缓冲区
|
||||
*/
|
||||
int adc_task_init(void)
|
||||
{
|
||||
DBG_INFO("adc_task_init");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:ADC 任务主函数
|
||||
* 入口参数:arg - FreeRTOS 传入参数(未使用)
|
||||
* 返 回 值:无
|
||||
* 限定条件:adc_task_init() 已成功调用
|
||||
* 函数说明:定时触发 TPAFE5160 同步采样并处理数据
|
||||
*/
|
||||
void adc_task_func(void const *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
for (;;) {
|
||||
osDelay(1000);
|
||||
}
|
||||
}
|
||||
25
App/task/adc_task.h
Normal file
25
App/task/adc_task.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 模块名称:ADC Sampling Task
|
||||
* 模块功能:TPAFE5160 8 通道同步采样,数据缓存与通知
|
||||
* 适用平台:STM32F407ZGTx + TPAFE5160
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __ADC_TASK_H
|
||||
#define __ADC_TASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int adc_task_init(void);
|
||||
void adc_task_func(void const *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ADC_TASK_H */
|
||||
78
App/task/net_task.c
Normal file
78
App/task/net_task.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 模块名称:Network Application Task
|
||||
* 模块功能:CH395F 协议栈轮询 + TCP/UDP 业务处理
|
||||
* 与 net_socket.h 配合,在 FreeRTOS 独立任务中运行
|
||||
* 适用平台:STM32F407ZGTx + CH395F
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
* v1.1 2026-07-19 王建锋 migrate from freertos.c StartNetTask
|
||||
*/
|
||||
|
||||
#include "net_task.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "net_socket.h"
|
||||
#include "net_select.h"
|
||||
#include "ch395f_test.h"
|
||||
|
||||
#define DBG_TAG "[NET_TASK]"
|
||||
#include "dbg_log.h"
|
||||
|
||||
static uint8_t s_net_buf[1500];
|
||||
|
||||
/*
|
||||
* 函数功能:网络任务初始化
|
||||
* 入口参数:无
|
||||
* 返 回 值:0 - 成功,-1 - 失败
|
||||
* 限定条件:CH395F 协议栈已初始化
|
||||
* 函数说明:创建 TCP Server 监听 Socket,注册回调等
|
||||
*/
|
||||
int net_task_init(void)
|
||||
{
|
||||
DBG_INFO("net_task_init");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:网络任务主函数
|
||||
* 入口参数:arg - FreeRTOS 传入参数(未使用)
|
||||
* 返 回 值:无
|
||||
* 函数说明:FreeRTOS 任务函数,启动后先等待 2 秒再进入轮询循环
|
||||
* 依次处理 net_poll、TCP echo、UDP/Select 测试
|
||||
*/
|
||||
void net_task_func(void const *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
osDelay(2000);
|
||||
DBG_INFO("netTask: started");
|
||||
|
||||
for (;;) {
|
||||
net_poll();
|
||||
|
||||
#ifdef ENABLE_PHASE4_TESTS
|
||||
for (int i = 1; i < 8; i++) {
|
||||
net_sock_t *p_sk = net_get_sock(i);
|
||||
if (p_sk == NULL || p_sk->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int n = net_recv(i, s_net_buf, sizeof(s_net_buf), NET_MSG_DONTWAIT);
|
||||
if (n > 0) {
|
||||
net_send(i, s_net_buf, n, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_PHASE5_TESTS
|
||||
ch395f_phase5_tests();
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_PHASE7_TESTS
|
||||
ch395f_phase7_tests();
|
||||
#endif
|
||||
|
||||
osDelay(10);
|
||||
}
|
||||
}
|
||||
25
App/task/net_task.h
Normal file
25
App/task/net_task.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 模块名称:Network Application Task
|
||||
* 模块功能:网络协议栈轮询、TCP/UDP 业务处理
|
||||
* 适用平台:STM32F407ZGTx + CH395F
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __NET_TASK_H
|
||||
#define __NET_TASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int net_task_init(void);
|
||||
void net_task_func(void const *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_TASK_H */
|
||||
45
App/task/rs485_task.c
Normal file
45
App/task/rs485_task.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 模块名称:RS485 Communication Task
|
||||
* 模块功能:RS-485 轮询收发、协议帧解析与响应
|
||||
* 适用平台:STM32F407ZGTx
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "rs485_task.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "rs485.h"
|
||||
|
||||
#define DBG_TAG "[RS485_TASK]"
|
||||
#include "dbg_log.h"
|
||||
|
||||
/*
|
||||
* 函数功能:RS485 任务初始化
|
||||
* 入口参数:无
|
||||
* 返 回 值:0 - 成功,-1 - 失败
|
||||
* 限定条件:UART 和 GPIO 已由 CubeMX 初始化
|
||||
* 函数说明:配置 RS-485 通信参数,注册接收回调
|
||||
*/
|
||||
int rs485_task_init(void)
|
||||
{
|
||||
DBG_INFO("rs485_task_init");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:RS485 任务主函数
|
||||
* 入口参数:arg - FreeRTOS 传入参数(未使用)
|
||||
* 返 回 值:无
|
||||
* 限定条件:rs485_task_init() 已成功调用
|
||||
* 函数说明:轮询接收缓冲区并解析协议帧
|
||||
*/
|
||||
void rs485_task_func(void const *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
for (;;) {
|
||||
osDelay(100);
|
||||
}
|
||||
}
|
||||
25
App/task/rs485_task.h
Normal file
25
App/task/rs485_task.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 模块名称:RS485 Communication Task
|
||||
* 模块功能:RS-485 数据收发与协议解析
|
||||
* 适用平台:STM32F407ZGTx
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __RS485_TASK_H
|
||||
#define __RS485_TASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int rs485_task_init(void);
|
||||
void rs485_task_func(void const *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __RS485_TASK_H */
|
||||
122
App/util/crc.c
Normal file
122
App/util/crc.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 模块名称:CRC Utility
|
||||
* 模块功能:CRC-16 Modbus (poly=0x8005, init=0xFFFF, refin=true, refout=true, xorout=0x0000)
|
||||
* CRC-8 (poly=0x07, init=0x00, refin=false, refout=false, xorout=0x00)
|
||||
* 适用平台:通用嵌入式平台
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
static const uint16_t s_crc16_table[256] = {
|
||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||||
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||||
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||||
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||||
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||||
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||||
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||||
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||||
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||||
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||||
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||||
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||||
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||||
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||||
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||||
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||||
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||||
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||||
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||||
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||||
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||||
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||||
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||||
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||||
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||||
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||||
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||||
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||||
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||||
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||||
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
|
||||
};
|
||||
|
||||
static const uint8_t s_crc8_table[256] = {
|
||||
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
||||
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
||||
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
|
||||
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
|
||||
0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
|
||||
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
|
||||
0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
|
||||
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
|
||||
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
|
||||
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
|
||||
0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
|
||||
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
|
||||
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
|
||||
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
|
||||
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
|
||||
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
|
||||
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
|
||||
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
|
||||
0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
|
||||
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
|
||||
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
|
||||
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
|
||||
0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
|
||||
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
|
||||
0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
|
||||
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
|
||||
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
|
||||
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
|
||||
0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
|
||||
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
|
||||
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3,
|
||||
};
|
||||
|
||||
/*
|
||||
* 函数功能:计算 CRC-16 Modbus
|
||||
* 入口参数:data - 数据指针
|
||||
* len - 数据长度
|
||||
* 返 回 值:16 位 CRC 值
|
||||
* 限定条件:data 为非空指针
|
||||
* 函数说明:多项式 0x8005,初始值 0xFFFF,结果异或 0x0000
|
||||
*/
|
||||
uint16_t crc16_modbus(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint16_t crc = 0xFFFF;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
crc = (crc >> 8) ^ s_crc16_table[(crc ^ data[i]) & 0xFF];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:计算 CRC-8
|
||||
* 入口参数:data - 数据指针
|
||||
* len - 数据长度
|
||||
* 返 回 值:8 位 CRC 值
|
||||
* 限定条件:data 为非空指针
|
||||
* 函数说明:多项式 0x07,初始值 0x00
|
||||
*/
|
||||
uint8_t crc8(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
crc = s_crc8_table[crc ^ data[i]];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
28
App/util/crc.h
Normal file
28
App/util/crc.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 模块名称:CRC Utility
|
||||
* 模块功能:CRC-16 Modbus & CRC-8 查表计算
|
||||
* 适用平台:通用嵌入式平台
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __CRC_H
|
||||
#define __CRC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
uint16_t crc16_modbus(const uint8_t *data, size_t len);
|
||||
uint8_t crc8(const uint8_t *data, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CRC_H */
|
||||
164
App/util/ringbuf.c
Normal file
164
App/util/ringbuf.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 模块名称:Ring Buffer
|
||||
* 模块功能:字节环形缓冲区实现,head == tail 为空,head + 1 == tail 为满
|
||||
* 适用平台:通用嵌入式平台
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "ringbuf.h"
|
||||
|
||||
/*
|
||||
* 函数功能:初始化环形缓冲区
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* pool - 存储池指针
|
||||
* size - 存储池大小(字节)
|
||||
* 返 回 值:无
|
||||
* 限定条件:rb 和 pool 均为非空指针
|
||||
* 函数说明:size 保留一个空位用于区分空/满状态
|
||||
*/
|
||||
void ringbuf_init(ringbuf_t *rb, uint8_t *pool, size_t size)
|
||||
{
|
||||
rb->buf = pool;
|
||||
rb->size = size;
|
||||
rb->head = 0;
|
||||
rb->tail = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:写入数据到环形缓冲区
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* data - 源数据指针
|
||||
* len - 待写入长度
|
||||
* 返 回 值:实际写入字节数
|
||||
* 限定条件:rb 和 data 均为非空指针
|
||||
* 函数说明:空间不足时写入能容纳的最大字节数
|
||||
*/
|
||||
size_t ringbuf_put(ringbuf_t *rb, const uint8_t *data, size_t len)
|
||||
{
|
||||
size_t cap = 0;
|
||||
size_t n = 0;
|
||||
size_t i = 0;
|
||||
|
||||
cap = rb->size - 1 - ringbuf_avail(rb);
|
||||
n = (len < cap) ? len : cap;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
rb->buf[rb->head] = data[i];
|
||||
rb->head = (rb->head + 1) % rb->size;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:从环形缓冲区读取数据
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* data - 目标数据指针
|
||||
* len - 期望读取长度
|
||||
* 返 回 值:实际读取字节数
|
||||
* 限定条件:rb 和 data 均为非空指针
|
||||
* 函数说明:读取后数据从缓冲区移除
|
||||
*/
|
||||
size_t ringbuf_get(ringbuf_t *rb, uint8_t *data, size_t len)
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t i = 0;
|
||||
|
||||
n = ringbuf_avail(rb);
|
||||
n = (n < len) ? n : len;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
data[i] = rb->buf[rb->tail];
|
||||
rb->tail = (rb->tail + 1) % rb->size;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:预读取数据(不移除)
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* data - 目标数据指针
|
||||
* len - 期望读取长度
|
||||
* 返 回 值:实际可读取字节数
|
||||
* 限定条件:rb 和 data 均为非空指针
|
||||
* 函数说明:与 ringbuf_get 的区别是不移动 tail 指针
|
||||
*/
|
||||
size_t ringbuf_peek(const ringbuf_t *rb, uint8_t *data, size_t len)
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t i = 0;
|
||||
size_t idx = 0;
|
||||
|
||||
n = ringbuf_avail(rb);
|
||||
n = (n < len) ? n : len;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
idx = (rb->tail + i) % rb->size;
|
||||
data[i] = rb->buf[idx];
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取缓冲区中有效数据长度
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* 返 回 值:有效数据字节数
|
||||
* 限定条件:rb 为非空指针
|
||||
*/
|
||||
size_t ringbuf_avail(const ringbuf_t *rb)
|
||||
{
|
||||
if (rb->head >= rb->tail) {
|
||||
return rb->head - rb->tail;
|
||||
}
|
||||
return rb->size - rb->tail + rb->head;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取缓冲区剩余空间
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* 返 回 值:剩余空间字节数(保留一个空位)
|
||||
* 限定条件:rb 为非空指针
|
||||
*/
|
||||
size_t ringbuf_space(const ringbuf_t *rb)
|
||||
{
|
||||
return rb->size - 1 - ringbuf_avail(rb);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:判断缓冲区是否为空
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* 返 回 值:1 - 空,0 - 非空
|
||||
* 限定条件:rb 为非空指针
|
||||
*/
|
||||
int ringbuf_is_empty(const ringbuf_t *rb)
|
||||
{
|
||||
return (rb->head == rb->tail) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:判断缓冲区是否为满
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* 返 回 值:1 - 满,0 - 非满
|
||||
* 限定条件:rb 为非空指针
|
||||
*/
|
||||
int ringbuf_is_full(const ringbuf_t *rb)
|
||||
{
|
||||
return (ringbuf_avail(rb) == rb->size - 1) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:重置缓冲区
|
||||
* 入口参数:rb - 缓冲区控制块指针
|
||||
* 返 回 值:无
|
||||
* 限定条件:rb 为非空指针
|
||||
*/
|
||||
void ringbuf_reset(ringbuf_t *rb)
|
||||
{
|
||||
rb->head = 0;
|
||||
rb->tail = 0;
|
||||
}
|
||||
42
App/util/ringbuf.h
Normal file
42
App/util/ringbuf.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 模块名称:Ring Buffer
|
||||
* 模块功能:线程安全的字节环形缓冲区(单生产者-单消费者模型)
|
||||
* 适用平台:通用嵌入式平台
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-19
|
||||
* 修改记录:
|
||||
* v1.0 2026-07-19 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __RINGBUF_H
|
||||
#define __RINGBUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t head;
|
||||
size_t tail;
|
||||
} ringbuf_t;
|
||||
|
||||
void ringbuf_init(ringbuf_t *rb, uint8_t *pool, size_t size);
|
||||
size_t ringbuf_put(ringbuf_t *rb, const uint8_t *data, size_t len);
|
||||
size_t ringbuf_get(ringbuf_t *rb, uint8_t *data, size_t len);
|
||||
size_t ringbuf_peek(const ringbuf_t *rb, uint8_t *data, size_t len);
|
||||
size_t ringbuf_avail(const ringbuf_t *rb);
|
||||
size_t ringbuf_space(const ringbuf_t *rb);
|
||||
int ringbuf_is_empty(const ringbuf_t *rb);
|
||||
int ringbuf_is_full(const ringbuf_t *rb);
|
||||
void ringbuf_reset(ringbuf_t *rb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __RINGBUF_H */
|
||||
Reference in New Issue
Block a user