RS-485總線接口是一種常用的串口,具有網絡連接方便、抗干擾性能好、傳輸距離遠等優點。RS-485收發器采用平衡發送和差分接收,因此具有抑制共模干擾的能力,加上收發器具有高的靈敏度,能檢測到低達200mv的電壓,可靠通信的傳輸距離可達數千米。使用RS-485總線組網,只需一對雙絞線就可實現多系統聯網構成分布式系統、設備簡單、價格低廉、通信距離長。
51單片機的485通信程序
#ifndef __485_C__ #define __485_C__
#include 《reg51.h》
#include 《string.h》
#define unsigned char uchar
#define unsigned int uint
/* 通信命令 */
#define __ACTIVE_ 0x01 // 主機詢問從機是否存在
#define __GETDATA_ 0x02 // 主機發送讀設備請求
#define __OK_ 0x03 // 從機應答
#define __STATUS_ 0x04 // 從機發送設備狀態信息
#define __MAXSIZE 0x08 // 緩沖區長度
#define __ERRLEN 12 // 任何通信幀長度超過12則表示出錯
uchar dbuf[__MAXSIZE]; // 該緩沖區用于保存設備狀態信息
uchar dev; // 該字節用于保存本機設備號
sbit M_DE = P1^0; // 驅動器使能,1有效
sbit M_RE = P1^1; // 接收器使能,0有效
void get_status(); // 調用該函數獲得設備狀態信息,函數代碼未給出
void send_data(uchar type, uchar len, uchar *buf); // 發送數據幀
bit recv_cmd(uchar *type); // 接收主機命令,主機請求僅包含命令信息
void send_byte(uchar da); // 該函數發送一幀數據中的一個字節,由send_data()函數調用
void main() {
uchar type; uchar len;
/* 系統初始化 */
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; // 命令類型錯誤,丟棄當前幀后返回
}
}
}
void READSTATUS() interrupt 0 using 1 // 產生外部中斷0時表示設備狀態發生改變,該函數使用寄存器組1
{
get_status(); // 獲得設備狀態信息,并將其存入dbuf指向的存儲區,數據最后一字節置0表示數據結束
}
/* 該函數接收一幀數據并進行檢測,無論該幀是否錯誤,函數均會返回 * 函數參數type保存接收到的命令字
* 當接收到數據幀錯誤或其地址位不為0時(非主機發送幀),函數返回0,反之返回1 */
bit recv_cmd(uchar *type) {
bit db = 0; // 當接收到的上一個字節為0xdb時,該位置位
bit c0 = 0; // 當接收到的上一個字節為0xc0時,該位置位
uchar data_buf[__ERRLEN]; // 保存接收到的幀
評論
查看更多