8051单片机-校验和

发布时间:2024-07-30  

【例子】通过校验和的方式实现数据传输与控制,例如控制LED灯、蜂鸣器、发送数据到上位机。

由于是数据传输与控制,需要定制一个结构体、共用体方便数据识别,同时增强可读性。从数据帧格式定义中可以定义为“PKT_SUM_EX”类型。


识别数据请求什么操作可以通过以下手段来识别:识别数据头部1、数据头部2,操作码。当完全接收数据完毕后通过校验该数据得出的校验值与该数据的尾部的校验值是否匹配。


若匹配,则根据操作码的请求进行操作;若不匹配则丢弃当前数据帧,等待下一个数据帧的到来。


结构体定义:


/*使用结构体对数据包进行封装


 *方便操作数据


 */


typedef  struct _PKT_SUM


{


    UINT8 m_ucHead1;       //首部1


    UINT8 m_ucHead2;       //首部2


    UINT8 m_ucOptCode;     //操作码


    UINT8 m_ucDataLength;  //数据长度


    UINT8 m_szDataBuf[16]; //数据


 


    UINT8 m_ucCheckSum;      //CRC16为2个字节


 


}PKT_SUM;


 


/*使用共用体再一次对数据包进行封装


 *操作数据更加方便


 */


typedef union _PKT_SUM_EX


{


    PKT_SUM r;


    UINT8 p[32];


} PKT_SUM_EX;


校验和代码如下:


#include "stc.h"


/***************************************************

 *          类型定义,方便代码移植

 ***************************************************/

typedef unsigned char   UINT8;

typedef unsigned int    UINT16;

typedef unsigned long   UINT32; 

    

typedef char            INT8;

typedef int             INT16;

typedef long            INT32;

typedef bit             BOOL;


/***************************************************

 *          大量宏定义,便于代码移植和阅读

 ***************************************************/

//--------------------------------

                                   //----头部----

#define DCMD_CTRL_HEAD1      0x10  //PC下传控制包头部1

#define DCMD_CTRL_HEAD2      0x01  //PC下传控制包头部2


                                   //----命令码----

#define DCMD_NULL            0x00  //命令码:空操作

#define DCMD_CTRL_BELL       0x01  //命令码:控制蜂鸣器

#define DCMD_CTRL_LED        0x02  //命令码:控制LED

#define DCMD_REQ_DATA        0x03  //命令码:请求数据


                                   //----数据----

#define DCTRL_BELL_ON        0x01  //蜂鸣器响

#define DCTRL_BELL_OFF       0x02  //蜂鸣器禁鸣

#define DCTRL_LED_ON         0x03  //LED亮

#define DCTRL_LED_OFF        0x04  //LED灭


//--------------------------------

                                   //----头部----

#define UCMD_CTRL_HEAD1      0x20  //MCU上传控制包头部1

#define UCMD_CTRL_HEAD2      0x01  //MCU上传控制包头部2


                                   //----命令码----

#define UCMD_NULL            0x00  //命令码:空操作

#define UCMD_REQ_DATA        0x01  //命令码:请求数据



#define CTRL_FRAME_LEN       0x04  //帧长度(不包含数据和校验值)

#define CHECKSUM_LEN         0x01  //检验值长度


#define EN_UART()            ES=1 //允许串口中断

#define NOT_EN_UART()        ES=0 //禁止串口中断


#define BELL(x)             {if((x))P0_6=1 ;else P0_6=0;} //蜂鸣器控制宏函数

#define LED(x)              {if((x))P2=0x00;else P2=0xFF;}//LED控制宏函数    


#define TRUE                1

#define FALSE               0


#define HIGH                1

#define LOW                 0   


#define ON                  1

#define OFF                 0


#define NULL                (void *)0 


/*使用结构体对数据包进行封装

 *方便操作数据

 */

typedef  struct _PKT_SUM

{

    UINT8 m_ucHead1;       //首部1

    UINT8 m_ucHead2;       //首部2

    UINT8 m_ucOptCode;     //操作码

    UINT8 m_ucDataLength;  //数据长度

    UINT8 m_szDataBuf[16]; //数据


    UINT8 m_ucCheckSum;      //CRC16为2个字节


}PKT_SUM;


/*使用共用体再一次对数据包进行封装

 *操作数据更加方便

 */

typedef union _PKT_SUM_EX

{

    PKT_SUM r;

    UINT8 p[32];

} PKT_SUM_EX;



PKT_SUM_EX    PktSumEx; //定义数据包变量

BOOL  bLedOn=FALSE;     //定义是否点亮LED布尔变量

BOOL  bBellOn=FALSE;    //定义是否蜂鸣器响布尔变量

BOOL  bReqData=FALSE;   //定义是否请求数据布尔变量


/****************************************************

** 函数名称: CheckSum

** 输    入: buf 要校验的数据;

             len 要校验的数据的长度 

** 输    出: 校验值

** 功能描述: 计算校验和

*****************************************************/

UINT16 CheckSum(UINT8 *buf, UINT8 len) 

{

      UINT8 i=0,Sum=0;


      for (i=0;i      {

          Sum+=*buf++;

      }


      return Sum;

/*************************************************************

* 函数名称:BufCpy

* 输    入:dest目标缓冲区; 

           Src  源缓冲区

           size 复制数据的大小

* 输    出:无

* 说    明:复制缓冲区

**************************************************************/

BOOL BufCpy(UINT8 * dest,UINT8 * src,UINT32 size)

{

    if(NULL ==dest || NULL==src ||NULL==size)

    {

        return FALSE;

    }

    

    do

    {

        *dest++ = *src++;

        

    }while(--size!=0);

    

    return TRUE;

}

/****************************************************

** 函数名称: UartInit

** 输    入: 无

** 输    出: 无

** 功能描述: 串口初始化

*****************************************************/                                                                               

void UartInit(void)

{

    SCON=0x40;

    T2CON=0x34;

    RCAP2L=0xD9;

    RCAP2H=0xFF;

    REN=1;

     ES=1;

}

/****************************************************

** 函数名称: UARTSendByte

** 输    入: b 单个字节

** 输    出: 无

** 功能描述: 串口 发送单个字节

*****************************************************/ 

void UARTSendByte(UINT8 b)

{

      SBUF=b;

     while(TI==0);

     TI=0;

}

/****************************************************

** 函数名称: UARTSendNBytes

** 输    入: buf 缓冲区

            len 发送数据长度

** 输    出: 无

** 功能描述: 串口 发送单个字节

*****************************************************/ 

void UartSendNBytes(UINT8 *buf,UINT8 len)

{

     while(len--)

     {

         UARTSendByte(*buf++);

     }

}

/****************************************************

** 函数名称: main

** 输    入: 无

** 输    出: 无

** 功能描述: 函数主体

*****************************************************/

void main(void)

{

     UINT8 i=0;

     UINT8 ucCheckSum=0;


     UartInit();//串口初始化


     EA=1;      //开总中断

     

     while(1)

     {

          if(bLedOn)  //是否点亮Led

          {

             LED(ON);  

          }

          else

          {

             LED(OFF); 

          }

          

          

          if(bBellOn)//是否响蜂鸣器

          {

             BELL(ON);

          }

          else

          {

             BELL(OFF);

          }

          

          if(bReqData)//是否请求数据

          {

             bReqData=FALSE;


             NOT_EN_UART(); //禁止串口中断

             

             PktSumEx.r.m_ucHead1=UCMD_CTRL_HEAD1;//MCU上传数据帧头部1

             PktSumEx.r.m_ucHead2=UCMD_CTRL_HEAD2;//MCU上传数据帧头部2

             PktSumEx.r.m_ucOptCode=UCMD_REQ_DATA;//MCU上传数据帧命令码


             

             PktSumEx.r.m_ucCheckSum=CheckSum(PktSumEx.p,

                                                    CTRL_FRAME_LEN+

                                               PktSumEx.r.m_ucDataLength);//计算校验值

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>