485通訊協(xié)議程序怎么寫(51單片機(jī)的485通信程序案例)
RS-485總線接口是一種常用的串口,具有網(wǎng)絡(luò)連接方便、抗干擾性能好、傳輸距離遠(yuǎn)等優(yōu)點(diǎn)。RS-485收發(fā)器采用平衡發(fā)送和差分接收,因此具有抑制共模干擾的能力,加上收發(fā)器具有高的靈敏度,能檢測(cè)到低達(dá)200mv的電壓,可靠通信的傳輸距離可達(dá)數(shù)千米。使用RS-485總線組網(wǎng),只需一對(duì)雙絞線就可實(shí)現(xiàn)多系統(tǒng)聯(lián)網(wǎng)構(gòu)成分布式系統(tǒng)、設(shè)備簡(jiǎn)單、價(jià)格低廉、通信距離長(zhǎng)。
51單片機(jī)的485通信程序
#ifndef __485_C__ #define __485_C__
#include 《reg51.h》
#include 《string.h》
#define unsigned char uchar
#define unsigned int uint
/* 通信命令 */
#define __ACTIVE_ 0x01 // 主機(jī)詢問從機(jī)是否存在
#define __GETDATA_ 0x02 // 主機(jī)發(fā)送讀設(shè)備請(qǐng)求
#define __OK_ 0x03 // 從機(jī)應(yīng)答
#define __STATUS_ 0x04 // 從機(jī)發(fā)送設(shè)備狀態(tài)信息
#define __MAXSIZE 0x08 // 緩沖區(qū)長(zhǎng)度
#define __ERRLEN 12 // 任何通信幀長(zhǎng)度超過12則表示出錯(cuò)
uchar dbuf[__MAXSIZE]; // 該緩沖區(qū)用于保存設(shè)備狀態(tài)信息
uchar dev; // 該字節(jié)用于保存本機(jī)設(shè)備號(hào)
sbit M_DE = P1^0; // 驅(qū)動(dòng)器使能,1有效
sbit M_RE = P1^1; // 接收器使能,0有效
void get_status(); // 調(diào)用該函數(shù)獲得設(shè)備狀態(tài)信息,函數(shù)代碼未給出
void send_data(uchar type, uchar len, uchar *buf); // 發(fā)送數(shù)據(jù)幀
bit recv_cmd(uchar *type); // 接收主機(jī)命令,主機(jī)請(qǐng)求僅包含命令信息
void send_byte(uchar da); // 該函數(shù)發(fā)送一幀數(shù)據(jù)中的一個(gè)字節(jié),由send_data()函數(shù)調(diào)用
void main() {
uchar type; uchar len;
/* 系統(tǒng)初始化 */
P1 = 0xff; // 讀取本機(jī)設(shè)備號(hào)
dev = (P1》》2);
TMOD = 0x20; // 定時(shí)器T1使用工作方式2
TH1 = 250; // 設(shè)置初值
TL1 = 250;
TR1 = 1; // 開始計(jì)時(shí)
PCON = 0x80; // SMOD = 1
SCON = 0x50; // 工作方式1,波特率9600bps,允許接收
ES = 0; // 關(guān)閉串口中斷
IT0 = 0; // 外部中斷0使用電平觸發(fā)模式 EX0 = 1; // 開啟外部中斷0 EA = 1; // 開啟中斷
/* 主程序流程 */
while(1) // 主循環(huán) {
if(recv_cmd(&type) == 0) // 發(fā)生幀錯(cuò)誤或幀地址與本機(jī)地址不符,丟棄當(dāng)前幀后返回
conTInue; switch(type) {
case __ACTIVE_: // 主機(jī)詢問從機(jī)是否存在
send_data(__OK_, 0, dbuf); // 發(fā)送應(yīng)答信息,這里buf的內(nèi)容并未用到
break;
case __GETDATA_: len = strlen(dbuf);
send_data(__STATUS_, len, dbuf); // 發(fā)送設(shè)備狀態(tài)信息
break; default:
break; // 命令類型錯(cuò)誤,丟棄當(dāng)前幀后返回
}
}
}
void READSTATUS() interrupt 0 using 1 // 產(chǎn)生外部中斷0時(shí)表示設(shè)備狀態(tài)發(fā)生改變,該函數(shù)使用寄存器組1
{
get_status(); // 獲得設(shè)備狀態(tài)信息,并將其存入dbuf指向的存儲(chǔ)區(qū),數(shù)據(jù)最后一字節(jié)置0表示數(shù)據(jù)結(jié)束
}
/* 該函數(shù)接收一幀數(shù)據(jù)并進(jìn)行檢測(cè),無論該幀是否錯(cuò)誤,函數(shù)均會(huì)返回 * 函數(shù)參數(shù)type保存接收到的命令字
* 當(dāng)接收到數(shù)據(jù)幀錯(cuò)誤或其地址位不為0時(shí)(非主機(jī)發(fā)送幀),函數(shù)返回0,反之返回1 */
bit recv_cmd(uchar *type) {
bit db = 0; // 當(dāng)接收到的上一個(gè)字節(jié)為0xdb時(shí),該位置位
bit c0 = 0; // 當(dāng)接收到的上一個(gè)字節(jié)為0xc0時(shí),該位置位
uchar data_buf[__ERRLEN]; // 保存接收到的幀