找回密码
 立即注册
查看: 523|回复: 0

快速搭建简单的串口分包通讯

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2024-8-30 14:46:30 | 显示全部楼层 |阅读模式
本帖最后由 王昱顺 于 2024-8-30 15:13 编辑

快速搭建简单的串口分包通讯

在近距离通讯中(20cm内),串口通讯也是一个很不错的选择。
虽然已经拥有了ModBus这种广为人知协议,但是从头适配起来往往有些麻烦。所以,这里给出一种快速的(10分钟内可从头写完)的串口传输协议。

协议分成三部分:包头,数据,校验和。
包头固定为0x55,校验和为ADD8(即定义一个unsigned char变量,然后将所有数据(包括0x55包头)加起来,溢出部分不管)。

发送十分简单,并不需要考虑延时分包问题,直接在需要的时候发送数据就可以了(不过这个并没有数据重发功能,发送受到干扰也会造成数据丢失)

这里主要讲一下接收部分的实现:
  1. u8 uart_set[10] = {0};//串口操作缓冲区
  2. u8 uart_cnt = 0;//串口指针
  3. u8 crc_add = 0, crc_cnt = 0;
  4. void Uart2_Isr(void) interrupt 8
  5. {
  6.        //发送中断部分,略
  7.        if(S2CON & 0x01) // 检测串口2接收中断
  8.        {
  9.               S2CON&= ~0x01; // 清除串口2接收中断请求位
  10.               if(uart_cnt != 0)
  11.               {
  12.                      uart_set[uart_cnt]= S2BUF;
  13.                      uart_cnt++;
  14.                      if(uart_cnt == 10)
  15.                      {
  16.                             uart_cnt= 0;
  17.                             crc_add= 0;
  18.                             for(crc_cnt = 0; crc_cnt < 9; crc_cnt++)
  19.                             {
  20.                                    crc_add+= uart_set[crc_cnt];
  21.                             }
  22.                             if(crc_add == uart_set[9])
  23.                             {
  24.                                    //数据解析
  25.                                    uart_dat_out1= (int)(uart_set[1] << 8 | uart_set[2]);
  26.                                    uart_dat_out2= (int)(uart_set[3] << 8 | uart_set[4]);
  27.                                    uart_dat_diff1= (int)(uart_set[5] << 8 | uart_set[6]);
  28.                                    uart_dat_diff2= (int)(uart_set[7] << 8 | uart_set[8]);
  29.                             }
  30.                      }
  31.               }
  32.               if(S2BUF == 0x55 && uart_cnt == 0)
  33.               {
  34.                      uart_set[uart_cnt]= S2BUF;
  35.                      uart_cnt++;
  36.               }
  37.        }
  38. }
复制代码


首先是包头同步功能,检测到串口接收中断的数据为包头数据,并且当前串口数据指针为包头时,将数据存入缓冲区,并且开始串口数据指针自加,否则就继续等待。
这样,就算数据丢失造成错位,但是crc校验不过,仍然会在下一次的等待同步过程中继续同步。

然后就是数据帧阶段,这部分会根据串口数据指针存入缓冲区,直到最后一个数据的时候进行crc校验比较,成功后则将缓冲区内容取出,然后赋值给所需变量。
这个部分中,数据的长度应该是确定的。这个协议要求收发双方发送了同样的指定长度数据,并不能支持不定长数据传输。好处就是不需要延迟分包,连一块发也是可以的。

这个代码经过实际测试,效果良好,没有传入错误的数据,且性能损耗小,计算简单。

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 06:51 , Processed in 0.111519 second(s), 42 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表