
(1)了解协议
首先,您应该了解Modbus RTU协议,包括它的总线层次、报文格式、功能码及其对应的功能等等。
(2)定义层次
其次,在实现Modbus RTU程序之前,您需要做的另一个任务便是定义层次。
(3)开发层次
接着,需要开发总线层次所需的软件,以用于编写和维护Modbus RTU程序。
(4)编写程序
最后,将用您所开发的软件编写Modbus RTU程序,以实现您所需的功能,如可以在给定的从动装置中读取和写入数据。
给你个程序看看:89S52的。#include"reg51.h"
#include"modbus.h"
uchar m=0,n=0
uint crc=0
uint myaw=0
void delay(uint w)
{ uchar i
while(w--)
for(i=0i<113i++)
}
void My_function(uint My_baud,uchar My_address,uint My_registeraddess,uint My_register)
{myaddress= My_address
My_register_address=My_registeraddess
My_register_num=My_register
if(flag)
{
switch(My_baud)
{
case 19200 :PCON=PCON|0x80TMOD=0x20TH1=0xfdbreak
case 9600 :PCON=PCON&0x7fTMOD=0x20TH1=0xfdbreak
case 4800 :PCON=PCON&0x7fTMOD=0x20TH1=0xfabreak
case 2400 :PCON=PCON&0x7fTMOD=0x20TH1=0xf4break
case 1200 :PCON=PCON&0x7fTMOD=0x20TH1=0xe8break
case 600 :PCON=PCON&0x7fTMOD=0x20TH1=0xd0break
case 300 :PCON=PCON&0x7fTMOD=0x20TH1=0xa0break
case 110 :PCON=PCON&0x7fTMOD=0x10TH1=0xfeTL1=0xffbreak
default: PCON=PCON&0x7fTMOD=0x20TH1=0xfd
}
SCON=0xd0
IE=0x90
Stor=0
TR1=1
flag=0
TI=0//发送中断标志位清零
RI=0//接收中断标志位清零
}
}
void My_receive()
{
dee.byte.Hi=receive[2]
dee.byte.Lo=receive[3]
switch(receive[1])
{
case 0x02:error1=0break
case 0x01:error1=0break
case 0x05:error1=0break
case 0x0f:error1=0break
case 0x04:error1=0break
case 0x03:error1=0break
case 0x06:error1=0break
case 0x10:error1=0break
case 0x17:error1=0break
case 0x16:error1=0break
case 0x14:error1=0break
case 0x15:error1=0break
case 0x2b:error1=0break
default:error1=1
}
if (dee.word>0&&dee.word<0x07d1) error3=0else error3=1
if (dee.word==My_register_address)
{
dee.byte.Hi=receive[4]
dee.byte.Lo=receive[5]
if(dee.word==My_register_num) error2=0else error2=1
}
else error2=1
if(error1==1||error2==1||error3==1)
error_check=1
else
error_check=0
}
uint crc16(uchar *puchMsg, uint usDataLen)
{
uchar uchCRCHi = 0xFF //* 高CRC字节初始化
uchar uchCRCLo = 0xFF //* 低CRC 字节初始化
unsigned long uIndex // CRC循环中的索引
while (usDataLen--) // 传输消息缓冲区
{
uIndex = uchCRCHi ^ *puchMsg++ // 计算CRC
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]
uchCRCLo = auchCRCLo[uIndex]
}
return (uchCRCHi | uchCRCLo<<8)
}
bit check_modbus(uchar *puchMsg, uint usDataLen)
{
uchar uchCRCHi = 0xFF //* 高CRC字节初始化
uchar uchCRCLo = 0xFF //* 低CRC 字节初始化
crc=crc16( puchMsg, usDataLen)
m=crcn=crc>>8&0x00ff
if((receive[6]==m)&&(receive[7]==n))
return1
else
return 0
}
void Uart() interrupt 4using 1
{
if(RI)
{
receive[receive_count]=SBUF
RI=0
receive_count++}
if(8==receive_count)
{
jieshou=1
receive_count=0
if(check_modbus(receive,6)==1&&myaddress==receive[0])
{
My_receive()
if(error_check==1)
Beginsend(3)
}
else {
/*receive[0]=0x00receive[1]=0x00receive[2]=0x00
receive[3]=0x00receive[4]=0x00receive[5]=0x00
receive[6]=0x00receive[7]=0x00receive_count=0*/
}
}
}
void Beginsend(uchar Me )
{
ES=0Stor=1
TI=0
send[0]=receive[0]
while(error_check==1)
{
if(error1==1) {send[1]=receive[1]|0x80send[2]=0x01break}
if(error3==1) {send[1]=receive[1]|0x80send[2]=0x03break}
if(error2==1) {send[1]=receive[1]|0x80send[2]=0x02break}
break
}
myaw=crc16(send,Me)
send[3] =myaw&0x00ff
send[4] =myaw>>8&0x00ff
/*if(jiaoyan(send[0])==0)
TB8=1
else
TB8=0
delay(2)*/
SBUF=send[0]
/*
while(TI==0)
TI=0
delay(20)
if(jiaoyan(send[1])==0)
TB8=1
else
TB8=0
delay(2)*/
SBUF=send[1]
while(TI==0)
TI=0/*
if(jiaoyan(send[2])==0)
TB8=1
else
TB8=0
delay(2)*/
SBUF=send[2]
while(TI==0)
TI=0
delay(20)/*
if(jiaoyan(send[3])==0)
TB8=1
else
TB8=0
delay(2)*/
SBUF=send[3]
while(TI==0)
TI=0
delay(20)/*
if(jiaoyan(send[4])==0)
TB8=1
else
TB8=0
delay(20)*/
SBUF=send[4]
while(TI==0)
TI=0
ES=1
yifasong=1
Stor=0
error1=0error2=0error3=0error4=0
}
bit jiaoyan(uchar Me)
{ uchar w=0
if(Me&0x01==1) w++
if(Me&0x02==1) w++
if(Me&0x04==1) w++
if(Me&0x08==1) w++
if(Me&0x10==1) w++
if(Me&0x20==1) w++
if(Me&0x40==1) w++
if(Me&0x80==1) w++
if(0==w%2) return 1
elsereturn 0
}
void main()
{
My_function(BAUD,ADDRESS,REGISTERADDRESS ,MYREGISTER )
while(1)
}
首先你要对MODBUS熟悉,然后你要会算RTU类型的CRC校验。这个网上有算法。
函数算也行,查表也行。把计算的16字节校验补到待发送的数据后面一起发送。高位低位还要调换一下,这个你找资料看去吧。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)