新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機實現485總線現場監測系統

        單片機實現485總線現場監測系統

        作者: 時間:2016-11-18 來源:網絡 收藏
        在一些要求響應速度快、實時性強、控制量多的應用場合,往往理由多個單片機結合PC機組成分布系統,在這樣的系統中可以使用RS-485接口連接單片機和PC機。RS-485是RS-232的改良標準,在通信速率、傳輸距離、多機連接等方面較RS-232有了很大的提高,在軟件設計上和RS-232基本一致。在結合RS-485及有關資料基礎上學習了用單片機實現485總線現場監測系統。這個系統以PC機為主機,多個單片機為從機的現場監測系統,單片機組組成的各個節點負責采集終端設備的狀態信息,主機以輪詢的方式向各個節點獲取這些設備信息,并根據信息內容進行相關的操作。

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

        主要器件:

        1、PC機端的232/485轉換接口:MC1488和MC1489實現TTL電平和RS-232通信電平的轉化;PC147光電隔離器件;MAX481485驅動收發芯片。

        2、單片機端:AT89C52單片機芯片,用于數據采集和與485總線接口;MAX481485驅動收發芯片;DIP-6開關用于確定本機的設備號。

        試驗流程圖:

        主機端流程:


        單片機端流程圖:


        試驗電路圖:

        主機端

        單片機端:

        試驗程序代碼:

        // 485Mon.h程序

        #ifndef_485MON_H//防止485Mon.h被重復引用

        #define_485MON_H

        #include //引用標準庫的頭文件

        #include

        #include

        #define uchar unsigned char

        #define uint unsigned int

        #define ACTIVE0x11

        #define GETDATA0x22

        #define READY0x33

        #define SENDDATA0x44

        #define RECFRMMAXLEN 16//接收幀的最大長度,超過此值認為幀超長錯誤

        #define STATUSMAXLEN 10//設備狀態信息最大長度

        uchar DevNo;//設備號

        xdata uchar StatusBuf[STATUSMAXLEN];

        //為簡化起見,假設了10位固定的采集數據

        #define DATA00x10

        #define DATA10x20

        #define DATA20x30

        #define DATA30x40

        #define DATA40x50

        #define DATA50x60

        #define DATA60x70

        #define DATA70x80

        #define DATA80x90

        #define DATA90xA0

        sbit DE = P1^6;//驅動器使能,1有效

        sbit RE = P1^7;//接收器使能,0有效

        void init();//系統初始化

        void Get_Stat();//簡化的數據采集函數

        bit Recv_Data(uchar *type);//接收數據幀函數

        void Send(uchar m);//發送單字節數據

        void Send_Data(uchar type,uchar len,uchar *buf);//發送數據幀函數

        void Clr_StatusBuf();//清除設備狀態信息緩沖區函數

        #endif

        // 485Mon.c程序

        #include "485Mon.h"

        void main(void)

        {

        uchar type;

        /*初始化*/

        init();

        while (1)

        {

        if (Recv_Data(&type)==0)//接收幀錯誤或者地址不符合,丟棄

        continue;

        switch (type)

        {

        case ACTIVE://主機詢問從機是否在位

        Send_Data(READY,0,StatusBuf);//發送READY指令

        break;

        case GETDATA://主機讀設備請求

        Clr_StatusBuf();

        Get_Stat();//數據采集函數

        Send_Data(SENDDATA,strlen(StatusBuf),StatusBuf);

        break;

        default:

        break;//指令類型錯誤,丟棄當前幀

        }

        }

        }

        /*初始化*/

        void init(void)

        {

        P1 = 0xff;

        DevNo = (P1&0x00111111);//讀取本機設備號

        TMOD = 0x20;

        SCON = 0x50;

        TH1 = 0xfd;

        TL1 = 0xfd;

        TR1 = 1;

        PCON = 0x00;// SMOD=0

        EA = 0;

        }

        /*接收數據幀函數,實際上接收的是主機的指令*/

        bit Recv_Data(uchar *type)

        {

        uchar tmp,rCount,i;

        uchar r_buf[RECFRMMAXLEN];//保存接收到的幀

        uchar Flag_RecvOver;//一幀接收結束標志

        uchar Flag_StartRec;//一幀開始接收標志

        uchar CheckSum;//校驗和

        uchar DataLen;//數據字節長度變量

        /*禁止發送,允許接收*/

        DE = 0;

        RE = 0;

        /*接收一幀數據*/

        rCount = 0;

        Flag_StartRec = 0;

        Flag_RecvOver = 0;

        while (!Flag_RecvOver)

        {

        RI = 0;

        while (!RI);

        tmp = SBUF;

        RI=0;

        /*判斷是否收到字符$,其數值為0x24 */

        if ((!Flag_StartRec) && (tmp == 0x24))

        {

        Flag_StartRec = 1;

        }

        if (Flag_StartRec)

        {

        r_buf[rCount] = tmp;

        rCount ++;

        /*判斷是否收到字符*,其數值為0x2A,根據接收的指令設置相應標志位*/

        if (tmp == 0x2A)

        Flag_RecvOver = 1;

        }

        if (rCount == RECFRMMAXLEN)//幀超長錯誤,返回0

        return 0;

        }

        接上篇程序:

        /*計算校驗和字節*/

        CheckSum = 0;

        DataLen = r_buf[3];

        for (i=0;i++;i<3+DataLen)

        {

        CheckSum = CheckSum + r_buf[i+1];

        }

        /*判斷幀是否錯誤*/

        if (rCount<6)//幀過短錯誤,返回0,最短的指令幀為6個字節

        return 0;

        if (r_buf[1]!=DevNo)//地址不符合,錯誤,返回0

        return 0;

        if (r_buf[rCount-2]!=CheckSum)//校驗錯誤,返回0

        return 0;

        *type = r_buf[2];//獲取指令類型

        return 1;//成功,返回1

        }

        /*發送數據幀函數*/

        void Send_Data(uchar type,uchar len,uchar *buf)

        {

        uchar i,tmp;

        uchar CheckSum = 0;

        /*允許發送,禁止接收*/

        DE = 1;

        RE = 1;

        /*發送幀起始字節*/

        tmp = 0x24;

        Send(tmp);

        Send(DevNo);//發送地址字節,也即設備號

        CheckSum = CheckSum + DevNo;

        Send(type);//發送類型字節

        CheckSum = CheckSum + type;

        Send(len);//發送數據長度字節

        CheckSum = CheckSum + len;

        /*發送數據*/

        for (i=0;i

        {

        Send(*buf);

        CheckSum = CheckSum + *buf;

        buf++;

        }

        Send(CheckSum);//發送校驗和字節

        /*發送幀結束字節*/

        tmp = 0x2A;

        Send(tmp);

        }

        /*采集數據函數經過簡化處理,取固定的10個字節數據*/

        void Get_Stat(void)

        {

        StatusBuf[0]=DATA0;

        StatusBuf[1]=DATA1;

        StatusBuf[2]=DATA2;

        StatusBuf[3]=DATA3;

        StatusBuf[4]=DATA4;

        StatusBuf[5]=DATA5;

        StatusBuf[6]=DATA6;

        StatusBuf[7]=DATA7;

        StatusBuf[8]=DATA8;

        StatusBuf[9]=DATA9;

        }

        /*發送單字節數據*/

        void Send(uchar m)

        {

        TI = 0;

        SBUF = m;

        while(!TI);

        TI = 0;

        }

        /*清除設備狀態信息緩沖區函數*/

        void Clr_StatusBuf(void)

        {

        uchar i;

        for (i=0;i

        StatusBuf[i] = 0;

        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 聂荣县| 砀山县| 尉氏县| 武邑县| 土默特左旗| 河池市| 响水县| 通渭县| 兖州市| 安康市| 泽普县| 呼图壁县| 黄梅县| 得荣县| 渭源县| 印江| 藁城市| 白河县| 洛扎县| 会东县| 宁阳县| 沁阳市| 满城县| 松原市| 温泉县| 平武县| 巴彦淖尔市| 望奎县| 鲁甸县| 龙井市| 凌云县| 建平县| 泸定县| 兴安盟| 韶山市| 阳泉市| 长垣县| 小金县| 栾城县| 武安市| 乌海市|