久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: 我寫的一個實現單片機與PC機多機通訊的程序 串口通信 [打印本頁]

作者: 51hei社區    時間: 2016-1-14 00:10
標題: 我寫的一個實現單片機與PC機多機通訊的程序 串口通信
   下面是我寫的一個實現多個下位機(單片機)與一個上位機(PC機)的一主多從串口通訊程序,用的STC89C52RC,定時器2做串口通信波特率發生器。
     實現功能是這樣的:
     用調試助手向單片機發送一個數據包。
     通訊協議是這樣的:
      數據包的格式如下所示(共10個字節組成):
0x2A,0xEB,0x8D,地址碼,指令碼,數據長度碼,數據碼,數據碼,校驗碼,0xAD  
前面三個字節為幀頭,即開始符。
地址碼: 欲傳送的目的地址,即選定哪一個單片機。
指令碼:向單片機發送的指令
數據長度碼: 用于指示后面有效數據的個數
數據碼:傳送的數據,配合指令碼的純數據。
校驗碼: 累加和校驗,對地址碼,指令碼,數據長度碼,數據碼進行累加,用來檢驗數據的完整性和正確性。
0xAD : 幀尾,即結束符。

    本程序實現功能是這樣的:
    用調試助手向單片機發送一個數據包,單片機收到后對數據解析,再回傳指定的數據。
    例如發送:2a eb 8d 01 03 01 01 06 ad
指令碼為01,單片機接收到后解析,回傳0xce 0x7b 0x11 0xed。其中前兩個字節為開始符,最后一個字節為結束符。同理,若收到的指令碼為02,回傳0xce 0x7b 0x12 0xed。以此模擬控制單片機操作。
若接收錯誤,即累加校驗碼不等于單片機實際計算的累加和,回傳0xce 0x7b 0x02 0xed,提示接收錯誤,要求PC重發數據(模擬,需要上位機軟件配合才行)。
單片機開機初始化后即向PC發送一個數據0xce 0x7b 0x00 0xed,用于指示單片機與PC通信已連接。

下面是程序:
#define ID 0x01 //單片機地址
uint8 rec_data;   //串口通信接收數據
uint8 state_flag=0;  //通信協議解析狀態標志,初始化為0
uint8 retval=0;  //通信協議解析函數返回值,初始化為0
uint8 cmd;  //指令碼
uint8 Data[2];  //數據碼
uint8 data_count;  //數據長度碼

程序大體思想是:
    首先定義了幾個全局變量,接收到數據后,串口中斷子程序中用變量rec_data存儲一個字節的數據,隨后對數據進行解析:首先判斷數據包的完整性,正確性,然后提取指令碼,數據碼等數據,存放起來用于主程序處理。
    協議解析過程中,使用一個變量state_flag的全局變量作為協議解析狀態標志,用于確定當前字節處于一幀數據中的那個部位,同時在接收過程中自動對接收數據進行校驗和處理,在數據包接收完的同時也進行了校驗的比較。因此當幀尾結束符接收到的時候,則表示一幀數據已經接收完畢,并且也通過了校驗,關鍵數據也保存到了緩沖區(cmd和Data[])中。主程序即可通過查詢retval的標志位來進行協議的解析處理。如果retval=1;   //錯誤標志,數據包傳送不正確。如果retval=2;   //接收成功標志,數據包傳送成功。
    接收過程中,只要哪一步收到的數據不是預期值,則直接將狀態標志復位,用于下一幀數據的判斷,避免狀態自鎖。
    以下是程序:
void PortInit();                //各端口初始化
void TimerInit();        //定時器初始化
void UsartInit();        //串口初始化
void usart_cmd_scan();        //串口命令掃描
void Data_analysis();   //通信協議解析函數
void Send(uint8 sendcmd);  //數據發送函數


/*--------------------------------        串口中斷服務子程序 ------------------------------------*/
void ser() interrupt 4
{
   RI=0;
   rec_data=SBUF;   //讀取接收到的數據
   Data_analysis();//數據解析  
}

/*
* 函數名:Data_analysis
* 描  述:通信協議解析函數
* 輸  入:無
* 輸  出:無
* 備  注:解析串口接收到的數據
/*--------------------------------        多機通信協議格式 ------------------------------------*/
/*  數據包的格式如下所示(共10個字節組成): */
/*  0x2A,0xEB,0x8D,地址碼,指令碼,數據長度碼,數據碼,數據碼,校驗碼,0xAD  */
void Data_analysis()
{
   static uchar recdata_sum=0;  //存放累加和
   static uchar lencnt=0;  //數據長度計數器
   switch (state_flag)
     {
        case 0:
          {
             if(rec_data == 0x2A)     // 是否幀頭第一個數據
               state_flag = 1;
             else
               state_flag = 0;    // 標志復位
             break;      
          }
        case 1:
          {
             if(rec_data == 0xEB)     // 是否幀頭第二個數據
               state_flag = 2;
             else
               state_flag = 0;    // 標志復位
             break;
          }
        case 2:
          {
             if(rec_data == 0x8D)     // 是否幀頭第三個數據
               state_flag = 3;
             else
               state_flag = 0;    // 標志復位
             break;
          }
        case 3:
          {
             if(rec_data == ID)    // 判斷目的地址是否正確
               {
                  state_flag = 4;
                  recdata_sum=rec_data;   //開始累加
               }   
             else
               state_flag = 0;   // 標志復位
             break;
          }
        case 4:
          {
             state_flag = 5;
             cmd=rec_data;  //指令碼存儲
             recdata_sum+=rec_data;  //累加
             break;
          }        
        case 5:
          {
             lencnt = 0;  //數據長度計數器清零
             data_count=rec_data;  //數據長度碼存儲
             recdata_sum+=rec_data;  //累加
             if (data_count!=0)  //后面有數據碼
               state_flag=6;
             else
               state_flag=8;
             break;
          }
        case 6:
        case 7:
          {
              Data[lencnt++]=rec_data;  //數據碼保存
              recdata_sum+=rec_data;   //累加
              if(lencnt==data_count)
              {
                                          state_flag=8;
                                        lencnt = 0;        
                          }  

              else
                state_flag=7;
              break;
          }
        case 8:
          {
             if(recdata_sum==rec_data)   //數據校驗,判斷累加和是否相等
               state_flag=9;
             else
               {
                  retval=1;   //置錯誤標志,數據包傳送不正確。
                  state_flag=0;   
               }
                         recdata_sum=0;//累加和清零
             break;
          }
        case 9:
          {
             if (rec_data==0xAD)
               {
                                           retval=2;   //置接收成功標志,數據包傳送成功。
                                        state_flag=0;
                           }
             else
               state_flag=0;
             break;
          }

     }
}

//主程序 , 不斷掃描串口接收到的命令
void main()
{
        PortInit();                //各端口初始化
        TimerInit();        //定時器初始化
        UsartInit();        //串口初始化                                   
        Send(0xce);
        Send(0x7b);
        Send(0x00);
        Send(0xed);
        while(1)
        {
                usart_cmd_scan();        //串口命令掃描
        }        
}


/*
* 函數名:usart_cmd_scan
* 描  述:串口命令掃描
* 輸  入:無
* 輸  出:無
* 備  注:掃描PC通過串口發送的命令
*/
void usart_cmd_scan()
{
        uchar sendcmd;   //下位機向PC發送的命令碼
           switch (retval)
    {
        case 1:      //數據發送錯誤,請求PC重發
          {
             sendcmd=2;  //向PC發送的重發數據命令,PC識別后向下位機重發數據包。
             Send(0xce);
                         Send(0x7b);
                         Send(sendcmd);
                         Send(0xed);  //向PC發送命令

                         retval=0;   //標志清零,防止重復掃描,重復執行。  2013/9/24
                         break;

          }
        case 2:      //數據發送成功,執行命令
          {
             switch (cmd)    //命令解碼
                         {
                                 case 0x01:
                                {
                                        Send(0xce);
                                        Send(0x7b);
                                        Send(0x11);
                                        Send(0xed);
                                        cmd=0x00;
                                        break;
                                }
                                case 0x02:
                                {
                                        Send(0xce);
                                        Send(0x7b);
                                        Send(0x12);
                                        Send(0xed);
                                        cmd=0x00;
                                        break;
                                }
                                case 0x03:
                                {
                                        Send(0xce);
                                        Send(0x7b);
                                        Send(0x13);
                                        Send(0xed);
                                        cmd=0x00;
                                        break;
                                }                 
                         }
            }
                  retval=0;   //標志清零,防止重復掃描,重復執行。
     }
}


/*
* 函數名:Send
* 描  述:串口數據發送函數
* 輸  入:sendcmd - 待發送的數據
* 輸  出:無
* 備  注:
*/
void Send(uint8 sendcmd)
{
   ES=0;  //關閉串口
   SBUF=sendcmd;  //發送數據,向PC發送。
   while(!TI);
   TI=0;  //發送完成,TI清零
   ES=1;  //開串口
}

以上是我寫的這個程序,希望大家指點一下。
程序運行整體可以,但是有個問題,也希望大神們能幫忙看一下什么問題
每次在單片機關機后,再重新上電后,發送都沒反應,只有手動按下開發板的復位鍵后才能正常通信,當再次斷電上電后,又不行了,又得按復位鍵才正常。按說開發板上電就復位了呀,為什么還要手動復位才行?什么的問題?你們試一下這個程序有這個問題嗎?
    還望大神們幫忙指點啊!


作者: 傻叉式告白    時間: 2016-1-15 09:21
復位的時間不同步    時序問題吧      我剛學單片機   這是我自己的理解
作者: 明白    時間: 2016-1-30 11:59
每一個數據包在接收的時候,要加上超時約定,超過這個約定時間就要重新來
作者: 123.123    時間: 2017-12-13 16:58
發送數據后延時

作者: cm976201    時間: 2018-12-12 22:20
明白 發表于 2016-1-30 11:59
每一個數據包在接收的時候,要加上超時約定,超過這個約定時間就要重新來

你好,請問這個超時約定應該怎么寫呢?要用到定時器中斷嗎
作者: xy51hei    時間: 2019-6-6 16:56
寫得不錯,樓主有crc16校驗的例程么。
作者: kepuple    時間: 2019-6-7 09:12
開機收不到連接信息,再次發送連接
作者: 3310mad2    時間: 2021-4-1 20:33
mark一下,有時間仔細學學




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 国产精品久久久久久久久久免费 | 亚洲第一天堂 | 国产一区二区精品在线 | 91精品国产91久久久久久 | 日韩欧美高清dvd碟片 | 久久免费视频2 | 波波电影院一区二区三区 | 成人福利在线视频 | 成人午夜电影在线观看 | 欧美在线a | 国产精品三级久久久久久电影 | 日本二区在线观看 | 精品国产高清一区二区三区 | 在线看无码的免费网站 | 成人黄色在线 | 欧美日韩电影在线 | 精品国产精品 | 欧美久久大片 | 性高朝久久久久久久3小时 av一区二区三区四区 | 日韩在线国产精品 | 久草日韩| 青娱乐自拍 | 久久精品 | 911精品美国片911久久久 | 欧美在线视频一区 | 国产一区二区三区四区三区四 | 亚洲精品二区 | 超碰在线播 | 亚洲一区久久 | 国产日韩免费视频 | 亚洲精品国产电影 | 久久精品免费 | 精品欧美乱码久久久久久 | 久久久久久a | 在线免费观看亚洲 | 日本精品免费 | 欧美a级成人淫片免费看 | 99精品电影 | 99精品视频一区二区三区 | 亚洲一区 中文字幕 | 久久久亚洲成人 |