欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
單片機RS485程序
[打印本頁]
作者:
飲酒作樂
時間:
2020-4-23 10:25
標題:
單片機RS485程序
#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]; //
保存接收到的幀
uchar tmp;
uchar ecc = 0;
uchar i;
M_DE = 0; //
置發送禁止,接收允許
M_RE = 0;
/*
接收一幀數據
*/
i = 0;
while(!c0) //
循環直至幀接收完畢
{
RI = 0;
while(!RI);
tmp = SBUF;
RI = 0;
if(db == 1) //
接收到的上一個字節為
0xdb
{
switch(tmp)
{
case 0xdd:
data_buf[i] = 0xdb; // 0xdbdd
表示
0xdb
ecc = ecc^0xdb;
db = 0;
break;
case 0xdc
data_buf[i] = 0xc0; // 0xdbdc
表示
0xc0
ecc = ecc^0xc0;
db = 0;
break;
default
return 0; //
幀錯誤,返回
}
i++;
}
switch(tmp) //
正常情況
{
case 0xc0: //
幀結束
c0 = 1;
break;
case 0xdb: //
檢測到轉義字符
db = 1;
break;
default: //
普通數據
data_buf[i] = tmp; //
保存數據
ecc = ecc^tmp; //
計算校驗字節
i++;
}
if(i == __ERRLEN) //
幀超長,錯誤,返回
return 0;
}
/*
判斷幀是否錯誤
*/
if(i<4) //
幀過短,錯誤,返回
return 0;
if(ecc != 0) //
校驗錯誤,返回
return 0;
if(data_buf[0] != dev) //
非訪問本機命令,錯誤,返回
return 0;
*type = data_buf[1]; //
獲得命令字
return 1; //
函數成功返回
}
/*
該函數發送一幀數據幀,參數
type
為命令字、
len
為數據長度、
buf
為要發送的數據內
容
*/
void send_data(uchar type, uchar len, uchar *buf)
{
uchar i;
uchar ecc = 0; //
該字節用于保存校驗字節
M_DE = 1; //
置發送允許,接收禁止
M_RE = 1;
send_byte(dev); //
發送本機地址
ecc = dev;
send_byte(type); //
發送命令字
ecc = ecc^type;
send_byte(len); //
發送長度
ecc = ecc^len;
for(i=0; i<len; i++) //
發送數據
{
send_byte(*buf);
ecc = ecc^(*buf);
buf++;
}
send_byte(ecc); //
發送校驗字節
TI = 0; //
發送幀結束標志
SBUF = 0xc0;
while(!TI);
TI = 0;
}
/*
該函數發送一個數據字節,若該字節為
0xdb
,則發送
0xdbdd
,若該字節為
0xc0
則,發
送
0xdbdc */
void send_byte(uchar da)
{
switch(da)
{
case 0xdb: //
字節為
0xdb
,發送
0xdbdd
TI = 0;
SBUF = 0xdb;
while(!TI);
TI = 0;
SBUF = 0xdd;
while(!TI)
TI = 0;
break;
case 0xc0: //
字節為
0xc0
,發送
0xdbdc
TI = 0;
SBUF = 0xdb;
while(!TI);
TI = 0;
SBUF = 0xdc;
while(!TI)
TI = 0;
break;
default: //
普通數據則直接發送
TI = 0;
SBUF = da;
while(!TI);
TI = 0;
}
}
#endif
復制代碼
歡迎光臨 (http://m.raoushi.com/bbs/)
Powered by Discuz! X3.1