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

[复制链接]
 楼主| 发表于 2015-12-17 16:20 | 显示全部楼层 |阅读模式
  1. #include "at89x52.h"
  2. /***************************************************
  3. *          类型定义,方便代码移植
  4. ***************************************************/
  5. typedef unsigned char   UINT8;
  6. typedef unsigned int UINT16;
  7. typedef unsigned long   UINT32;   
  8. typedef char            INT8;
  9. typedef int             INT16;
  10. typedef long            INT32;
  11. typedef bit             BOOL;
  12. /***************************************************
  13. *          大量宏定义,便于代码移植和阅读
  14. ***************************************************/
  15. //-------------------------------- //----头部----
  16. #define DCMD_CTRL_HEAD1      0x10  //PC下传控制包头部1
  17. #define DCMD_CTRL_HEAD2      0x01  //PC下传控制包头部2
  18.                                    //----命令码----
  19. #define DCMD_NULL            0x00  //命令码:空操作
  20. #define DCMD_CTRL_BELL       0x01  //命令码:控制蜂鸣器
  21. #define DCMD_CTRL_LED        0x02  //命令码:控制LED
  22. #define DCMD_REQ_DATA        0x03  //命令码:请求数据
  23.                                    //----数据----
  24. #define DCTRL_BELL_ON        0x01  //蜂鸣器响
  25. #define DCTRL_BELL_OFF       0x02  //蜂鸣器禁鸣
  26. #define DCTRL_LED_ON         0x03  //LED亮
  27. #define DCTRL_LED_OFF        0x04  //LED灭
  28. //-------------------------------- //----头部----
  29. #define UCMD_CTRL_HEAD1      0x20  //MCU上传控制包头部1
  30. #define UCMD_CTRL_HEAD2      0x01  //MCU上传控制包头部2
  31.                                    //----命令码----
  32. #define UCMD_NULL            0x00  //命令码:空操作
  33. #define UCMD_REQ_DATA        0x01  //命令码:请求数据
  34. #define CTRL_FRAME_LEN       0x04  //帧长度(不包含数据和校验值)
  35. #define CHECKSUM_LEN         0x01  //检验值长度
  36. #define EN_UART()            ES=1 //允许串口中断
  37. #define NOT_EN_UART()        ES=0 //禁止串口中断
  38. #define BELL(x)             {if((x))P0_6=1 ;else P0_6=0;} //蜂鸣器控制宏函数
  39. #define LED(x)              {if((x))P2=0x00;else P2=0xFF;}//LED控制宏函数
  40. #define TRUE                1
  41. #define FALSE               0
  42. #define HIGH                1
  43. #define LOW                 0
  44. #define ON                  1
  45. #define OFF                 0
  46. #define NULL                (void *)0


 楼主| 发表于 2015-12-17 16:20 | 显示全部楼层
  1. //使用结构体对数据包进行封装方便操作数据
  2. typedef  struct _PKT_SUM
  3. {
  4. UINT8 m_ucHead1;       //首部1
  5. UINT8 m_ucHead2;       //首部2
  6. UINT8 m_ucOptCode;     //操作码
  7. UINT8 m_ucDataLength;  //数据长度
  8. UINT8 m_szDataBuf[16]; //数据
  9. UINT8 m_ucCheckSum;    //CRC16为2个字节
  10. }PKT_SUM;
  11. //使用共用体再一次对数据包进行封装操作数据更加方便
  12. typedef union _PKT_SUM_EX
  13. {
  14. PKT_SUM r;
  15. UINT8 p[32];
  16. } PKT_SUM_EX;
  17. PKT_SUM_EX    PktSumEx; //定义数据包变量
  18. BOOL  bLedOn=FALSE;     //定义是否点亮LED布尔变量
  19. BOOL  bBellOn=FALSE;    //定义是否蜂鸣器响布尔变量
  20. BOOL  bReqData=FALSE;   //定义是否请求数据布尔变量
 楼主| 发表于 2015-12-17 16:21 | 显示全部楼层
  1. /****************************************************
  2. ** 函数名称: CheckSum
  3. ** 输    入: buf 要校验的数据;
  4.              len 要校验的数据的长度
  5. ** 输    出: 校验值
  6. ** 功能描述: 计算校验和
  7. *****************************************************/
  8. UINT16 CheckSum(UINT8 *buf, UINT8 len)
  9. {
  10.    UINT8 i=0,Sum=0;
  11.    for (i=0;i<len;i++)
  12.    {
  13.     Sum+=*buf++;
  14.    }
  15.    return Sum;
  16. }
  17. /*************************************************************
  18. * 函数名称:BufCpy
  19. * 输    入:dest目标缓冲区;
  20.            Src  源缓冲区
  21.            size 复制数据的大小
  22. * 输    出:无
  23. * 说    明:复制缓冲区
  24. **************************************************************/
  25. BOOL BufCpy(UINT8 * dest,UINT8 * src,UINT32 size)
  26. {
  27.     if(NULL ==dest || NULL==src ||NULL==size)
  28.     {
  29.      return FALSE;
  30.     }   
  31. do
  32. {
  33.   *dest++ = *src++;  
  34. }while(--size!=0);
  35. return TRUE;
  36. }
 楼主| 发表于 2015-12-17 16:22 | 显示全部楼层
  1. /****************************************************
  2. ** 函数名称: UartInit
  3. ** 输    入: 无
  4. ** 输    出: 无
  5. ** 功能描述: 串口初始化
  6. *****************************************************/                                                                              
  7. void UartInit(void)
  8. {
  9. SCON=0x40;
  10. T2CON=0x34;
  11. RCAP2L=0xD9;
  12. RCAP2H=0xFF;
  13. REN=1;
  14.     ES=1;
  15. }
  16. /****************************************************
  17. ** 函数名称: UARTSendByte
  18. ** 输    入: b 单个字节
  19. ** 输    出: 无
  20. ** 功能描述: 串口 发送单个字节
  21. *****************************************************/
  22. void UARTSendByte(UINT8 b)
  23. {
  24.    SBUF=b;
  25.   while(TI==0);
  26.   TI=0;
  27. }
 楼主| 发表于 2015-12-17 16:24 | 显示全部楼层
  1. /****************************************************
  2. ** 函数名称: UARTSendByte
  3. ** 输    入: b 单个字节
  4. ** 输    出: 无
  5. ** 功能描述: 串口 发送单个字节
  6. *****************************************************/
  7. void UartSendNBytes(UINT8 *buf,UINT8 len)
  8. {
  9.      while(len--)
  10.      {
  11.          UARTSendByte(*buf++);
  12.      }
  13. }
  14. code INT8 HexTable[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  15. void UARTCiPrintfString(const INT8 *str)
  16. {
  17.      while(str && *str)
  18.      {   
  19.         UARTSendByte(*str++);               
  20.      }
  21. }
  22. void UARTCiPrintfVal(UINT8 *str,UINT32 val,UINT8 show)
  23. {   
  24.      UINT8 i=0;
  25.      UINT8 buf[10]={0};   
  26.   UARTCiPrintfString(str);
  27.      if(10 == show)
  28.      {
  29.          for(i=0; i<10 ;i++)
  30.          {
  31.              buf[i]=(UINT8)('0'+val%10);  
  32.              val/=10;  
  33.          }        
  34.          for(i=9;i>=0;)
  35.          {
  36.              if('0' == buf[i])
  37.              {
  38.                  i--;
  39.              }
  40.              else
  41.              {
  42.                 break;
  43.              }
  44.          }        
  45.          while(1)
  46.          {   
  47.             
  48.              UARTSendByte(buf[i]);            
  49.              if(!i)
  50.              {
  51.                  break;
  52.              }            
  53.              i--;
  54.          }         
  55.      }   
  56.      if(16 == show)
  57.      {
  58.         UARTSendByte('0');
  59.      UARTSendByte('x');   
  60.         i=28;      
  61.         while(i)
  62.         {
  63.             if(0  == ((val>>i) &0x0f))
  64.             {  
  65.                 i=i-4;              
  66.             }
  67.             else
  68.             {
  69.                 break;
  70.             }
  71.         }      
  72.         while(1)
  73.         {
  74.             UARTSendByte(HexTable[(val>>i) &0x0f]);            
  75.             if(!i)
  76.             {
  77.                 break;
  78.             }                    
  79.             i=i-4;
  80.         }      
  81.      }   
  82.      UARTCiPrintfString("\r\n");
  83. }
 楼主| 发表于 2015-12-17 16:24 | 显示全部楼层
  1. #define DEBUGMSG   UARTCiPrintfString
  2. #define DEBUGMSGEx UARTCiPrintfVal
  3. /****************************************************
  4. ** 函数名称: main
  5. ** 输    入: 无
  6. ** 输    出: 无
  7. ** 功能描述: 函数主题
  8. *****************************************************/
  9. void main(void)
  10. {
  11.      UINT8 i=0;
  12.   UINT8 ucCheckSum=0;
  13.   UartInit();//串口初始化
  14.   EA=1;      //开总中断
  15.      while(1)
  16.      {
  17.           if(bLedOn)  //是否点亮Led
  18.     {
  19.        LED(ON);
  20.     }
  21.     else
  22.     {
  23.        LED(OFF);
  24.     }  
  25.     if(bBellOn)//是否响蜂鸣器
  26.     {
  27.        BELL(ON);
  28.     }
  29.     else
  30.     {
  31.        BELL(OFF);
  32.     }   
  33.     if(bReqData)//是否请求数据
  34.     {
  35.        bReqData=FALSE;
  36.     NOT_EN_UART(); //禁止串口中断   
  37.     PktSumEx.r.m_ucHead1=UCMD_CTRL_HEAD1;//MCU上传数据帧头部1
  38.     PktSumEx.r.m_ucHead2=UCMD_CTRL_HEAD2;//MCU上传数据帧头部2
  39.     PktSumEx.r.m_ucOptCode=UCMD_REQ_DATA;//MCU上传数据帧命令码   
  40.     PktSumEx.r.m_ucCheckSum=CheckSum(PktSumEx.p,CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength);//计算校验值
  41.          //这样做的原因是因为有时写数据长度不一样,导致PktSumEx.r.m_ucCheckSum会出现为0的情况,所以使用BufCpy将校验值复制到相应的位置
  42.     BufCpy(&PktSumEx.p[CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength],&PktSumEx.r.m_ucCheckSum,CHECKSUM_LEN);   
  43.     UartSendNBytes(PktSumEx.p,CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength+CHECKSUM_LEN);//发送数据
  44.     EN_UART();//允许串口中断      
  45.     }
  46.      }
  47. }
 楼主| 发表于 2015-12-17 16:25 | 显示全部楼层
  1. /****************************************************
  2. ** 函数名称: UartIRQ
  3. ** 输    入: 无
  4. ** 输    出: 无
  5. ** 功能描述: 串口中断服务程序
  6. *****************************************************/
  7. void UartIRQ(void)interrupt 4
  8. {
  9.      static UINT8  uccnt=0;
  10.          UINT8  uclen;
  11.    UINT8  ucCheckSum;   
  12.      if(RI) //是否接收到数据
  13.      {
  14.         RI=0;
  15.         PktSumEx.p[uccnt++]=SBUF;//获取单个字节
  16.         if(PktSumEx.r.m_ucHead1 == DCMD_CTRL_HEAD1)//是否有效的数据帧头部1
  17.         {
  18.            if(uccnt<CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength+CHECKSUM_LEN)//是否接收完所有数据
  19.            {
  20.               if(uccnt>=2 && PktSumEx.r.m_ucHead2!=DCMD_CTRL_HEAD2)//是否有效的数据帧头部2
  21.               {
  22.                  uccnt=0;
  23.                  return;
  24.               }                  
  25.            }
  26.            else
  27.            {      
  28.         uclen=CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength;//获取数据帧有效长度(不包括校验值)
  29.      ucCheckSum=CheckSum(PktSumEx.p,uclen);//计算校验值
  30.           //这样做的原因是因为有时写数据长度不一样,导致PktSumEx.r.m_ucCheckSum会出现为0的情况,所以使用BufCpy将校验值复制到相应的位置
  31.      BufCpy(&PktSumEx.r.m_ucCheckSum,&PktSumEx.p[uclen],CHECKSUM_LEN);
  32.      //DEBUGMSGEx("ucCheckSum:=",ucCheckSum,16);
  33.      //DEBUGMSGEx("PktSumEx.r.m_ucCheckSum:=",PktSumEx.r.m_ucCheckSum,16);
  34.      //DEBUGMSG("CheckSuming ...\r\n");
  35.      if(ucCheckSum!=PktSumEx.r.m_ucCheckSum)//校验值是否匹配
  36.      {
  37.          uccnt=0;
  38.          return;
  39.      }
  40.     // DEBUGMSG("CheckSum OK\r\n");
  41.               switch(PktSumEx.r.m_ucOptCode)//从命令码中获取相对应的操作
  42.               {
  43.                 case DCMD_CTRL_BELL://控制蜂鸣器命令码
  44.                 {
  45.       if(DCTRL_BELL_ON==PktSumEx.r.m_szDataBuf[0])//数据部分含控制码
  46.       {
  47.          bBellOn=TRUE;
  48.       }
  49.       else
  50.       {
  51.          bBellOn=FALSE;
  52.       }
  53.                 }
  54.                 break;
  55.                 case DCMD_CTRL_LED://控制LED命令码
  56.                 {
  57.       if(DCTRL_LED_ON==PktSumEx.r.m_szDataBuf[0])//数据部分含控制码
  58.       {
  59.          bLedOn=TRUE;
  60.       }
  61.       else
  62.       {
  63.          bLedOn=FALSE;
  64.       }
  65.                 }
  66.                 break;
  67.                 case DCMD_REQ_DATA://请求数据命令码
  68.                 {
  69.                      bReqData=TRUE;
  70.                 }
  71.                 break;
  72.               }
  73.               uccnt=0;
  74.               return;
  75.            }
  76.         }
  77.         else
  78.         {
  79.             uccnt=0;
  80.         }
  81.      }
  82. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

277

帖子

1

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