新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 實(shí)現(xiàn)單片機(jī)與PC機(jī)多機(jī)通訊的程序

        實(shí)現(xiàn)單片機(jī)與PC機(jī)多機(jī)通訊的程序

        作者: 時間:2016-11-30 來源:網(wǎng)絡(luò) 收藏
        下面是我寫的一個實(shí)現(xiàn)多個下位機(jī)(單片機(jī))與一個上位機(jī)(PC機(jī))的一主多從串口通訊程序,用的STC89C52RC,定時器2做串口通信波特率發(fā)生器。

        實(shí)現(xiàn)功能是這樣的:
        用調(diào)試助手向單片機(jī)發(fā)送一個數(shù)據(jù)包。
        通訊協(xié)議是這樣的:
        數(shù)據(jù)包的格式如下所示(共10個字節(jié)組成):
        0x2A,0xEB,0x8D,地址碼,指令碼,數(shù)據(jù)長度碼,數(shù)據(jù)碼,數(shù)據(jù)碼,校驗(yàn)碼,0xAD
        前面三個字節(jié)為幀頭,即開始符。
        地址碼: 欲傳送的目的地址,即選定哪一個單片機(jī)。
        指令碼:向單片機(jī)發(fā)送的指令
        數(shù)據(jù)長度碼: 用于指示后面有效數(shù)據(jù)的個數(shù)
        數(shù)據(jù)碼:傳送的數(shù)據(jù),配合指令碼的純數(shù)據(jù)。
        校驗(yàn)碼: 累加和校驗(yàn),對地址碼,指令碼,數(shù)據(jù)長度碼,數(shù)據(jù)碼進(jìn)行累加,用來檢驗(yàn)數(shù)據(jù)的完整性和正確性。
        0xAD : 幀尾,即結(jié)束符。

        本文引用地址:http://www.104case.com/article/201611/323815.htm

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

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

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


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

        /*
        * 函數(shù)名:Data_analysis
        * 描 述:通信協(xié)議解析函數(shù)
        * 輸 入:無
        * 輸 出:無
        * 備 注:解析串口接收到的數(shù)據(jù)


        上一頁 1 2 下一頁

        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 方城县| 丰顺县| 阳新县| 涞源县| 博乐市| 五家渠市| 浦城县| 宁安市| 衡南县| 梓潼县| 曲水县| 舒城县| 新营市| 乌兰县| 临沭县| 上饶县| 慈溪市| 大安市| 镶黄旗| 临夏市| 湖南省| 武夷山市| 怀远县| 孟村| 巴东县| 额尔古纳市| 保康县| 德阳市| 北京市| 邹平县| 张掖市| 二连浩特市| 铜川市| 凉城县| 宜城市| 惠东县| 沙坪坝区| 施秉县| 吕梁市| 岳西县| 长海县|