|
- #include<reg51.h>
- #include<string.h>
- #define uchar unsigned char
- #define uint unsigned int
-
- /* 通信命令 */
- #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)信息
- /****************************幀格式****************************
- 目的地址-本機(jī)地址-命令字-數(shù)據(jù)-校驗(yàn)碼-結(jié)束標(biāo)志 至少5個字節(jié)
- *************************************************************/
- #define MAXSIZE 0x08 // 緩沖區(qū)長度
- #define ERRLEN 12 // 任何通信幀長度超過12則表示出錯
- uchar send_buf[MAXSIZE]={0xc0,0xdb}; // 該緩沖區(qū)用于保存設(shè)備狀態(tài)信息
- uchar rec_buf[ERRLEN]; // 保存接收到的幀
- uchar dev; // 該字節(jié)用于保存本機(jī)設(shè)備號
- sbit M_DE = P1^0; // 驅(qū)動器使能,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 *send_buf); // 發(fā)送數(shù)據(jù)幀
- bit recv_cmd(uchar *type); // 接收主機(jī)命令,主機(jī)請求僅包含命令信息
- void send_byte(uchar da); // 該函數(shù)發(fā)送一幀數(shù)據(jù)中的一個字節(jié),由send_data()函數(shù)調(diào)用
-
- void main()
- {
- uchar type;
- uchar len=2;
-
- /* 系統(tǒng)初始化 */
- dev =0xff; //設(shè)備號
- TMOD = 0x20; // 定時器T1使用工作方式2
- TH1 = 0xfd; // 設(shè)置初值
- TL1 = 0xfd;
- TR1 = 1; // 開始計時
- PCON = 0x00; // bps不倍增
- SCON = 0x50; // 工作方式1,波特率9600bps,允許接收
- ES = 1; // 開串口中斷
- IT0 = 0; // 外部中斷0使用電平觸發(fā)模式
- EX0 = 1; // 開啟外部中斷0
- EA = 1; // 開啟中斷
- /* 主程序流程 */
- while(1) // 主循環(huán)
- {
-
- if(recv_cmd(&type) == 0) // 發(fā)生幀錯誤或幀地址與本機(jī)地址不符,丟棄當(dāng)前幀后返回
- continue;
- SBUF = rec_buf[0];
- while(!TI);
- TI = 0;
- SBUF = rec_buf[1];
- while(!TI);
- TI = 0;
- SBUF = rec_buf[2];
- while(!TI);
- TI = 0;
- SBUF = rec_buf[3];
- while(!TI);
- TI = 0;
- SBUF = rec_buf[4];
- while(!TI);
- TI = 0;
- /*
- switch(type)
- {
- case __ACTIVE_: // 主機(jī)詢問從機(jī)是否存在
- send_data(__OK_, 0, send_buf); // 發(fā)送應(yīng)答信息,這里buf的內(nèi)容并未用到
- break;
- case __GETDATA_:
- len = strlen(send_buf);
- send_data(__STATUS_, len, send_buf); // 發(fā)送設(shè)備狀態(tài)信息
- break;
- default:
- break; // 命令類型錯誤,丟棄當(dāng)前幀后返回
- }
- */
- }
- }
- /* 該函數(shù)接收一幀數(shù)據(jù)并進(jìn)行檢測,無論該幀是否錯誤,函數(shù)均會返回
- * 函數(shù)參數(shù)type保存接收到的命令字
- * 當(dāng)接收到數(shù)據(jù)幀錯誤或其地址位不為0時(非主機(jī)發(fā)送幀),函數(shù)返回0,反之返回1
- */
- bit recv_cmd(uchar *type)
- {
- bit db = 0; // 當(dāng)接收到的上一個字節(jié)為0xdb時,該位置位
- bit c0 = 0; // 當(dāng)接收到的上一個字節(jié)為0xc0時,該位置位
-
- uchar tmp;
- uchar sum = 0;
- uchar i,j;
-
- 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) // 接收到的上一個字節(jié)為0xdb
- {
- switch(tmp)
- {
- case 0xdd:
- rec_buf[i] = 0xdb; // 0xdbdd表示0xdb
-
- db = 0;
- break;
- case 0xdc:
- rec_buf[i] = 0xc0; // 0xdbdc表示0xc0
-
- db = 0;
- break;
- default :
- return 0; // 幀錯誤,返回
- }
- i++;
- }
- else{
- switch(tmp) // 正常情況
- {
- case 0xc0: // 幀結(jié)束
- c0 = 1;
-
- break;
- case 0xdb: // 檢測到轉(zhuǎn)義字符
- db = 1;
-
- break;
- default: // 普通數(shù)據(jù)
- rec_buf[i] = tmp; // 保存數(shù)據(jù)
- // 計算校驗(yàn)字節(jié)
- i++;
- }
- if(i == ERRLEN) // 幀超長,錯誤,返回
- return 0;
- }
- }
-
- /* 判斷幀是否錯誤 */
- if(i<4) // 幀過短,錯誤,返回
- return 0;
- for(j=0;j<i-1;j++)
- sum+=rec_buf[j];
- sum=sum%256;
- if(sum !=rec_buf[i-1] ) // 校驗(yàn)錯誤,返回
- return 0;
- if(rec_buf[0] != dev) // 非訪問本機(jī)命令,錯誤,返回
- return 0;
- *type = rec_buf[2]; // 獲得命令字
- return 1; // 函數(shù)成功返回
- }
-
- // 該函數(shù)發(fā)送一幀數(shù)據(jù)幀,參數(shù)type為命令字、len為數(shù)據(jù)長度、buf為要發(fā)送的數(shù)據(jù)內(nèi)容
- void send_data(uchar type, uchar len, uchar *send_buf)
- {
- uchar i;
- uchar sum = 0; // 該字節(jié)用于保存校驗(yàn)字節(jié)
-
- M_DE = 1; // 置發(fā)送允許,接收禁止
- M_RE = 1;
-
- send_byte(0x00); // 發(fā)送目的地址
- sum+=0x00; //假設(shè)主機(jī)地址為0x00
- send_byte(dev); // 發(fā)送本機(jī)地址
- sum+=dev;
- send_byte(type); // 發(fā)送命令字
- sum+=type;
- //send_byte(len); // 發(fā)送長度
-
- for(i=0; i<len; i++) // 發(fā)送數(shù)據(jù)
- {
- send_byte(*send_buf);
- sum =sum+ (*send_buf);
- send_buf++;
- }
- sum%=256;
- send_byte(sum); // 發(fā)送校驗(yàn)字節(jié)
-
- TI = 0; // 發(fā)送幀結(jié)束標(biāo)志
- SBUF = 0xc0;
- while(!TI);
- TI = 0;
- }
- //該函數(shù)發(fā)送一個數(shù)據(jù)字節(jié),若該字節(jié)為0xdb,則發(fā)送0xdbdd,若該字節(jié)為0xc0則,發(fā)送0xdbdc
- void send_byte(uchar da)
- {
- switch(da)
- {
- case 0xdb: // 字節(jié)為0xdb,發(fā)送0xdbdd
- TI = 0;
- SBUF = 0xdb;
- while(!TI);
- TI = 0;
- SBUF = 0xdd;
- while(!TI)
- TI = 0;
- break;
- case 0xc0: // 字節(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;
- }
- }
復(fù)制代碼
|
|