仪器社区

求51/pic16f877a使用modbus RTU方式通信实例

_a9_free685 2010-11-06
51/pic16f877a 使用异步串行口通过modbus RTU协议方式通信实例。我自己写了个。老是调试不出来。比如发01 05 00 10 ff 00 8d ff控制一个脚的高低电平。帮我读取一个数值(int date)比如发01 04 00 13 00 03/01 41 ce(读到单个寄存器)可以读取到int date里的数... 51/pic16f877a 使用异步串行口通过modbus RTU协议方式通信实例。我自己写了个。老是调试不出来。比如发01 05 00 10 ff 00 8d ff控制一个脚的高低电平。帮我读取一个数值(int date)比如发01 04 00 13 00 03/01 41 ce(读到单个寄存器)可以读取到int date里的数, date 是RD0每高电平一次就加1)。网上的都是只MODBUS通信部份数据处理部是没有的。谢谢! QQ:358618924
评论
全部评论
廖若星辰2
给你个程序看看: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=0;i<113;i++);
}
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|0x80;TMOD=0x20; TH1=0xfd;break;
case 9600 :PCON=PCON&0x7f; TMOD=0x20; TH1=0xfd;break;
case 4800 :PCON=PCON&0x7f; TMOD=0x20; TH1=0xfa;break;
case 2400 :PCON=PCON&0x7f; TMOD=0x20; TH1=0xf4;break;
case 1200 :PCON=PCON&0x7f; TMOD=0x20; TH1=0xe8;break;
case 600 :PCON=PCON&0x7f; TMOD=0x20; TH1=0xd0;break;
case 300 :PCON=PCON&0x7f; TMOD=0x20; TH1=0xa0;break;

case 110 :PCON=PCON&0x7f; TMOD=0x10; TH1=0xfe;TL1=0xff;break;
default: PCON=PCON&0x7f;TMOD=0x20; TH1=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=0;break;
case 0x01:error1=0;break;
case 0x05:error1=0;break;
case 0x0f:error1=0;break;
case 0x04:error1=0;break;
case 0x03:error1=0;break;
case 0x06:error1=0;break;
case 0x10:error1=0;break;
case 0x17:error1=0;break;
case 0x16:error1=0;break;
case 0x14:error1=0;break;
case 0x15:error1=0;break;
case 0x2b:error1=0;break;
default:error1=1;
}

if (dee.word>0&&dee.word<0x07d1) error3=0; else 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=0; else 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=crc;n=crc>>8&0x00ff;
if((receive[6]==m)&&(receive[7]==n))

return 1 ;
else
return 0;
}

void Uart() interrupt 4 using 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]=0x00;receive[1]=0x00;receive[2]=0x00;
receive[3]=0x00;receive[4]=0x00;receive[5]=0x00;
receive[6]=0x00;receive[7]=0x00;receive_count=0;*/
} ;
};
}

void Beginsend(uchar Me )
{

ES=0; Stor=1;
TI=0;
send[0]=receive[0];

while(error_check==1)
{
if(error1==1) {send[1]=receive[1]|0x80;send[2]=0x01;break;}
if(error3==1) {send[1]=receive[1]|0x80;send[2]=0x03;break;}
if(error2==1) {send[1]=receive[1]|0x80;send[2]=0x02;break;}

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=0;error2=0;error3=0;error4=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;
else return 0;
}
void main()
{

My_function(BAUD,ADDRESS,REGISTERADDRESS ,MYREGISTER ) ;

while(1);
}

首先你要对MODBUS熟悉,然后你要会算RTU类型的CRC校验。这个网上有算法。
函数算也行,查表也行。把计算的16字节校验补到待发送的数据后面一起发送。高位低位还要调换一下,这个你找资料看去吧。
6 0 2010-11-07 0条评论 回复
您可能感兴趣的社区主题
加载中...
发布 评论