新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 485通信程序(51單片機)

        485通信程序(51單片機)

        作者: 時間:2016-11-11 來源:網絡 收藏
        #include

        #include

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

        #defineucharunsignedchar

        #defineuintunsignedint

        /*通信命令*/

        #define_ACTIVE_0x01//主機詢問從機是否存在

        #define_GETDATA_0x02//主機發送讀設備請求

        #define_OK_0x03//從機應答

        #define_STATUS_0x04//從機發送設備狀態信息

        #define_MAXSIZE0x08//緩沖區長度

        #define_ERRLEN12//任何通信幀長度超過12則表示出錯

        uchardbuf[MAXSIZE]; //該緩沖區用于保存設備狀態信息

        uchardev;//該字節用于保存本機設備號

        sbitM_DE=P1^0;//驅動器使能,1有效

        sbitM_RE=P1^1;//接收器使能,0有效

        voidget_status();//調用該函數獲得設備狀態信息,函數全碼未給出

        voidsend_data(uchartype,ucharlen,uchar*buf);//發送數據幀

        bitrecv_cmd(uchar*type);//接收主機命令,主機請求包含命令信息。

        voidsend_byte(ucharda);//該函數發送一幀數據中的一個字節,由send_data()函數調用

        voidmain()

        {

        uchartype;

        ucharlen;

        /*系統初始化*/

        P1=0xff;//讀取本機設備號

        dev=(P1>>2);

        TMOD=0x20;//定時器T1使用方式2

        TH1=250;

        TL1=250;

        TR1=1;//開始計時

        PCON=0x80;//SMOD=1;

        SCON=0x50;//工作方式1,波特優選法9600bps,允許接收

        ES=0; //關閉串品中斷

        IT0=0;//外部中斷0使有電平觸發模式

        EX0=1;//開啟外部中斷0

        EA=0;//開啟總中斷

        /*主程序流程*/

        while(1)

        {

        if(recv_cmd(&type)==0)//發送幀錯誤或幀地址與本機地址不符,丟棄當前幀后返回

        continue;

        switch(type)

        {

        case_ACTIVE_://主機詢問從機是否存在

        send_data(_OK_,0,dbuf);//發送應答信息,這里的buf的內容并未用到

        break;

        case_GETDATA_://主機發送讀設備請求

        len=strlen(dbuf);

        snd_data(_STATUS_,len,dbuf);//發送設備信息

        break;

        default:

        break;//命令類型錯誤,丟棄當前幀返回

        }

        }

        }

        voidREADSTATUS()interrput0using1//產生外部中斷0時表示設備狀態發生改變,該函數使用寄存器組1

        {

        get_status();//獲得設備狀態信息,并將其存入dbuf指向的存儲區,數據最后一個字節置0表示數據結束

        }

        /*該函數接收一幀數據度進行檢測,無論該幀是否錯誤,函數均會返回。

        *函數參數type保存接收到的命令字

        *當接收的數扭幀錯誤或其地址位不為0時(非主機發送幀),快活數返回0,反之返回1

        */

        bitrecv_cmd(uchar*type)

        {

        bitdb=0;//當接收到的上一個字節為0xdb時,該位置位

        bitc0=0;//當接慢到的上一個字節為0xc0時,該位置位

        uchardata_buf[_ERRLEN];//保存接收到的幀

        uchartmp;

        ucharecc=0;

        uchari;

        M_DE=0;//置發送禁止,接收允許

        M_RE=0;

        /*接收一幀數據*/

        i=0;

        while(!c0)//循環直至幀接收完畢

        RI=0;

        while(RI);

        tmp=SBUF;

        RI=0;

        if(db==1)//接收到的上一個字節為0xdb

        {

        swithc(tmp)

        case0xdd:

        data_buf[i]=0xdb;//0xdbdd表示0xdb

        ecc=ecc^0xdb;

        db=0;

        break;

        case0xdc:

        data_buf[i]=0xc0;//0xdbdc表示0xc0

        ecc=0;

        db=0;

        break;

        default:

        return0;//幀錯誤,返回

        i++;

        }

        switch(tmp)//正常情況下

        {

        case0xc0://幀結束

        c0=1;

        break;

        case0xdb: //檢測到轉義字符

        db=1;

        break;

        default://普通數據

        data_buf[i]=tmp;//保存數據

        ecc=ecc^tmp;//計算校驗字節

        i++;

        }

        if(i==_ERRLEN)//幀超長,錯誤,返回

        return0;

        /*判斷幀是否錯誤*/

        if(i<4)//幀過短,錯誤,返回

        return0;

        if(ecc!=0)//校驗錯誤,返回

        return0;

        if(data_buf[i!=dev) //非訪問本機命令,錯誤,返回

        return0;

        *type=data_buf[1];//獲得命令字

        return1;//函數成功返回

        }

        /*該函數發送一數據幀,參數type為命令字,len為數據長度,buf為要發送的數據內容*/

        voidsend_data(uchartype,ucharlen,uchar*buf)

        {

        uchari;

        ucharecc=0;

        M_DE=1;//置發送允許,接收禁止

        M_RE=1;

        send_byte(dev);//發送本機地址

        ecc=dev;

        send_byte(type);//發送命令字

        ecc=ecc^type;

        send_byte(len);//發送長度

        ecc=ecc^len;

        for(i=0;i

        {

        send_byte(*buf);

        ecc=ecc^(*buf);

        buff++;

        }

        send_byte(ecc);//發送校驗字節

        TI=0;//發送幀結束標志

        SBUF=0xc0;

        while(!TI);

        TI=0;

        }

        /*該函數發送一個數據字節,若該字節為0xdb,則發送0xdbdd,若該字節為0xc0,則發送0xdbdc*/

        voidsend_byte(ucharda)

        {

        switch(da)

        {

        case0xdb://字節為0xdb,發送0xdbdd

        TI=0;

        SBUF=0xdb;

        while(!TI);

        TI=0;

        SBUF=0xdd;

        while(!TI);

        TI=0;

        break;

        case0xc0://字節為0xc0,則發送0xdbdc

        TI=0;

        SBUF=0xdb;

        while(!TI);

        TI=0;

        SBUF=0xdc;

        while(!TI);

        TI=0;

        break;

        default://普通數據剛直接發送

        TI=0;

        SBUF=da;

        while(!TI);

        TI=0;

        }

        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 延川县| 富川| 丰顺县| 奈曼旗| 青浦区| 郎溪县| 东台市| 永昌县| 常山县| 衡南县| 高陵县| 柞水县| 喀喇| 赫章县| 鲁甸县| 贞丰县| 揭东县| 慈溪市| 柳河县| 宁夏| 罗江县| 柳州市| 阜宁县| 临泽县| 滁州市| 山阳县| 禹城市| 赞皇县| 威远县| 牙克石市| 塔城市| 平远县| 吉木乃县| 龙游县| 神农架林区| 濮阳市| 武鸣县| 沅陵县| 玉溪市| 康定县| 大姚县|