下面的程序,那位能告诉我,数据包应该怎莫写,我不太理解ASCII码表示,我从串扣发出去,去测试这个协议,多谢
//PC读MCU指令结构:(中断方式,ASCII码表示) //帧: 帧头标志|帧类型|器件地址|启始地址|长度n|效验和|帧尾标志 //值: 'n' 'y'| 'r' | 0x01 | x | x | x |0x13 0x10 //字节数: 2 | 1 | 1 | 1 | 1 | 1 | 2 //求和:
/////////////////////////////////////////////////////////////////////
//功能描述:中断方式:本程序为mcu的串口通讯提供(贞结构)函数接口,包括具体协议部分 //其他说明:只提供对AT89c51rc具体硬件的可靠访问接口 //stc试验板调试
/////////////////////////////////////////////////////////////////////
#include <reg51.h>
sbit P1_7=P1^7 ; //正在通讯
sbit P1_1=P1^1 ; //写回应帧发送完毕
sbit P1_0=P1^0 ; //写发送帧发送完毕
sbit P1_2=P1^2 ; //地址正确
//预定义 帧 #define F_ST1 0x6e //帧头标志 n
#define F_ST2 0x79 //帧头标志 y
#define F_R 0x72 //帧类型 读 r
#define F_W 0x77 //帧类型 写 w
#define F_D 0x64 //帧类型 数据帧 d
#define F_B 0x62 //帧类型 写回应帧 b
#define F_C 0x63 //帧类型 重发命令帧 c
#define F_Q 0x71 //帧类型 放弃帧 q
#define F_ADDR 0x31 //器件地址 0-9
#define F_END 0x7a //帧尾标志 z
#define F_SPACE 0x30 //空标志 0
#define F_ERR1 0x31 //错误标志1,flagerr 1
#define F_ERR2 0x32 //错误标志2 2 常数
#define S_MAXBUF 16 //接收/发送数据的最大缓存量
#define FIELD_MAXBUF 48 //最小场缓存,可以大于48字节,因为协议是以20字节为单位传输的
#define communicationing P1_7 //正在通讯(1)标志
#define ERRFRAME_MAX 5 //连续NOFRAME_CNT次帧不正确
#define ERR_NOCNTMAX_RESEND if(++errframe_cnt<=ERRFRAME_MAX)resend_frame(); else errframe_cnt=communicationing=0; //若超过 ERRFRAME_MAX 次则令通讯停止ERR_NOCNTMAX_RESEND
//public 变量 unsigned char databuf[FIELD_MAXBUF],errframe_cnt; //函数
///////////////////////////////////////////////////////////////////// //函 数 名:send() //功能描述:向串口发送一个字符 //函数说明: //调用函数: //全局变量: //输 入:ch-要发送的ASCII字符 //返 回:无 ///////////////////////////////////////////////////////////////////// void send(unsigned char ch)
{
SBUF=ch;
while(TI==0); TI=0; }
///////////////////////////////////////////////////////////////////// //函 数 名:receive() //功能描述:从串口接收一个字符 //函数说明: //调用函数: //全局变量: //输 入:无 //返 回:一个ASCII字符
///////////////////////////////////////////////////////////////////// unsigned char receive(void)
{ while(RI==0); RI=0; return SBUF; }
///////////////////////////////////////////////////////////////////// //函 数 名:CharToHex() //功能描述:把ASCII字符转换为16进制 //函数说明: //调用函数: //全局变量: //输 入:ASCII字符 //返 回:16进制 ///////////////////////////////////////////////////////////////////// unsigned char CharToHex(unsigned char bChar)
{ if((bChar>=0x30)&&(bChar<=0x39))
bChar -= 0x30;
else if((bChar>=0x41)&&(bChar<=0x46))//大写字母
bChar -= 0x37;
else if((bChar>=0x61)&&(bChar<=0x66))//小写字母
bChar -= 0x57;
else bChar = 0xff;
return bChar; }
///////////////////////////////////////////////////////////////////// //函 数 名:HexToChar() //功能描述:把16进制转换为ASCII字符 //函数说明: //调用函数: //全局变量: //输 入:16进制 //返 回:ASCII字符 ///////////////////////////////////////////////////////////////////// unsigned char HexToChar(unsigned char bHex)
{ if((bHex>=0)&&(bHex<=9))
bHex += 0x30;
else if((bHex>=10)&&(bHex<=15))//大写字母
bHex += 0x37;
else bHex = 0xff;
return bHex; }
///////////////////////////////////////////////////////////////////// //函 数 名:com_int() //功能描述:初始化串口 //函数说明:默认其他参数为[baud_rate],n,8,1 //调用函数: //全局变量: //输 入:baud_rate 波特率 //返 回:无 ///////////////////////////////////////////////////////////////////// void com_init(unsigned int baud_rate)
{ EA=1; ES=1;//ET1=1; SCON = 0x50; /* 0x52;//SCON */
TMOD = 0x20; /*0x20;// TMOD */
TCON = 0x60; /*0x60;// TCON */
PCON=PCON&0x7f;
switch(baud_rate)//波特率设置 { case 1200: TL1=0xe8;TH1=0Xe8;break;//1200
case 2400:
TL1=0xf4;TH1=0Xf4;break;//2400
case 4800:
TL1=0xfa;TH1=0Xfa;break;//4800
case 9600:
TL1=0xfd;TH1=0Xfd;break;//9600
case 19200:
PCON=PCON|0x80;TL1=0xfd;TH1=0Xfd;break;//19200
case 38400:
PCON=PCON|0x80;TL1=0xfe;TH1=0Xfe;break;//38400
default:
TL1=0xfd;TH1=0Xfd;break;//9600 } } ///////////////////////////////////////////////////////////////////// //函 数 名:resend_frame() //功能描述:发送重发帧 //函数说明:通知PC重发 //调用函数: //全局变量: //输 入:无 //返 回:无 ///////////////////////////////////////////////////////////////////// void resend_frame(void) { send(F_ST1); send(F_ST2); send(F_C); send(F_SPACE); send(F_SPACE);//发送效验和 send(F_END); }
///////////////////////////////////////////////////////////////////// //函 数 名:quit_frame() //功能描述:发送放弃帧 //函数说明:通知PC放弃通讯 //调用函数: //全局变量: //输 入:无 //返 回:无 ///////////////////////////////////////////////////////////////////// void quit_frame(void) { send(F_ST1); send(F_ST2); send(F_Q); send(F_ERR1); send(F_ERR1);//发送效验和 send(F_END); }
///////////////////////////////////////////////////////////////////// //函 数 名:com_int() //功能描述:串口中断 //函数说明: //调用函数: //全局变量: //输 入:无 //返 回:无 ///////////////////////////////////////////////////////////////////// void com_int()interrupt 4 { unsigned char i,csaddr,clen,csum,tempbuf[S_MAXBUF];
csum=0;
if(receive()==F_ST1)//是侦
{
if(receive()==F_ST2)//头判断完 { communicationing =0; //设置通讯状态为正常即启动通讯
switch(receive()) { case F_R://是读指令帧r
if(receive()==F_ADDR)//地址正确 { P1_2=!P1_2; csaddr=CharToHex(receive())<<4;
csaddr+=CharToHex (receive());
clen=CharToHex(receive())<<4;
clen+=CharToHex(receive());
csum=csaddr+clen; i=CharToHex(receive())<<4;
i+=CharToHex(receive());
if(i==csum)//效验和正确 { if(receive()==F_END)//结束标志正确开始发送数据帧 { csum=0;
send(F_ST1);
send(F_ST2);
send(F_D);
send (HexToChar((clen&0xf0)>>4));
send(HexToChar(clen&0x0f));
csum+=clen;
for (i=0;i<clen;i++) { send(HexToChar((databuf[i+csaddr]&0xf0)>>4));
send(HexToChar(databuf [i+csaddr]&0x0f)); csum+=databuf[i+csaddr]; } //if (csum>127)csum-=128; send (HexToChar((csum&0xf0)>>4));
send(HexToChar(csum&0x0f));
send(F_END);//发送数据帧完毕 P1_0=!P1_0;
} else { ERR_NOCNTMAX_RESEND break;//结束标志错误 }
}else { ERR_NOCNTMAX_RESEND break;//效验和错误 }
}//地址不正确 break;
case F_W://是PC写指令帧w
if(receive()==F_ADDR)//地址正确 { csaddr=CharToHex(receive())<<4;
csaddr+=CharToHex(receive());
clen=CharToHex(receive()) <<4;
clen+=CharToHex(receive());
csum=csaddr+clen;
for(i=0;i<clen;i++) { tempbuf[i+csaddr] =CharToHex(receive())<<4;
tempbuf[i+csaddr]+=CharToHex(receive());
csum+=tempbuf [i+csaddr];
}
i=CharToHex(receive()) <<4;
i+=CharToHex(receive());
if(csum!=i) { ERR_NOCNTMAX_RESEND break; }//效验和错误
if(F_END!=receive()) { ERR_NOCNTMAX_RESEND break; }//结束标志错误
for (i=csaddr;i<clen+csaddr;i++) databuf[i-csaddr]=tempbuf[i-csaddr];//正确则保存数据
}//从PC获得数据写完毕//开始发送写回应帧
send(F_ST1);
send(F_ST2);
send(F_B);
send (F_SPACE);
send(F_SPACE);//发送效验和
send(F_END);//写回应帧发送完毕
P1_1=!P1_1;
break;
case F_Q://检测接收放弃帧
csaddr=receive();
csum+=csaddr;//csaddr兼做放弃帧码标志
if(csaddr!=F_ERR1 && csaddr!=F_ERR2) { ERR_NOCNTMAX_RESEND break; }
if(csum!=receive()) { ERR_NOCNTMAX_RESEND break; }
if(F_END!=receive()) { ERR_NOCNTMAX_RESEND break; } communicationing=0;//出错退出通讯
break;
default:
resend_frame();//要求从发 } }//忽略 }//忽略 if(!communicationing)quit_frame();//调用放弃帧,通知PC 放弃通讯 } /////////////////////////////////////////////////////////////////
//主函数
///////////////////////////////////////////////////////////////// void main(void) {
unsigned char i;
for (i=0;i<FIELD_MAXBUF;i++)
databuf=i+0x30;
com_init(9600);
while(1)
{ /*可以处理非串口任务*/ }
}
|