新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 51單片機實現的485通訊程序

        51單片機實現的485通訊程序

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

        #defineunsignedcharuchar
        #defineunsignedintuint
        /*通信命令*/
        #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=1;//開啟中斷
        /*主程序流程*/
        while(1)//主循環
        {
        if(recv_cmd(&type)==0)//發生幀錯誤或幀地址與本機地址不符,丟棄當前幀后返回
        continue;
        switch(type)
        {
        case__ACTIVE_://主機詢問從機是否存在
        send_data(__OK_,0,dbuf);//發送應答信息,這里buf的內容并未用到
        break;
        case__GETDATA_:
        len=strlen(dbuf);
        send_data(__STATUS_,len,dbuf);//發送設備狀態信息
        break;
        default:
        break;//命令類型錯誤,丟棄當前幀后返回
        }
        }
        }
        voidREADSTATUS()interrupt0using1//產生外部中斷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
        {
        switch(tmp)
        {
        case0xdd:
        data_buf[i]=0xdb;//0xdbdd表示0xdb
        ecc=ecc^0xdb;
        db=0;
        break;
        case0xdc
        data_buf[i]=0xc0;//0xdbdc表示0xc0
        ecc=ecc^0xc0;
        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[0]!=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);
        buf++;
        }
        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;
        }
        }
        #endif


        RS-232接口實現計算機和單片機通信程序
        作者:
        佚名來源:
        本站原創點擊數:…更新時間:2008年07月10日【字體:大中小】 


        //此程序通過RS-232接口來完成計算機和單片機通信(程序已用p18f458試驗板上調試通過)
        //程序的調試可以用"串口調試助手V2.1"輔助完成,此程序可在http://www.51hei.com下載
        //此程序首先發送測試數據55H,再通過中斷實現數據的接收和發送
        #include"p18f458.h"
        voidInterruptHandlerHigh(void);
        //初始化程序
        voidinitial()
        {
        SPBRG=0X19;//選擇傳輸波特率為9600bps
        TXSTA=0X04;//選擇異步高速方式傳輸8位數據
        RCSTA=0X80;//允許同步串行口工作
        TRISC=0X80;//將RC7,RC6設置為輸入,斷絕與外接電路的連接
        TXSTAbits.TXEN=1;//發送允許
        RCSTAbits.CREN=1;//接受數據允許
        PIE1bits.RCIE=1;//接收中斷使能
        INTCON=0XC0;//總中斷和外圍中斷允許
        }
        //高優先級中斷向量
        #pragmacodeInterruptVectorHigh=0x08
        voidInterruptVectorHigh(void)
        {
        _asm
        gotoInterruptHandlerHigh//跳到中斷程
        _endasm
        }
        //高優先級中斷服務程序
        #pragmacode
        #pragmainterruptInterruptHandlerHigh
        voidInterruptHandlerHigh()
        {
        while(PIR1bits.RCIF==1)//若接收中斷標志不為1,則為誤操作,返回
        {
        TXREG=RCREG;//將接收到的數據放入發送寄存器,并啟動發送
        }
        }
        //主程序
        main()
        {
        initial();//系統初始化
        TXREG=0X55;//發送數據55H進行測試
        for(;;);
        }


        ------------------------------------------匯編語言版本的RS-232接口實現計算機和單片機通信程序------------
        ;
        此程序通過RS-232接口來完成計算機和單片機通訊(程序以在p18f458試驗板上調通)
        ;
        本單片機程序由http://www.51hei.com提供
        ;
        此程序首先發送測試數據55H,再通過中斷實現數據的接收和發送
        ;
        程序的調試可以用"串口調試助手V2.1"輔助完成
        LISTP=18f458
        INCLUDE"P18f458.INC"
        ORG0x00
        GOTOMAIN
        ORG0x08
        GOTOINTSERVE
        ORG0X30
        ;
        **************中斷服務子程序***************
        INTSERVE
        BTFSSPIR1,RCIF;
        接收中斷標志為1?
        GOTOERR_RE;
        誤操作,返回
        MOVFRCREG,0;
        否則,將接收到的數據通過W寄存器
        MOVWFTXREG;
        放入發送寄存器,并啟動發送
        ERR_RENOP
        RETFIE
        ;
        ****************初始化程序***************
        INITIALNOP
        MOVLW0X19;
        選擇傳輸波特率為9600bps
        MOVWFSPBRG
        MOVLW0X04;
        選擇異步高速方式傳輸8位數據
        MOVWFTXSTA
        MOVLW0X80;
        允許同步串行口工作
        MOVWFRCSTA
        MOVLW0X80;
        將RC7,RC6設置為輸入,斷絕與外接電路的連接
        MOVWFTRISC
        BSFTXSTA,TXEN;
        發送允許
        BSFRCSTA,CREN;
        接受數據允許
        BSFPIE1,RCIE;
        接收中斷使能
        MOVLW0XC0;
        總中斷和外圍中斷允許
        MOVWFINTCON
        RETURN
        ;
        **********************主程序*********************
        MAINNOP
        CLRWDT
        CALLINITIAL
        MOVLW0X55;
        發送數據55H進行測試
        MOVWFTXREG
        LOOP
        GOTOLOOP
        END




        兩片51單片機互相通信的串行通信程序(一個發送程序,一個接收程序)
        2007-05-2708:27
        ;
        系統晶振是11.0592MHz
        ;
        51單片機發送單片機程序
        ;
        此程序用Proteus仿真通過
        ;
        此程序在硬件上測試通過
        ;
        2007-05-27
        ;
        附有簡化電路圖
        ;
        為了使初學者能看懂,程序與圖盡可能的簡單扼要
        ;
        實驗現象為,發送端的P1口的哪個鍵被接下,接收端的哪個燈對應著亮
        ;
        如果把兩個單片機的T和R通過無線模塊(如基于MCP2120芯片的模塊)來擴充,便可做成無線通信
        ORG0000H
        AJMPSTART
        ORG0040H
        START:
        MOVSP,#60H
        MOVSCON,#50H;串口方式1
        MOVTMOD,#20H;T1方式2
        MOVTL1,#0FDH;波特率9600的常數
        MOVTH1,#0FDH
        SETBTR1
        movr5,#00h
        WAIT:
        movp1,#0ffh
        mova,p1
        movr5,a
        lcalldelay;
        讀鍵盤,這里去抖動,還要加幾句話
        mova,p1
        nop
        CJNEA,5,WAIT;
        是否有鍵輸入
        MOVSBUF,a;
        串口輸出鍵盤輸入的值
        NOP
        SS:
        JBCTI,WAIT;
        是否發送完畢
        SJMPSS
        DELAY:
        ;
        延時子程序
        PUSH0;
        保存現場
        PUSH1
        MOV0,#06H
        DELAY1:
        MOV1,#0H
        DJNZ1,$
        DJNZ0,DELAY1
        POP1;
        恢復現場
        POP0
        RET
        END


        ;
        系統晶振是11.0592MHz
        ;
        51單片機接收單片機程序
        ;
        此程序用Proteus仿真通過
        ;
        此程序在硬件上測試通過
        ;
        2007-05-27
        ;
        附有簡化電路圖
        ;
        為了使初學者能看懂,程序與圖盡可能的簡單扼要
        ;
        實驗現象為,發送端的P1口的哪個鍵被接下,接收端的哪個燈對應著亮
        ;
        如果把兩個單片機的T和R通過無線模塊(如基于MCP2120芯片的模塊)來擴充,便可做成無線通信
        ORG0000H
        AJMPSTART
        ORG0040H
        START:
        MOVSCON,#50H;串口方式1
        MOVTMOD,#20H;T1方式2
        MOVTL1,#0FDH;波特率9600的常數
        MOVTH1,#0FDH
        SETBTR1
        WAIT:
        JBCRI,DIS_REC;
        是否接收到數據
        sjmpwait
        DIS_REC:
        MOVA,SBUF;
        讀串口接收到的數據
        movp1,a
        SJMPwait
        end




        51單片機串行口通信程序設計例子
        時間:2009-03-0617:13來源:
        未知作者:
        牛牛點擊:768次
        串行口方式0應用編程8051單片機串行口方式0為移位寄存器方式,外接一個串入并出的移位寄存器,就能擴展一個并行口。單片機串行口通信
        程序設計硬件連接圖例:用8051單片機串行口外接CD4094擴展8位并行輸出口,如圖所示,8位并行口的各位都接一個發光二極管
          串行口方式0應用編程8051單片機串行口方式0為移位寄存器方式,外接一個串入并出的移位寄存器,就能擴展一個并行口。

        <單片機串行口通信程序設計硬件連接圖>
        例:用8051單片機串行口外接CD4094擴展8位并行輸出口,如圖所示,8位并行口的各位都接一個發光二極管,要求發光管呈流水燈狀態。串行口方式0的數據
        傳送可采用中斷方式,也可采用查詢方式,無論哪種方式,都要借助于TI或RI標志。串行發送時,能靠TI置位(發完一幀數據后)引起中斷申請,在中斷服務程序中發送
        下一幀數據,或者通過查詢TI的狀態,只要TI為0就繼續查詢,TI為1就結束查詢,發送下一幀數據。在串行接收時,則由RI引起中斷或對RI查詢來確定何時接收下一幀數據。
        無論采用什么方式,在開始通信之前,都要先對控制寄存器SCON進行初始化。在方式0中將,將00H送SCON就能了。


        -----------------單片機串行口通信程序設計列子--------------------------
        ORG2000H
        START:
        MOVSCON,#00H;置串行口工作方式0
        MOVA,#80H;最高位燈先亮
        CLRP1.0;
        關閉并行輸出(避象傳輸過程中,各LED的"暗紅"現象)
        OUT0:
        MOVSBUF,A;
        開始串行輸出
        OUT1:
        JNBTI,OUT1;
        輸出完否
        CLRTI;
        完了,清TI標志,以備下次發送
        SETBP1.0;
        打開并行口輸出
        ACALLDELAY;
        延時一段時間
        RRA;
        循環右移
        CLRP1.0;
        關閉并行輸出
        JMPOUT0;
        循環
        說明:DELAY延時子程序能用前面我們講P1口流水燈時用的延時子程序,這里就不給出了


        關鍵詞: 51單片機485通

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 余姚市| 苍溪县| 运城市| 绩溪县| 新河县| 灵川县| 额尔古纳市| 明水县| 德昌县| 甘肃省| 连江县| 沭阳县| 寿宁县| 乐陵市| 蒙城县| 清流县| 敖汉旗| 嫩江县| 临西县| 泽普县| 贞丰县| 文登市| 罗源县| 西吉县| 赫章县| 珲春市| 农安县| 竹北市| 枣阳市| 凉山| 义乌市| 比如县| 临汾市| 南漳县| 凤庆县| 邮箱| 霍邱县| 枝江市| 广东省| 奎屯市| 娱乐|