标题:
stc11f60xe单片机modbus(RTU)从站源程序可与plc组态王通信
[打印本页]
作者:
das
时间:
2015-4-8 21:14
标题:
stc11f60xe单片机modbus(RTU)从站源程序可与plc组态王通信
晶振12M 波特率9200 可与组态王通信 组态王IO设备选择西门子S7-200 MODBUS(RTU)或支持MODBUS 协义的PLC
编译器为KEIL3
单片机型号:STC11F60XE
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define _irol_(a,b) (a<<b)|(a>>16-b)
#define BIT(A) (1<<A )
#define D0 DW0[0]
#define D1 DW0[1]
#define D2 DW0[2]
#define D3 DW0[3]
#define D4 DW0[4]
#define D5 DW0[5]
#define D6 DW0[6]
#define D7 DW0[7]
#define D8 DW0[8]
#define D9 DW0[9]
#define D10 DW0[10]
#define D11 DW0[11]
#define D12 DW0[12]
#define D13 DW0[13]
#define D14 DW0[14]
#define D15 DW0[15]
#define D16 DW0[16]
#define D17 DW0[17]
#define D18 DW0[18]
#define D19 DW0[19]
#define D20 DW0[20]
#define D21 DW0[21]
#define D22 DW0[22]
#define D23 DW0[23]
#define D24 DW0[24]
#define D25 DW0[25]
#define D26 DW0[26]
#define D27 DW0[27]
#define D28 DW0[28]
#define D29 DW0[29]
#define D30 DW0[30]
#define D31 DW0[31]
unsigned long bdata M00=0xAAAADCBA;
unsigned int idata DW0[32]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30} ;//_at_ 0x0000
/*sbit p10=P1^0;
sbit p11=P1^1; */
sbit p12=P1^2;
sbit p13=P1^3;
sbit p14=P1^4;
uchar ac;
uchar at;//结束接收计时;
uint b;
uchar *p;
uchar uartR[80]={2};//接收缓冲区;
bit fcbz;//启动发送标志,发送结束需清零;
bit fcz;//发送中标志位;
uchar fc;//发送数据个数;
uchar fc1;//发送数据现在数;
bit a1;//数据接收中标志位;
bit a2;//数据接收结束标志位;
bit crc1;//crc校验正确位;1有效;
sfr BRT=0X9C;
sfr AUXR1=0XA2;
sfr AUXR=0X8E;
uchar code suzhu[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};
sbit P07=P0^7;
void delay(uint a) //延时函数;
{
while(a--);
}
void time0() interrupt 1 //定时器0中断服务程序,用于提供通信接收空闲结束时钟等;
{
TH0=0XFE;
TL0=0X0C;
if(a1)
{
at++;
if(at>=100) //50毫秒无数据流,完成接收;
{a1=0;
a2=1;
at=0;
}
}
if(M00&BIT(0))
{
b++;
if(b==1000)
{
b=0;
if(M00&BIT(1))M00&=~BIT(1);
else M00|=BIT(1);
}
if(M00&BIT(1))P07=!P07;
else P07=1;
}
else P07=1;
}
void uartinit() //串口初始化;
{
SCON=0X50;
PCON = 0x80;
AUXR=0X15;
BRT=217;
EA=1;
ES=1;
}
uint crc16(unsigned char *p,A) //调用时把校验数据首地址送给指针p,校验数据个数送给A;
{
uint code pp[256]={0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040};
uchar i;
uint arc, crc;
crc=0xffff;
for (i=0;i<A;i++ )
{
arc= (p[i]^crc)&0x00ff;
crc=_irol_(crc,8);
crc= crc & 0x00ff;
crc= crc^pp[arc];
}
return(crc);
}
void modbus1(unsigned char *p,unsigned long M00) //功能码1(读线圈)处理函数;
{
unsigned int A,B;
unsigned char i,y,u;
B=p[4];
B=B<<8|p[5];//取线圈个数;
A=p[2];
A=A<<8|p[3]; //取线圈地址;
if(B>0&&B<33)
{
if(A>=0&&A+B<33)
{
fc=B/8;
for(i=0;i<fc;i++)
{
u=0;
for(y=0;y<8;y++)
{
u>>=1;
if((M00>>A)&0x01 )u|=0x80;
A++;
}
p[i+3]=u;
}
if(B%8)
{
fc+=1;
u=0;
for(y=0;y<B%8;y++)
{
if((M00>>A)&0x01 )u|=0x01<<y;
A++;
}
p[fc+2]=u;
}
p[2]=fc;
fc+=3;
}
else
{
p[1]=0x81;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x81;
p[2]=0x03;
fc=3;
}
}
void modbus2(unsigned char *p,unsigned long M00)//功能码2(读输入离散)处理函数;
{
unsigned int A,B;
unsigned char i,y,u;
B=p[4];
B=B<<8|p[5];//取IO离散个数;
A=p[2];
A=A<<8|p[3];//取IO离散地址;
if(B>0&&B<33)
{
if(A>=0&&A+B<33)
{
fc=B/8;
for(i=0;i<fc;i++)
{
u=0;
for(y=0;y<8;y++)
{
u>>=1;
if((M00>>A)&0x01 )u|=0x80;
A++;
}
p[i+3]=u;
}
if(B%8)
{
fc+=1;
u=0;
for(y=0;y<B%8;y++)
{
if((M00>>A)&0x01 )u|=0x01<<y;
A++;
}
p[fc+2]=u;
}
p[2]=fc;
fc+=3;
}
else
{
p[1]=0x82;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x82;
p[2]=0x03;
fc=3;
}
}
void modbus3(unsigned char *p,unsigned int *p0)//功能码3(读保持寄存器)处理函数;
{
unsigned int A,B;
unsigned char i;
unsigned int *p1;
p1=p+3;
B=p[4];
B=B<<8|p[5]; //取保持寄存器数量;
A=p[2];
A=A<<8|p[3];//取保持寄存器地址;
if(B>0&&B<33)
{
if(A>=0&&A+B<33)
{
for(i=0;i<B;i++)
{
p1[i]=p0[A+i];
}
p[2]=B*2;
fc=B*2+3;
}
else
{
p[1]=0x83;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x83;
p[2]=0x03;
fc=3;
}
}
void modbus4(unsigned char *p,unsigned int *p0 ) //功能码4(读输入寄存器)处理函数;
{
unsigned int A,B;
unsigned char i;
unsigned int *p1;
p1=p+3;
B=p[4];
B=B<<8|p[5]; //取输入寄存器个数;
A=p[2];
A=A<<8|p[3]; //取输入寄存器地址;
if(B>0&&B<33)
{
if(A>=0&&A+B<33)
{
for(i=0;i<B;i++)
{
p1[i]=p0[A+i];
}
p[2]=B*2;
fc=B*2+3;
}
else
{
p[1]=0x84;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x84;
p[2]=0x03;
fc=3;
}
}
void modbus5(unsigned char *p,unsigned long *p1)//功能码5(写单个线圈)处理函数;
{
unsigned int A,B,i;
B=p[4];
B=B<<8|p[5];//取线圈状态;
A=p[2];
A=A<<8|p[3];//取线圈地址;
if(B==0X0000||B==0XFF00)
{
if(A>=0&&A<32)
{
i=1;
if(B==0XFF00)
{
p1[0]|=i<<A;
}
else M00&=~(i<<A);
fc=6;
}
else
{
p[1]=0x85;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x85;
p[2]=0x03;
fc=3;
}
}
void modbus6(unsigned char *p,unsigned int *p1)//功能码6(写单个寄存器)处理函数;
{
unsigned int A,B;
B=p[4];
B=B<<8|p[5];//取寄存器值;
A=p[2];
A=A<<8|p[3];//取寄存器地址;
if(B>=0X00||B<=0XFFFF)
{
if(A>=0&&A<32)
{
p1[A]=B;
fc=6;
}
else
{
p[1]=0x86;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x86;
p[2]=0x03;
fc=3;
}
}
void modbus15(unsigned char *p,unsigned long *M00)//功能码15(写多个线圈)处理函数;
{
unsigned int A,B;
unsigned char i,y,u;
unsigned long l;
B=p[4];
B=B<<8|p[5]; //取线圈个数;
A=p[2];
A=A<<8|p[3];//取线圈地址;
if(B>0&&B<33)
{
if(A>=0&&A+B<33)
{
l=1;
fc=B/8;
for(i=0;i<fc;i++)
{
u=p[i+7];
for(y=0;y<8;y++)
{
if((u>>y)&0x01 )M00[0]|=l<<A;
else M00[0]&=~(l<<A);
A++;
}
}
if(B%8)
{
if(fc)
{
fc+=1;
u=p[fc+6];
}
else u=p[7];
for(y=0;y<B%8;y++)
{
if((u>>y)&0x01 )M00[0]|=l<<A;
else M00[0]&=~(l<<A);
A++;
}
}
fc=6;
p14=0;
}
else
{
p[1]=0x8F;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x8F;
p[2]=0x03;
fc=3;
}
}
void modbus16(unsigned char *p,unsigned int *p1)
{
unsigned int A,B;
unsigned int *p0;
p0=p+7;
B=p[4];
B=B<<8|p[5];//取寄存器数量;
A=p[2];
A=A<<8|p[3];//取寄存器地址;
if(B>0&&B<33)
{
if(A>=0&&A+B<33)
{
p1+=A;
while(B--)
{
p1[0]=p0[0];
p1++;
p0++;
}
fc=6;
}
else
{
p[1]=0x90;
p[2]=0x02;
fc=3;
fcbz=1;
}
}
else
{
p[1]=0x90;
p[2]=0x03;
fc=3;
fcbz=1;
}
}
/*void modbus23(unsigned char *p,unsigned int *p1)
{
unsigned int A,B,AW,BW;
unsigned int *p0;
// unsigned char u;
B=p[4];
B=B<<8|p[5];//取读寄存器数量;
A=p[2];
A=A<<8|p[8]; //取读寄存器地址;
BW=p[8];
BW=BW<<8|p[9];//取写寄存器数量;
AW=p[6];
AW=AW<<8|p[7]; //取写寄存器地址;
if(B>0&&B<33&&BW>0&&BW<33)
{
if(A>=0&&A+B<33&&AW>=0&&AW+BW<33)
{
unsigned char i;
p1+=AW;
p0=p+11;
do
{
p1[0]=p0[0];
p1++;
p0++;
}while(BW--);
////////////////////c=(B&0X00FF)*2;
p0=p+3;
p1=p1-AW-BW;
p1+=A;
for(i=0;i<B;i++)
{
p1[i]=p0[A+i];
}
}
else
{
p[1]=0x97;
p[2]=0x02;
fc=3;
}
}
else
{
p[1]=0x97;
p[2]=0x03;
fc=3;
}
}*/
void modata(uchar *p,ac)
{
unsigned int a,b;
p13=0;
a=p[ac];
a=(a<<8)|p[ac-1];
b=crc16(p,ac-1);
if(a!=b)goto pp;
p12=0;
fcbz=1;
switch(p[1]) //功能码判断与服务函数调用;
{
case 1: //读线圈;
modbus1(uartR, M00);
break;
case 2://读输入离散;
modbus2(uartR, M00);
break;
case 3://读保持寄存器;
modbus3(uartR,DW0);
break;
case 4://读输入寄存器;
modbus4(uartR,DW0);
break;
case 5://写单个线圈;
modbus5(uartR, &M00);
break;
case 6://写单个数据寄存器;
modbus6(uartR, DW0);
break;
case 15://写多个连续线圈;
modbus15(uartR,&M00);
break;
case 16://写多个连续寄存器;
modbus16(uartR,DW0);
break;
// case 23://读写寄存器;
// modbus23(uartR,DW0);
break;
default:
p[1]+=0x80;
p[2]=0x01;
fc=3;
}
pp:;
}
modbushy(unsigned char *p ,a)//通讯回应;
{
unsigned int b;
b=crc16(p,a);
p[a]=b;
a+=1;
p[a]=b>>8;
fc=a;
SBUF=p[0];
}
void uart() interrupt 4 //串口中断函数;
{
uchar ua;
if(RI)
{
RI=0;
ua=SBUF;
if(!a1)
{
if(ua==2)
{a1=1;
ac=0;
at=0;
uartR[0]=ua;
}
}
else
{
RI=0;
ac++;
uartR[ac]=ua;
at=0; //清零结束接收计时器;
}
}
else
{
TI=0;
if(fc--)
{
fc1++;
SBUF=uartR[fc1];
}
else fc1=0,fc=0;
}
}
void sumaguan(uint c)
{
P2|=0x0f;
P1=suzhu[c%10];
P2&=~1;
delay(300);
P2|=0x0f;
P1=suzhu[c%100/10];
P2&=~4;
delay(300);
P2|=0x0f;
P1=suzhu[c%1000/100];
//if(b1)P1&=~0x80;
P2&=~2;
delay(300);
P2|=0x0f;
P1=suzhu[c/1000];
P2&=~8;
delay(300);
}
void main()
{
TH0=0XFE;
TL0=0X0C;
TMOD=0X01;
TR0=1;
EA=1;
ET0=1;
uartinit();
while(1)
{
if(!(M00&BIT(0)))M00&=~BIT(1);
//sumaguan(D1);
if(a2)modata(uartR,ac),a2=0;
if(fcbz)modbushy(uartR ,fc),fcbz=0;
}
}
复制代码
作者:
努力的小T
时间:
2015-6-11 18:50
你好,请问有51单片机modbus协议的程序吗?
作者:
难得糊涂2018
时间:
2019-9-17 19:59
谢谢分享!
作者:
难得糊涂2018
时间:
2019-9-28 19:35
有例子吗,大神?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1