以读取线圈状态为例说明。主站发送命令:【设备地址】【命令号01】【起始寄存器地址高8 位】【低8 位】【读取的寄存器数高8 位】【低8 位】【CRC 校验的低8位】【高8 位】。从站响应:【设备地址】【命令号01】【返回的字节个数】【数据1】【数据2】…【数据n】【CRC 校验的低8 位】【高8 位】。
(3)数据区
数据区根据功能码的不同而不同。数据区包含需要从机执行什么动作,或由从机采集的返送信息。这些信息可以是实际数值、设置点、主机发送给从机或从机发送给主机的地址等。例如,功能码告诉从机读取寄存器的值,则数据区必须包含要读取寄存器的起始地址及读取长度。对于不同的从机,地址和数据信息都不相同。
(4)错误校验码
主机或从机可用校验码判别接收信息是否出错。错误检测域包含一个16 位的值(用2 个8 位的字符来实现)。错误检测域的内容是通过对消息内容进行“循环冗余检测”得出的。CRC 域附加在消息的最后,添加时先是低字节然后是高字节,故CRC 的高位字节是发送消息的最后一个宁节。错误校验采用CRC-16 校验方法。
3 软件编程
下面是采用C5l 编写的软件,主要包括CRC 校验和终端接收及波特率设置等。由于篇幅有限,其他程序略。
//功能:串口初始化,波特率为9600bps,方式1;
void lnit_Com(void)
{
TMOD=0X20;
PCON=0X00;
SCON=-X50;
TH1=0Xfd;
TL=0Xfd;
TR1=1;
EA=1;
ES=1;
}
//CRC 校验函数
uint CRC 16(uchar*pushmsg,unsigned short usdatalen)
{
uchar uchCRCHi=0xff; //高CRC字节初始化
uchar uchCRCLO=0xff; //低CRC字节初始化
uint ulndex;
while (usDataLen--) //传输消息缓冲区
{
ulndex=uchCRCHi-*pushMsg0++;// 计算CRC
uchCRCHi=uchCRCLO^auchCRCHi【ulndex】;
uchCRCLO=uchCRCLO【ulndex】;
}
return (uchCRCHi<<8|uchCRCLo);
}
//发送函数和判断函数
void send(uchar rrbuf【】,int sendCount)
{
uchar i,crcHi,crclo,j,k=0;
uchar sendbuf【32】;
usDataLen=sendCount-2;
sendbuf【0】=ReceBuf【0】;
sendbuf【1】=ReceBuf【1】;
sendbuf【2】=sendCount-2;
for(j=3;j<sendCount-2;j++)
{
sendbuf【j】=rrbuf【k】;k++;
}
k=o;
crcData=CRC(sendbuf,usDataLen);
crcHi=crcData/256;
crcHi=crcData%256;
senddbuf【sendCount-2】=crcHi;
senddbuf【sendCount-1】=crcLo;
for(i=0;i<sendCount;i++)
{
SBUF=sendbuf【i】;
while(TI=0);TI=0;
}
}
void Read()
{
switch(startAdress)
{
case 0x002; send(&writcVUf【0】,sendcCount);break;
case 0x003; send(rbufl,sendCount );break;
default;
{
SBUF=0x00;while(TI==0 TI=0; );
}
}
}
//数据帧分析处理函数
void crc_Data()
{
crcDataHi=crcData/256;
crcDataHi=crcData/256;
if(crcDataHi==receBuf【6】&crcDataLo==recebuf【7】)
{
StartAress=ReceBuf【2】 ;
StartAress<<=8;
StartAress=StartAress|ReceBuf【3】;
if(ReceBuf【0】==0x00)
{
sendCount=5+2*(ReceBUf【4】*256+ReceBuf【5】);
Read();
}
}
else{SBUF=0x0a;while(TI==0);TI=0;}
}
//串口中断函数---实现CRC数据信息的分析处理
void cmmmIntProc()interrupt 4{
if(RI){
RI=0;ReceBuf【receCount】=SBUF;
receCount++;usDataLen=receCount-2;
switch(ReceBuf【1】)
{
case 0x01;if(receCount>=8)
{receCount=0readbit();} break;
case 0x02;if(receCount>=8)
{receCount=0readbit();} break;
case 0x03;if(receCount>=8)
{receCount=0readbit();} break;
case 0x04;if(receCount>=8)
{receCount=0readbit();} break;
case 0x05;if(receCount>=8)
{receCount=0readbit();} break;
case 0x06;if(receCount>=8)
{receCount=0;WriteVyte();}break;
default; if(receCount>=8)
{
receCount=0;SBUF=0X55;
while(TI==0);
TI=0;
}
}
}
}
4 总结
由于Modhus 协议具有开放性和透明性等特点,而51系列单片机技术成熟、开发成本低,二者的结合将继续成为各类通信系统设计的首选。本设计方法已经应用于触摸屏与单片机通信设计,并取得了较好效果。这种方法对于编制类似的通信软件有一定的借鉴作用,部分程序可以直接移植。
楼主最近还看过