欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
51單片機實現(xiàn)的485通訊程序①
[打印本頁]
作者:
daming
時間:
2014-12-30 00:52
標題:
51單片機實現(xiàn)的485通訊程序①
#include<reg51.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
/* 通信命令 */
#define __ACTIVE_ 0x01 // 主機詢問從機是否存在
#define __GETDATA_ 0x02 // 主機發(fā)送讀設備請求
#define __OK_ 0x03 // 從機應答
#define __STATUS_ 0x04 // 從機發(fā)送設備狀態(tài)信息
/****************************幀格式****************************
目的地址-本機地址-命令字-數(shù)據(jù)-校驗碼-結束標志 至少5個字節(jié)
*************************************************************/
#define MAXSIZE 0x08 // 緩沖區(qū)長度
#define ERRLEN 12 // 任何通信幀長度超過12則表示出錯
uchar send_buf[MAXSIZE]={0xc0,0xdb}; // 該緩沖區(qū)用于保存設備狀態(tài)信息
uchar rec_buf[ERRLEN]; // 保存接收到的幀
uchar dev; // 該字節(jié)用于保存本機設備號
sbit M_DE = P1^0; // 驅動器使能,1有效
sbit M_RE = P1^1; // 接收器使能,0有效
void get_status(); // 調用該函數(shù)獲得設備狀態(tài)信息,函數(shù)代碼未給出
void send_data(uchar type, uchar len, uchar *send_buf); // 發(fā)送數(shù)據(jù)幀
bit recv_cmd(uchar *type); // 接收主機命令,主機請求僅包含命令信息
void send_byte(uchar da); // 該函數(shù)發(fā)送一幀數(shù)據(jù)中的一個字節(jié),由send_data()函數(shù)調用
void main()
{
uchar type;
uchar len=2;
/* 系統(tǒng)初始化 */
dev =0xff; //設備號
TMOD = 0x20; // 定時器T1使用工作方式2
TH1 = 0xfd; // 設置初值
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ā)生幀錯誤或幀地址與本機地址不符,丟棄當前幀后返回
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_: // 主機詢問從機是否存在
send_data(__OK_, 0, send_buf); // 發(fā)送應答信息,這里buf的內容并未用到
break;
case __GETDATA_:
len = strlen(send_buf);
send_data(__STATUS_, len, send_buf); // 發(fā)送設備狀態(tài)信息
break;
default:
break; // 命令類型錯誤,丟棄當前幀后返回
}
*/
}
}
/* 該函數(shù)接收一幀數(shù)據(jù)并進行檢測,無論該幀是否錯誤,函數(shù)均會返回
* 函數(shù)參數(shù)type保存接收到的命令字
* 當接收到數(shù)據(jù)幀錯誤或其地址位不為0時(非主機發(fā)送幀),函數(shù)返回0,反之返回1
*/
bit recv_cmd(uchar *type)
{
bit db = 0; // 當接收到的上一個字節(jié)為0xdb時,該位置位
bit c0 = 0; // 當接收到的上一個字節(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: // 幀結束
c0 = 1;
break;
case 0xdb: // 檢測到轉義字符
db = 1;
break;
default: // 普通數(shù)據(jù)
rec_buf[i] = tmp; // 保存數(shù)據(jù)
// 計算校驗字節(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] ) // 校驗錯誤,返回
return 0;
if(rec_buf[0] != dev) // 非訪問本機命令,錯誤,返回
return 0;
*type = rec_buf[2]; // 獲得命令字
return 1; // 函數(shù)成功返回
}
// 該函數(shù)發(fā)送一幀數(shù)據(jù)幀,參數(shù)type為命令字、len為數(shù)據(jù)長度、buf為要發(fā)送的數(shù)據(jù)內容
void send_data(uchar type, uchar len, uchar *send_buf)
{
uchar i;
uchar sum = 0; // 該字節(jié)用于保存校驗字節(jié)
M_DE = 1; // 置發(fā)送允許,接收禁止
M_RE = 1;
send_byte(0x00); // 發(fā)送目的地址
sum+=0x00; //假設主機地址為0x00
send_byte(dev); // 發(fā)送本機地址
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ā)送校驗字節(jié)
TI = 0; // 發(fā)送幀結束標志
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;
}
}
復制代碼
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1