[DemoCode下载] 51通讯协议—奇偶校验

[复制链接]
1285|9
 楼主| 春风的暖暖 发表于 2015-9-1 21:20 | 显示全部楼层 |阅读模式
  1. #include "at89x52.h"

  2. /***************************************************
  3. *          类型定义,方便代码移植
  4. ***************************************************/
  5. typedef unsigned char   UINT8;
  6. typedef unsigned int    UINT16;
  7. typedef unsigned long   UINT32;
  8.    
  9. typedef char            INT8;
  10. typedef int             INT16;
  11. typedef long            INT32;
  12. typedef bit             BOOL;

  13. /***************************************************
  14. *          大量宏定义,便于代码移植和阅读
  15. ***************************************************/
  16. //--------------------------------
  17.                                    //----头部----
  18. #define DCMD_CTRL_HEAD1      0x10  //PC下传控制包头部1
  19. #define DCMD_CTRL_HEAD2      0x01  //PC下传控制包头部2

  20.                                    //----命令码----
  21. #define DCMD_NULL            0x00  //命令码:空操作
  22. #define DCMD_CTRL_BELL       0x01  //命令码:控制蜂鸣器
  23. #define DCMD_CTRL_LED        0x02  //命令码:控制LED
  24. #define DCMD_REQ_DATA        0x03  //命令码:请求数据

  25.                                    //----数据----
  26. #define DCTRL_BELL_ON        0x01  //蜂鸣器响
  27. #define DCTRL_BELL_OFF       0x02  //蜂鸣器禁鸣
  28. #define DCTRL_LED_ON         0x03  //LED亮
  29. #define DCTRL_LED_OFF        0x04  //LED灭

  30. //--------------------------------
  31.                                    //----头部----
  32. #define UCMD_CTRL_HEAD1      0x20  //MCU上传控制包头部1
  33. #define UCMD_CTRL_HEAD2      0x01  //MCU上传控制包头部2

  34.                                    //----命令码----
  35. #define UCMD_NULL            0x00  //命令码:空操作
  36. #define UCMD_REQ_DATA        0x01  //命令码:请求数据


  37. #define CTRL_FRAME_LEN       0x04  //帧长度(不包含数据和校验值)
  38. #define PARITY_LEN           0x01  //检验值长度
  39. #define EN_UART()            ES=1  //允许串口中断
  40. #define NOT_EN_UART()       ES=0  //禁止串口中断

  41. #define BELL(x)             {if((x))P0_6=1 ;else P0_6=0;} //蜂鸣器控制宏函数
  42. #define LED(x)              {if((x))P2=0x00;else P2=0xFF;}//LED控制宏函数   

  43. #define TRUE                1
  44. #define FALSE               0

  45. #define HIGH                1
  46. #define LOW                 0   

  47. #define ON                  1
  48. #define OFF                 0

  49. #define NULL                (void *)0

  50. /*使用结构体对数据包进行封装
  51. *方便操作数据
  52. */
  53. typedef  struct _PKT_PARITY
  54. {
  55.     UINT8 m_ucHead1;       //首部1
  56.     UINT8 m_ucHead2;       //首部2
  57.     UINT8 m_ucOptCode;     //操作码
  58.     UINT8 m_ucDataLength;  //数据长度
  59.     UINT8 m_szDataBuf[16]; //数据

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

  61. }PKT_PARITY;

  62. /*使用共用体再一次对数据包进行封装
  63. *操作数据更加方便
  64. */
  65. typedef union _PKT_PARITY_EX
  66. {
  67.     PKT_PARITY r;
  68.     UINT8 p[32];
  69. } PKT_PARITY_EX;


  70. PKT_PARITY_EX    PktParityEx; //定义数据包变量
  71. BOOL  bLedOn=FALSE;     //定义是否点亮LED布尔变量
  72. BOOL  bBellOn=FALSE;    //定义是否蜂鸣器响布尔变量
  73. BOOL  bReqData=FALSE;   //定义是否请求数据布尔变量

  74. /******************************************************
  75. *函数名称:OddParity
  76. *输    入:buf 要校验的数据; len 校验数据的长
  77. *输    出:校验值
  78. *功    能:偶校验
  79. *******************************************************/
  80. BOOL OddParity(UINT8 *buf, UINT8 len)   
  81. {   
  82.     UINT8 i,j;   
  83.     UINT8 data_temp;   
  84.     BOOL  bParity;   

  85.     bParity = 1;  

  86.     for(j = 0; j < len;j++)   
  87.     {   
  88.         data_temp = *(buf + j);

  89.         for(i = 0; i < 8; i++)   
  90.         {   
  91.      
  92.             if((data_temp & 0x01) == 0x01)   
  93.             {   
  94.                 bParity ^= 1;   
  95.             }   

  96.             data_temp = data_temp >> 1;      
  97.         }   
  98.     }   

  99.     return bParity;   
  100. }
  101. /*************************************************************
  102. * 函数名称:BufClr
  103. * 输    入:dest 缓冲区; size 缓冲区大小
  104. * 输    出:无
  105. * 说    明:清空缓冲区
  106. **************************************************************/
  107. BOOL BufCpy(UINT8 * dest,UINT8 * src,UINT32 size)
  108. {
  109.     if(NULL ==dest || NULL==src ||NULL==size)
  110.     {
  111.         return FALSE;
  112.     }
  113.    
  114.     do
  115.     {
  116.         *dest++ = *src++;
  117.         
  118.     }while(--size!=0);
  119.    
  120.     return TRUE;
  121. }
  122. /****************************************************
  123. ** 函数名称: UartInit
  124. ** 输    入: 无
  125. ** 输    出: 无
  126. ** 功能描述: 串口初始化
  127. *****************************************************/         


 楼主| 春风的暖暖 发表于 2015-9-1 21:20 | 显示全部楼层
  1. void UartInit(void)
  2. {
  3.     SCON=0x40;
  4.     T2CON=0x34;
  5.     RCAP2L=0xD9;
  6.     RCAP2H=0xFF;
  7.     REN=1;
  8.     ES=1;
  9. }
  10. /****************************************************
  11. ** 函数名称: UARTSendByte
  12. ** 输    入: b 单个字节
  13. ** 输    出: 无
  14. ** 功能描述: 串口 发送单个字节
  15. *****************************************************/
  16. void UARTSendByte(UINT8 b)
  17. {
  18.       SBUF=b;
  19.      while(TI==0);
  20.      TI=0;
  21. }
  22. /****************************************************
  23. ** 函数名称: UARTSendByte
  24. ** 输    入: b 单个字节
  25. ** 输    出: 无
  26. ** 功能描述: 串口 发送单个字节
  27. *****************************************************/
  28. void UartSendNBytes(UINT8 *buf,UINT8 len)
  29. {
  30.      while(len--)
  31.      {
  32.          UARTSendByte(*buf++);
  33.      }
  34. }
  35. /****************************************************
  36. ** 函数名称: main
  37. ** 输    入: 无
  38. ** 输    出: 无
  39. ** 功能描述: 函数主题
  40. *****************************************************/
  41. void main(void)
  42. {
  43.       UINT8 i=0;
  44.      UINT8 ucCheckSum=0;

  45.      UartInit();//串口初始化

  46.      EA=1;      //开总中断
  47.      
  48.      while(1)
  49.      {
  50.           if(bLedOn)  //是否点亮Led
  51.           {
  52.              LED(ON);  
  53.           }
  54.           else
  55.           {
  56.              LED(OFF);
  57.           }
  58.          
  59.          
  60.           if(bBellOn)//是否响蜂鸣器
  61.           {
  62.              BELL(ON);
  63.           }
  64.           else
  65.           {
  66.              BELL(OFF);
  67.           }
  68.          
  69.           if(bReqData)//是否请求数据
  70.           {
  71.              bReqData=FALSE;

  72.              NOT_EN_UART(); //禁止串口中断
  73.             
  74.              PktParityEx.r.m_ucHead1=UCMD_CTRL_HEAD1;//MCU上传数据帧头部1
  75.              PktParityEx.r.m_ucHead2=UCMD_CTRL_HEAD2;//MCU上传数据帧头部2
  76.              PktParityEx.r.m_ucOptCode=UCMD_REQ_DATA;//MCU上传数据帧命令码
  77.             
  78.              PktParityEx.r.m_ucParity=OddParity(PktParityEx.p,
  79.                                                       CTRL_FRAME_LEN+
  80.                                                    PktParityEx.r.m_ucDataLength);//计算校验值

  81.                /*
  82.                 这样做的原因是因为有时写数据长度不一样,
  83.                   导致PktParityEx.r.m_ucParity会出现为0的情况
  84.                 所以使用BufCpy将校验值复制到相应的位置
  85.              */

  86.              BufCpy(&PktParityEx.p[CTRL_FRAME_LEN+PktParityEx.r.m_ucDataLength],
  87.                         &PktParityEx.r.m_ucParity,
  88.                       PARITY_LEN);
  89.             
  90.              UartSendNBytes(PktParityEx.p,
  91.                                CTRL_FRAME_LEN+
  92.                             PktParityEx.r.m_ucDataLength+
  93.                             PARITY_LEN);//发送数据

  94.              EN_UART();//允许串口中断
  95.                      
  96.           }
  97.      }
  98. }
 楼主| 春风的暖暖 发表于 2015-9-1 21:21 | 显示全部楼层
  1. /****************************************************
  2. ** 函数名称: UartIRQ
  3. ** 输    入: 无
  4. ** 输    出: 无
  5. ** 功能描述: 串口中断服务函数
  6. *****************************************************/
  7. void UartIRQ(void)interrupt 4
  8. {
  9.      static UINT8  uccnt=0;
  10.             UINT8  uclen;
  11.             UINT8  ucParity;
  12.      
  13.      if(RI) //是否接收到数据
  14.      {
  15.         RI=0;

  16.         PktParityEx.p[uccnt++]=SBUF;//获取单个字节

  17.         if(PktParityEx.r.m_ucHead1 == DCMD_CTRL_HEAD1)//是否有效的数据帧头部1
  18.         {
  19.            if(uccnt<CTRL_FRAME_LEN+PktParityEx.r.m_ucDataLength+PARITY_LEN)//是否接收完所有数据
  20.            {
  21.               if(uccnt>=2 && PktParityEx.r.m_ucHead2!=DCMD_CTRL_HEAD2)//是否有效的数据帧头部2
  22.               {
  23.                  uccnt=0;

  24.                  return;
  25.               }
  26.                     
  27.            }
  28.            else
  29.            {
  30.               
  31.               uclen=CTRL_FRAME_LEN+PktParityEx.r.m_ucDataLength;//获取数据帧有效长度(不包括校验值)

  32.               ucParity=OddParity(PktParityEx.p,uclen);//计算校验值

  33.                 /*
  34.                 这样做的原因是因为有时写数据长度不一样,
  35.                   导致PktParityEx.r.m_ucParity会出现为0的情况
  36.                 所以使用BufCpy将校验值复制到相应的位置
  37.                */
  38.               BufCpy(&PktParityEx.r.m_ucParity,
  39. &PktParityEx.p[uclen],
  40. PARITY_LEN);

  41.               if(ucParity!=PktParityEx.r.m_ucParity)//校验值是否匹配
  42.               {
  43.                   uccnt=0;

  44.                   return;  
  45.               }

  46.               switch(PktParityEx.r.m_ucOptCode)//从命令码中获取相对应的操作
  47.               {
  48.                 case DCMD_CTRL_BELL://控制蜂鸣器命令码
  49.                 {
  50.                      if(DCTRL_BELL_ON==PktParityEx.r.m_szDataBuf[0])//数据部分含控制码
  51.                      {
  52.                         bBellOn=TRUE;
  53.                      }
  54.                      else
  55.                      {
  56.                         bBellOn=FALSE;
  57.                      }
  58.                 }
  59.                 break;

  60.                 case DCMD_CTRL_LED://控制LED命令码
  61.                 {

  62.                      if(DCTRL_LED_ON==PktParityEx.r.m_szDataBuf[0])//数据部分含控制码
  63.                      {
  64.                         bLedOn=TRUE;
  65.                      }
  66.                      else
  67.                      {
  68.                         bLedOn=FALSE;
  69.                      }
  70.                 }
  71.                 break;

  72.                 case DCMD_REQ_DATA://请求数据命令码
  73.                 {
  74.                      bReqData=TRUE;
  75.                 }
  76.                 break;

  77.               }

  78.               uccnt=0;

  79.               return;
  80.            }

  81.         }
  82.         else
  83.         {
  84.             uccnt=0;
  85.         }

  86.      }
  87. }
ccw1986 发表于 2015-9-3 22:01 | 显示全部楼层
奇偶校验这种算法打成包最好了
598330983 发表于 2015-9-4 12:40 | 显示全部楼层
用的哪个串口?这个是硬件校验吗
稳稳の幸福 发表于 2015-9-4 20:48 | 显示全部楼层
晕死,是51的单片机啊,这可是新唐的地盘,新唐貌似都是arm吧。
mintspring 发表于 2015-9-28 15:59 来自手机 | 显示全部楼层
这都是噱头,从来没有用过的
wahahaheihei 发表于 2015-9-28 22:16 来自手机 | 显示全部楼层
几乎没有多少人用这个功能的。一般很少出错
yiyigirl2014 发表于 2015-9-29 10:06 来自手机 | 显示全部楼层
检验在要求较高的时候才用
gejigeji521 发表于 2015-9-29 11:10 来自手机 | 显示全部楼层
常规的应用一般不考虑的,特别低速的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

306

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部