8051单片机-奇偶校验

发布时间: 2024-07-30
来源: 电子工程世界

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


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


识别数据请求什么操作可以通过以下手段来识别:识别数据头部1、数据头部2,操作码。


当完全接收数据完毕后通过校验该数据得出的校验值与该数据的尾部的校验值是否匹配。若匹配,则根据操作码的请求进行操作;若不匹配则丢弃当前数据帧,等待下一个数据帧的到来。


结构体定义:


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


 *方便操作数据


 */


typedef  struct _PKT_PARITY


{


    UINT8 m_ucHead1;       //首部1


    UINT8 m_ucHead2;       //首部2


    UINT8 m_ucOptCode;     //操作码


    UINT8 m_ucDataLength;  //数据长度


    UINT8 m_szDataBuf[16]; //数据


 


    UINT8 m_ucParity;      //校验值为1个字节


 


}PKT_PARITY;


 


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


 *操作数据更加方便


 */


typedef union _PKT_PARITY_EX


{


    PKT_PARITY r;


    UINT8 p[32];


} PKT_PARITY_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 PARITY_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_PARITY

{

    UINT8 m_ucHead1;       //首部1

    UINT8 m_ucHead2;       //首部2

    UINT8 m_ucOptCode;     //操作码

    UINT8 m_ucDataLength;  //数据长度

    UINT8 m_szDataBuf[16]; //数据


    UINT8 m_ucParity;      //校验值为1个字节


}PKT_PARITY;


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

 *操作数据更加方便

 */

typedef union _PKT_PARITY_EX

{

    PKT_PARITY r;

    UINT8 p[32];

} PKT_PARITY_EX;



PKT_PARITY_EX    PktParityEx; //定义数据包变量

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

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

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

 

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

*函数名称:OddParity

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

*输    出:校验值

*功    能:偶校验

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

BOOL OddParity(UINT8 *buf, UINT8 len)   

{   

    UINT8 i,j;   

    UINT8 data_temp;   

    BOOL  bParity;   


    bParity = 1;  


    for(j = 0; j < len;j++)   

    {   

        data_temp = *(buf + j); 


        for(i = 0; i < 8; i++)   

        {   

     

            if((data_temp & 0x01) == 0x01)   

            {   

                bParity ^= 1;   

            }   


            data_temp = data_temp >> 1;      

        }   

    }   


    return bParity;   

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

* 函数名称:BufClr

* 输    入:dest 缓冲区; 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;

}

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

** 函数名称: UARTSendByte

** 输    入: b 单个字节

** 输    出: 无

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

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

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(); //禁止串口中断

             

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

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

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

文章来源于: 电子工程世界 原文链接

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