<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        51通訊協議—和校驗

        作者:佚名   來源:本站原創   點擊數:  更新時間:2014年09月01日   【字體:

         

         
        #include "at89x52.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<len;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;
        }
        /****************************************************
        ** 函數名稱: UARTSendByte
        ** 輸    入: b 單個字節
        ** 輸    出: 無
        ** 功能描述: 串口 發送單個字節
        *****************************************************/
        void UartSendNBytes(UINT8 *buf,UINT8 len)
        {
             while(len--)
             {
                 UARTSendByte(*buf++);
             }
        }
        code INT8 HexTable[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        void UARTCiPrintfString(const INT8 *str)
        {
             while(str && *str)
             {    
                UARTSendByte(*str++);               
             }
        }
        void UARTCiPrintfVal(UINT8 *str,UINT32 val,UINT8 show)
        {   
             UINT8 i=0;
             UINT8 buf[10]={0};    
          UARTCiPrintfString(str);
             if(10 == show)
             {
                 for(i=0; i<10 ;i++)
                 {
                     buf[i]=(UINT8)('0'+val%10);  
                     val/=10;  
                 }        
                 for(i=9;i>=0;)
                 {
                     if('0' == buf[i])
                     {
                         i--;
                     }
                     else
                     {
                        break;
                     }
                 }        
                 while(1)
                 {   
                    
                     UARTSendByte(buf[i]);             
                     if(!i)
                     {
                         break;
                     }            
                     i--;
                 }         
             }    
             if(16 == show)
             {
                UARTSendByte('0');
             UARTSendByte('x');    
                i=28;       
                while(i)
                {
                    if(0  == ((val>>i) &0x0f))
                    {  
                        i=i-4;              
                    }
                    else
                    {
                        break;
                    }
                }       
                while(1)
                {
                    UARTSendByte(HexTable[(val>>i) &0x0f]);            
                    if(!i)
                    {
                        break;
                    }                    
                    i=i-4;
                }       
             }    
             UARTCiPrintfString("\r\n");
        }
        #define DEBUGMSG   UARTCiPrintfString
        #define DEBUGMSGEx UARTCiPrintfVal
        /****************************************************
        ** 函數名稱: 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);//計算校驗值
                 //這樣做的原因是因為有時寫數據長度不一樣,導致PktSumEx.r.m_ucCheckSum會出現為0的情況,所以使用BufCpy將校驗值復制到相應的位置
            BufCpy(&PktSumEx.p[CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength],&PktSumEx.r.m_ucCheckSum,CHECKSUM_LEN);   
            UartSendNBytes(PktSumEx.p,CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength+CHECKSUM_LEN);//發送數據
            EN_UART();//允許串口中斷      
            }
             }
        }
        /****************************************************
        ** 函數名稱: UartIRQ
        ** 輸    入: 無
        ** 輸    出: 無
        ** 功能描述: 串口中斷服務程序
        *****************************************************/
        void UartIRQ(void)interrupt 4
        {
             static UINT8  uccnt=0;
                 UINT8  uclen;
           UINT8  ucCheckSum;    
             if(RI) //是否接收到數據
             {
                RI=0;
                PktSumEx.p[uccnt++]=SBUF;//獲取單個字節
                if(PktSumEx.r.m_ucHead1 == DCMD_CTRL_HEAD1)//是否有效的數據幀頭部1
                {
                   if(uccnt<CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength+CHECKSUM_LEN)//是否接收完所有數據
                   {
                      if(uccnt>=2 && PktSumEx.r.m_ucHead2!=DCMD_CTRL_HEAD2)//是否有效的數據幀頭部2
                      {
                         uccnt=0;
                         return;
                      }                   
                   }
                   else
                   {       
                uclen=CTRL_FRAME_LEN+PktSumEx.r.m_ucDataLength;//獲取數據幀有效長度(不包括校驗值)
             ucCheckSum=CheckSum(PktSumEx.p,uclen);//計算校驗值
                  //這樣做的原因是因為有時寫數據長度不一樣,導致PktSumEx.r.m_ucCheckSum會出現為0的情況,所以使用BufCpy將校驗值復制到相應的位置
             BufCpy(&PktSumEx.r.m_ucCheckSum,&PktSumEx.p[uclen],CHECKSUM_LEN);
             //DEBUGMSGEx("ucCheckSum:=",ucCheckSum,16);
             //DEBUGMSGEx("PktSumEx.r.m_ucCheckSum:=",PktSumEx.r.m_ucCheckSum,16);
             //DEBUGMSG("CheckSuming ...\r\n");
             if(ucCheckSum!=PktSumEx.r.m_ucCheckSum)//校驗值是否匹配
             {
                 uccnt=0;
                 return; 
             }
            // DEBUGMSG("CheckSum OK\r\n");
                      switch(PktSumEx.r.m_ucOptCode)//從命令碼中獲取相對應的操作
                      {
                        case DCMD_CTRL_BELL://控制蜂鳴器命令碼
                        {
              if(DCTRL_BELL_ON==PktSumEx.r.m_szDataBuf[0])//數據部分含控制碼
              {
                 bBellOn=TRUE;
              }
              else
              {
                 bBellOn=FALSE;
              }
                        }
                        break;
                        case DCMD_CTRL_LED://控制LED命令碼
                        {
              if(DCTRL_LED_ON==PktSumEx.r.m_szDataBuf[0])//數據部分含控制碼
              {
                 bLedOn=TRUE;
              }
              else
              {
                 bLedOn=FALSE;
              }
                        }
                        break;
                        case DCMD_REQ_DATA://請求數據命令碼
                        {
                             bReqData=TRUE;
                        }
                        break;
                      }
                      uccnt=0;
                      return;
                   }
                }
                else
                {
                    uccnt=0;
                }
             }
        }
         
        關閉窗口
        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮