新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 485通信程序(51單片機(jī))

485通信程序(51單片機(jī))

作者: 時(shí)間:2016-11-11 來源:網(wǎng)絡(luò) 收藏
#include

#include

本文引用地址:http://butianyuan.cn/article/201611/317037.htm

#defineucharunsignedchar

#defineuintunsignedint

/*通信命令*/

#define_ACTIVE_0x01//主機(jī)詢問從機(jī)是否存在

#define_GETDATA_0x02//主機(jī)發(fā)送讀設(shè)備請求

#define_OK_0x03//從機(jī)應(yīng)答

#define_STATUS_0x04//從機(jī)發(fā)送設(shè)備狀態(tài)信息

#define_MAXSIZE0x08//緩沖區(qū)長度

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

uchardbuf[MAXSIZE]; //該緩沖區(qū)用于保存設(shè)備狀態(tài)信息

uchardev;//該字節(jié)用于保存本機(jī)設(shè)備號

sbitM_DE=P1^0;//驅(qū)動(dòng)器使能,1有效

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

voidget_status();//調(diào)用該函數(shù)獲得設(shè)備狀態(tài)信息,函數(shù)全碼未給出

voidsend_data(uchartype,ucharlen,uchar*buf);//發(fā)送數(shù)據(jù)幀

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

voidsend_byte(ucharda);//該函數(shù)發(fā)送一幀數(shù)據(jù)中的一個(gè)字節(jié),由send_data()函數(shù)調(diào)用

voidmain()

{

uchartype;

ucharlen;

/*系統(tǒng)初始化*/

P1=0xff;//讀取本機(jī)設(shè)備號

dev=(P1>>2);

TMOD=0x20;//定時(shí)器T1使用方式2

TH1=250;

TL1=250;

TR1=1;//開始計(jì)時(shí)

PCON=0x80;//SMOD=1;

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

ES=0; //關(guān)閉串品中斷

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

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

EA=0;//開啟總中斷

/*主程序流程*/

while(1)

{

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_://主機(jī)發(fā)送讀設(shè)備請求

len=strlen(dbuf);

snd_data(_STATUS_,len,dbuf);//發(fā)送設(shè)備信息

break;

default:

break;//命令類型錯(cuò)誤,丟棄當(dāng)前幀返回

}

}

}

voidREADSTATUS()interrput0using1//產(chǎn)生外部中斷0時(shí)表示設(shè)備狀態(tài)發(fā)生改變,該函數(shù)使用寄存器組1

{

get_status();//獲得設(shè)備狀態(tài)信息,并將其存入dbuf指向的存儲區(qū),數(shù)據(jù)最后一個(gè)字節(jié)置0表示數(shù)據(jù)結(jié)束

}

/*該函數(shù)接收一幀數(shù)據(jù)度進(jìn)行檢測,無論該幀是否錯(cuò)誤,函數(shù)均會(huì)返回。

*函數(shù)參數(shù)type保存接收到的命令字

*當(dāng)接收的數(shù)扭幀錯(cuò)誤或其地址位不為0時(shí)(非主機(jī)發(fā)送幀),快活數(shù)返回0,反之返回1

*/

bitrecv_cmd(uchar*type)

{

bitdb=0;//當(dāng)接收到的上一個(gè)字節(jié)為0xdb時(shí),該位置位

bitc0=0;//當(dāng)接慢到的上一個(gè)字節(jié)為0xc0時(shí),該位置位

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

uchartmp;

ucharecc=0;

uchari;

M_DE=0;//置發(fā)送禁止,接收允許

M_RE=0;

/*接收一幀數(shù)據(jù)*/

i=0;

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

RI=0;

while(RI);

tmp=SBUF;

RI=0;

if(db==1)//接收到的上一個(gè)字節(jié)為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;//幀錯(cuò)誤,返回

i++;

}

switch(tmp)//正常情況下

{

case0xc0://幀結(jié)束

c0=1;

break;

case0xdb: //檢測到轉(zhuǎn)義字符

db=1;

break;

default://普通數(shù)據(jù)

data_buf[i]=tmp;//保存數(shù)據(jù)

ecc=ecc^tmp;//計(jì)算校驗(yàn)字節(jié)

i++;

}

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

return0;

/*判斷幀是否錯(cuò)誤*/

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

return0;

if(ecc!=0)//校驗(yàn)錯(cuò)誤,返回

return0;

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

return0;

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

return1;//函數(shù)成功返回

}

/*該函數(shù)發(fā)送一數(shù)據(jù)幀,參數(shù)type為命令字,len為數(shù)據(jù)長度,buf為要發(fā)送的數(shù)據(jù)內(nèi)容*/

voidsend_data(uchartype,ucharlen,uchar*buf)

{

uchari;

ucharecc=0;

M_DE=1;//置發(fā)送允許,接收禁止

M_RE=1;

send_byte(dev);//發(fā)送本機(jī)地址

ecc=dev;

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

ecc=ecc^type;

send_byte(len);//發(fā)送長度

ecc=ecc^len;

for(i=0;i

{

send_byte(*buf);

ecc=ecc^(*buf);

buff++;

}

send_byte(ecc);//發(fā)送校驗(yàn)字節(jié)

TI=0;//發(fā)送幀結(jié)束標(biāo)志

SBUF=0xc0;

while(!TI);

TI=0;

}

/*該函數(shù)發(fā)送一個(gè)數(shù)據(jù)字節(jié),若該字節(jié)為0xdb,則發(fā)送0xdbdd,若該字節(jié)為0xc0,則發(fā)送0xdbdc*/

voidsend_byte(ucharda)

{

switch(da)

{

case0xdb://字節(jié)為0xdb,發(fā)送0xdbdd

TI=0;

SBUF=0xdb;

while(!TI);

TI=0;

SBUF=0xdd;

while(!TI);

TI=0;

break;

case0xc0://字節(jié)為0xc0,則發(fā)送0xdbdc

TI=0;

SBUF=0xdb;

while(!TI);

TI=0;

SBUF=0xdc;

while(!TI);

TI=0;

break;

default://普通數(shù)據(jù)剛直接發(fā)送

TI=0;

SBUF=da;

while(!TI);

TI=0;

}

}



關(guān)鍵詞: 485通信程序51單片

評論


技術(shù)專區(qū)

關(guān)閉