C 语言工业级通用组件手写 15:累加和校验

目录

前言:

一、累加和校验核心本质与应用场景

[1. 什么是累加和校验](#1. 什么是累加和校验)

[2. 解决的核心痛点](#2. 解决的核心痛点)

[3. 典型工业落地场景](#3. 典型工业落地场景)

二、核心实现原理

[1. 基础累加原理](#1. 基础累加原理)

[2. 8 位 / 16 位 算法区别](#2. 8 位 / 16 位 算法区别)

[3. 工业级溢出机制](#3. 工业级溢出机制)

三、工业级设计规范

[1. 封装设计](#1. 封装设计)

[2. 接口设计](#2. 接口设计)

[3. 鲁棒约束](#3. 鲁棒约束)

[4. 线程安全](#4. 线程安全)

四、完整可复用源码

1、checksum.h

2、checksum.c

五、实战演示

六、进阶优化方向

七、面试考点与易错坑点

1.面试问答

2.常见坑点

总结


前言:

嵌入式串口、无线、总线短帧通信场景中,CRC 校验算法运算量大、代码体积大、占用资源多,对于 8 位 / 16 位资源受限单片机完全冗余。

累加和校验凭借代码极简、运算极速、零内存开销,成为工业轻量级通信、传感器上报、设备交互最通用的基础校验方式。

本篇手写一套可直接商用的工业级累加和组件,支持 8bit/16bit 双模式,全参数安全校验、可重入、无全局变量、裸机 RTOS 全平台适配,彻底解决小型设备数据完整性校验问题。


一、累加和校验核心本质与应用场景

1. 什么是累加和校验

累加和校验是嵌入式最基础的数据校验算法,原理为将一帧数据所有字节逐字节累加,利用数值累加结果的唯一性标识数据完整性。

发送端:计算整帧数据累加和,附加在帧尾发送。

接收端:对接收数据重新累加,与帧尾校验值比对,一致则数据合法,不一致判定为干扰丢包。

核心特性

  • 纯遍历累加,无复杂运算,MCU 耗时极低
  • 无需缓存、无需查表、不占用 RAM
  • 支持任意长度数据帧
  • 自然溢出生效,无需额外逻辑处理

2. 解决的核心痛点

  • 解决低端单片机算力不足问题:规避 CRC 复杂异或、移位运算。
  • 解决短帧通信校验冗余问题:几十字节以内短报文,累加和性价比最高。
  • 解决自定义协议无标准校验工具问题:统一项目校验规范,杜绝五花八门手写校验。
  • 解决低功耗设备延时问题:校验耗时极短,不影响休眠与实时性。
  • 解决代码臃肿问题:百行以内极简实现,不占用 Flash 资源。

3. 典型工业落地场景

  • 串口自定义通信协议校验。
  • LoRa、蓝牙、WiFi 短帧无线报文校验。
  • 传感器单次上报数据完整性验证。
  • 设备本地配置、日志、参数简单校验存储。
  • 工控板简易点对点通信、下位机上报协议。

二、核心实现原理

1. 基础累加原理

定义初始累加值为 0,从数据首地址开始,逐字节叠加至累加变量,遍历结束后得到最终校验值。

2. 8 位 / 16 位 算法区别

8 位累加和 使用 uint8_t 累加,自动 256 模溢出,占用帧尾空间最小,适合 20 字节以内短帧。

16 位累加和 使用 uint16_t 累加,65536 模溢出,容错率更低、重复概率极小,适合中长数据帧。

3. 工业级溢出机制

嵌入式工程中累加和溢出不做纠错处理

原因:收发双方运算规则完全一致,溢出时机、溢出数值完全同步,不影响校验比对结果,同时最大程度简化代码、提升运行效率。


三、工业级设计规范

1. 封装设计

完全无全局变量,纯函数式实现。 只读数据运算,不修改原始缓冲区数据。 支持多线程、多中断并发调用,天然可重入。

2. 接口设计

接口 功能说明
check_sum8 8 位字节累加和校验计算
check_sum16 16 位字节累加和校验计算

3. 鲁棒约束

对空指针、零长度数据做安全拦截,杜绝死机。

变量严格限定无符号整形,避免符号位干扰计算。 指针后置自增遍历,代码高效精简。

4. 线程安全

无静态变量、无全局变量、无状态依赖。

中断、任务并发调用完全安全,无需互斥锁、无需关中断。

四、完整可复用源码

1、checksum.h

复制代码
#ifndef CHECKSUM_H
#define CHECKSUM_H

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 8位累加和校验
 * @param data 数据源缓冲区
 * @param len 数据有效长度
 * @return 8位累加校验和
 */
uint8_t check_sum8(const uint8_t *data, size_t len);

/**
 * @brief 16位累加和校验
 * @param data 数据源缓冲区
 * @param len 数据有效长度
 * @return 16位累加校验和
 */
uint16_t check_sum16(const uint8_t *data, size_t len);

#ifdef __cplusplus
}
#endif

#endif

2、checksum.c

复制代码
#include "checksum.h"

uint8_t check_sum8(const uint8_t *data, size_t len)
{
    /* 安全拦截空指针与空数据 */
    if (data == NULL || len == 0)
    {
        return 0;
    }

    uint8_t sum = 0;
    while (len--)
    {
        sum += *data++;
    }
    return sum;
}

uint16_t check_sum16(const uint8_t *data, size_t len)
{
    if (data == NULL || len == 0)
    {
        return 0;
    }

    uint16_t sum = 0;
    while (len--)
    {
        sum += *data++;
    }
    return sum;
}

五、实战演示

复制代码
#include <stdio.h>
#include "checksum.h"

int main(void)
{
    /* 模拟串口接收数据帧 */
    uint8_t test_frame[] = {0x01, 0x06, 0x00, 0x10, 0x00, 0x01, 0x00, 0x0A};

    uint8_t  sum8  = check_sum8(test_frame, sizeof(test_frame));
    uint16_t sum16 = check_sum16(test_frame, sizeof(test_frame));

    printf("8位累加和结果: 0x%02X\r\n", sum8);
    printf("16位累加和结果: 0x%04X\r\n", sum16);

    return 0;
}

六、进阶优化方向

  1. 反码累加和优化 原始累加和容错低,可将最终结果取反,大幅提升错误识别率,工业设备常用。

  2. 分段累加优化 超长数据包可分段累加,防止单次遍历耗时过长,适配实时性高的系统。

  3. 查表加速优化 高频大数据校验场景,可预建累加表,将遍历计算转为查表读取,速度翻倍。

  4. 累加和 + 长度双校验 增加数据长度校验,规避 "数据错位但累加和一致" 的极端错误。

七、面试考点与易错坑点

1.面试问答

Q1:累加和校验的原理是什么?工业上为什么允许自然溢出?

答:逐字节累加数据所有内容得到校验值。收发双方计算规则完全一致,溢出数值、溢出进位完全同步,比对结果依然有效,溢出无需处理,同时最大化精简代码、提高运行速度。

Q2:累加和校验和 CRC 校验核心区别是什么?项目如何选型?

答:累加和无复杂运算、速度最快、资源最小,但容错率低;CRC 通过多项式异或,抗干扰强、可靠性高。 短帧、低干扰、低端单片机、低功耗场景用累加和;长帧、工业强干扰、高可靠通信必须用 CRC。

Q3:累加和校验存在哪些致命缺陷?

答:存在纠错盲区:多字节同时增减相同数值,累加和不变,无法识别错误;数据整体错位、整体偏移也可能校验正常,安全性远低于 CRC。

Q4:为什么本组件可以做到中断与多线程安全?

答:组件无全局变量、无静态变量、无状态缓存,所有变量均为函数局部栈变量,每次调用独立运算,互不干扰,天然可重入。

Q5:8 位累加和与 16 位累加和如何选型?

答:20 字节以内极短帧、节省帧空间选 8 位;20 字节以上中长帧、降低校验碰撞概率、提升可靠性选 16 位。

Q6:项目中如何提升累加和校验的可靠性?

答:可以采用「累加和取反」「累加和 + 数据长度双校验」「双重累加算法」,低成本提升校验准确率,兼顾速度与可靠性。

2.常见坑点

  • 未做空指针判断,传入 NULL 导致硬件 HardFault。
  • 数据长度传递错误,少算 / 多算字节导致校验完全错位。
  • 高干扰工业环境单独使用累加和,导致数据出错无法识别。
  • 混用有符号变量累加,符号位溢出导致校验值错乱。

总结

累加和校验是嵌入式工程师必须掌握的最轻量、最高效的数据校验手段,资源占用几乎为零、适配所有低端单片机、适配所有短帧通信场景。

虽然可靠性弱于 CRC,但在绝大多数普通设备通信、本地数据校验场景中完全够用,性价比极高。本组件工业级稳健封装,可直接商用落地,是嵌入式底层通用核心工具组件。


创作不易,如果对你有帮助,欢迎点赞、收藏、转发。

相关推荐
碎光拾影16 小时前
i.MX6ULL时钟系统配置指南
c语言·arm开发·嵌入式硬件
GeekArch16 小时前
第28讲:避坑——AI堆栈分配错误、栈溢出BUG
c语言·人工智能·stm32·mcu·学习·bug
wuyk55519 小时前
59.嵌入式C语言高级宏定义实战:多行宏、字符串化与符号拼接
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网·51单片机
无相求码21 小时前
C程序的内存到底怎么分的?栈、堆、全局区一张图讲清楚
c语言
天空'之城21 小时前
C 语言工业级通用组件手写 08:精准软件消抖
c语言·嵌入式开发·工业级组件·软件消抖·按键防抖
Legendary_0081 天前
LDR6500 设计指南:Type-C 音频快充二合一配件 PD 取电与插拔时序控制方案
c语言·开发语言·音视频
会飞的小新1 天前
C 标准库之 <fenv.h> 详解与深度解析
c语言·开发语言·microsoft
爱刷碗的苏泓舒1 天前
C 语言 if-else 与 switch-case 分支语句对比
c语言·开发语言
无相求码1 天前
指针的5层境界,从入门到劝退:C语言指针进阶全解析
c语言