C语言程序与设计3

一、协议处理的API设计与应用

PCT 通信协议简介
从机常作为执行单元,用于处理一些具体的事务,而主机(如
Windows 、 Linux 、 Android 和 emWin 平台等)常用于与从机进行交互,向
从机发送命令,或处理来自从机的数据,如下图所示。

PCT 通信协议格式
在主机与从机的通信过程中,主机和从机有一个共同的模块,即打包解
包模块( PackUnpack ),该模块遵循某种通信协议。通信协议有很多种,本
实验采用的 PCT 通信协议。 PCT 通信协议的数据包格式。

PCT 通信协议打包过程

第 1 步,准备原始数据,原始数据由模块 ID ( 0x00 ~ 0x7F )、二级ID 、数据 1 、数据 2 、数据 3 、数据 4 、数据 5 和数据 6 组成,如下图所示。其中,模块 ID 的取值范围为 0x00 ~ 0x7F ,二级 ID 和数据的取值范围为0x00 ~ 0xFF 。


第 2 步,依次取出二级 ID 、数据 1~ 数据 6 的最高位 bit7 ,将其存放于数据头的低 7 位,按照从低位到高位的顺序依次存放二级 ID 、数据 1 、数据2 、数据 3 、数据 4 、数据 5 和数据 6 的最高位 bit7 ,如下图所示。


第 3 步,对模块 ID 、数据头、二级 ID 、数据 1 、数据 2 、数据 3 、数据 4 、数据 5 和数据 6 的低 7 位求和,取求和结果的低 7 位,将其存放于校验和的低 7 位。


第 4 步,将数据头、二级 ID 、数据 1 、数据 2 、数据 3 、数据 4 、数据 5 、数据 6 和校验和的最高位置为 1 ,如下图所示。

PCT 通信协议解包过程
第 1 步,准备解包前的数据包,原始数据包由模块 ID 、数据头、二级ID 、数据 1 、数据 2 、数据 3 、数据 4 、数据 5 、数据 6 、校验和组成,如下图所示。其中,模块 ID 的最高位为 0 ,其余字节的最高位均为 1 。

第 2 步,对模块 ID 、数据头、二级 ID 、数据 1 、数据 2 、数据 3 、数据 4 、数据 5 和数据 6 的低 7 位求和,如下图所示,取求和结果的低 7 位与数据包的校验和低 7 位对比,如果两个值的结果相等,则说明校验正确。



第 3 步,数据头的最低位 bit0 与二级 ID 的低 7 位拼接之后作为最终的二级 ID ,数据头的 bit1 与数据 1 的低 7 位拼接之后作为最终的数据 1 ,数据头的 bit2 与数据 2 的低 7 位拼接之后作为最终的数据 2 ,以此类推。

第 4 步,下图所示即为解包后的结果,由模块 ID 、二级 ID 、数据 1 、数据 2 、数据 3 、数据 4 、数据 5 和数据 6 组成。其中,模块 ID 的取值范围为 0x00 ~ 0x7F ,二级 ID 和数据的取值范围为 0x00 ~ 0xFF 。

/*********************************************************************************************************
* 模块名称: PackUnpack.c
* 摘    要: PCT协议的打包解包模块
* 内    容: 
*           (1)数据包格式:模块ID+数据头+二级ID+数据1...数据6+校验和
*                            数据包都有校验和,由1个字节模块ID、1个字节数据头,1个字节二级ID,6个字节数据
*                            和1个字节校验和构成,因此,数据包长度为10个字节,数据包的数据容量为6个
*           (2)模块ID的最高位BIT7为0,数据头、二级ID、数据以及校验和的最高位为1,所有包的数据头依次包含
*                数据字节的最高位,如数据头的BIT0为二级ID的BIT7,数据头的BIT1为数据1的BIT7,数据头的BIT2
*                为数据2的BIT7,数据头的BIT6为数据6的BIT7
*           (3)参数板协议的简易版
* 注    意:                                                                   
**********************************************************************************************************
* 取代版本: 
* 作    者:
* 完成日期: 
* 修改内容: 
* 修改文件:  
*********************************************************************************************************/

/*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "PackUnpack.h"

/*********************************************************************************************************
*                                              宏定义
*********************************************************************************************************/

/*********************************************************************************************************
*                                              枚举结构体定义
*********************************************************************************************************/

/*********************************************************************************************************
*                                              内部变量
*********************************************************************************************************/
//以下四个参数在打包和解包的时候使用
static StructPackType s_ptPack;   //数据包,1字节模块ID,1字节数据头,1字节二级ID,6字节数据,1字节校验和
static u8       s_iPackLen;       //数据包长度,用来判断数据长度是否为10,不为10为错误包
static u8       s_iGotPackId;     //获取到ID的标志
static u8       s_iRestByteNum;   //剩余字节数
  
/*********************************************************************************************************
*                                              内部函数声明
*********************************************************************************************************/
static  void  PackWithCheckSum(u8* pPack);                      //带校验和的数据打包
static  u8    UnpackWithCheckSum(u8* pPack);                    //带校验和的数据解包

/*********************************************************************************************************
*                                              内部函数实现
*********************************************************************************************************/

/*********************************************************************************************************
* 函数名称: PackWithCheckSum
* 函数功能: 带校验和的数据打包
* 输入参数: 待打包的数据pPack的首地址 
* 输出参数: 打包好的数据pPack的首地址
* 返 回 值: void
* 创建日期: 2021年03月01日
* 注    意: 如数据头的BIT0为二级ID的BIT7,数据头的BIT1为数据1的BIT7,数据头的BIT2为数据2的BIT7,数据头的
*           BIT6为数据6的BIT7 
*********************************************************************************************************/
static void PackWithCheckSum(u8* pPack)
{
  u8  i;
  u8  dataHead;   //数据头,在数据包的第2个位置,即ModuleID之后
  u8  checkSum;   //校验和,在数据包的最后一个位置
   
  checkSum = *(pPack);  //取出ModuleID,加到校验和
  dataHead = 0;         //数据头清零
   
  for(i = 8; i > 1; i --)
  {
    //数据头左移,后面数据的最高位位于dataHead的靠左,如数据6的最高位位于dataHead的BIT6
    dataHead <<= 1;

    //取出原始数据的最高位,与dataHead相或
    dataHead |= (*(pPack + i) & 0x80) >> 7;
  
    //对数据进行最高位置1操作
    *(pPack + i) = *(pPack + i) | 0x80;

    //数据加到校验和
    checkSum += *(pPack+i);
  }

  //数据头在数据包的第二个位置,仅次于包头,数据头的最高位也要置为1
  *(pPack+1) = dataHead | 0x80;
  
  //将数据头加到校验和
  checkSum += *(pPack+1);

  //校验和的最高位也要置为1
  *(pPack+9) = checkSum | 0x80;
}

/*********************************************************************************************************
* 函数名称: UnpackWithCheckSum
* 函数功能: 带校验和的数据解包 
* 输入参数: 待解包的数据pPack的首地址,打包后的数据长度  
* 输出参数: 解包好的数据pPack的首地址
* 返 回 值: 0-解包不成功,1-解包成功
* 创建日期: 2021年03月01日
* 注    意: 
*********************************************************************************************************/
static u8  UnpackWithCheckSum(u8* pPack)
{
  u8  i;
  u8  dataHead;   //数据头,在数据包的第2个位置,即ModuleID之后            
  u8  checkSum;   //校验和,在数据包的最后一个位置

  checkSum  = *(pPack);       //取出模块ID,加到校验和
  
  dataHead = *(pPack + 1);    //取出数据包的数据头,赋给dataHead
  checkSum += dataHead;       //将数据头加到校验和
  
  for(i = 2; i < 9; i++)
  {
    checkSum += *(pPack + i); //将数据依次加到校验和
  
    //还原二级ID和6位数据
    *(pPack + i) = (*(pPack + i) & 0x7f) | ((dataHead & 0x1) << 7);
    
    dataHead >>= 1;           //数据头右移一位
  }
  
  //判断模块ID、数据头、二级ID和数据求和的结果(低七位)是否与校验和的低七位相等,如果不等返回0
  if((checkSum & 0x7f ) != ((*(pPack + 9)) & 0x7f))
  {
    return 0;
  }

  return 1;
}

/*********************************************************************************************************
*    
  • 21
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值