#include "main.h"
sbit SPEAK=P3^4;
/**********************************************************************
欢迎指正,多多交流,只有不断交流才会不断进步,
本协议内容是根据网络资源修改,网上的MODbus协议大多不能使用,本协议修改后可以完成01 03 05 06
功能码。10功能码大家完成吧,
本程序已经调试好,直接下载就可以使用,
-----------------------------------------------------------------------
modbus RTU 的C51程序
-----------------------------------------------------------------------
单片机AT89C51 11.0592MHZ
-----------------------------------------------------------------------
通信波特率 9600 8位数据 1位停止位 偶校验 485通位接口
-----------------------------------------------------------------------
单片机控制板地址 localAddr(变量)
通信可设置数据的地址:
字地址 0 - 255 (只取16位的低8位)
**********************************************************************/
uint16 idata D[64] _at_ 0x40; //10进制地址是64,
/**********************************************************************
D0 的10进制地址是 64
D1 的10进制地址是 65
该ModBUS支持的功能
01 读线圈 可以读取单个或多个线圈,
上位机发送数据格式 地址,功能码,线圈地址高位,线圈地址低位,读取线圈个数高位,读取线圈个数低位,CRC低位,CRC 高位,
下位机回应数据格式,地址 功能码,数据个数, 数据,CRC低位,CRC 高位,
03 读寄存器,可以读取单个或者多个寄存器
上位机发送数据格式 地址,功能码,寄存器地址高位,寄存器地址低位,数据个数高位,数据个数低位,CRC低位,CRC 高位,
下位机回应数据格式,地址 功能码,数据个数,数据1高位 数据1低位 数据2高位 数据2低位 。。。。,CRC低位,CRC 高位,
05 写单个线圈
上位机发送数据格式 地址,功能码,线圈地址高位,线圈地址低位,数据高位,数据低位,CRC低位,CRC 高位,
下位机回应数据格式,地址,功能码,线圈地址高位,线圈地址低位,数据高位,数据低位,CRC低位,CRC 高位,
06 写单个寄存器
上位机发送数据格式 地址,功能码,数据地址高位,数据地址低位,数据高位,数据低位,CRC低位,CRC 高位,
下位机回应数据格式 地址,功能码,数据地址高位,数据地址低位,数据高位,数据低位,CRC低位,CRC 高位,
0x10 写多个寄存器
上位机发送数据格式 地址,功能码,线圈地址高位,线圈地址低位,读取线圈个数高位,读取线圈个数低位,CRC低位,CRC 高位,
下位机回应数据格式,地址 功能码,数据个数, 数据,CRC低位,CRC 高位,
**********************************************************************/
uint8 xdata sendBuf[24],receBuf[24]; //发送接收缓冲区
uint8 idata checkoutError; // ==2 偶校验错
uint8 idata receTimeOut; //接收超时
bit idata bt1ms;//100ms,bt100ms; //定时标志位
uint8 xdata M[100] _at_ 0x00;
//-------------------------------定时器0 1ms 中断 -------------------------
void timer0_IntProc() interrupt 1
{
TL0 = TIMER_LOW;
TH0 = TIMER_HIGHT;
bt1ms = 1;
}
//--------------------------------串行中断程序---------------------------
void comm_IntProc() interrupt 4
{
if(TI)
{
TI = 0;
if(sendPosi < sendCount)
{
sendPosi++;
ACC = sendBuf[sendPosi];
TB8 = P; //加上校验位
SBUF = sendBuf[sendPosi];
}
else
{
//发送完后将485置于接收状态
b485Send = 1;
receCount = 0; //清接收地址偏移寄存器
checkoutError = 0;
}
}
else if(RI)
{
RI = 0;
receTimeOut = 10; //通讯超时值 这个地方很重要
//receTimeOut = 50; //通讯超时值
receBuf[receCount] = SBUF;
ACC = receBuf[receCount];
if(P != RB8)
checkoutError = 2; //偶校验出错
receCount++; //接收地址偏移寄存器加1
receCount &= 0x0f; //最多一次只能接收16个字节
}
}
//------------------------------------定时处理--------------------------------
void timeProc(void)
{
if(bt1ms)
{
bt1ms = 0;
if(receTimeOut>0)
{
receTimeOut--;
if(receTimeOut==0 && receCount>0) //判断通讯接收是否超时
{
//将485置为接收状态
b485Send = 1;
receCount = 0;// //将接收地址偏移寄存器清零
checkoutError = 0;
}
}
}
}
//------------------------------串口初始化------------------------------------
void initUart(void)
{
//偶校验
SCON=0xD0;
PCON=0X80;
ES = 1;
}
//-----------------------------初始化中断------------------------------------
void initInt(void)
{
TMOD= 0x21; //T0用于定时,T1用于波特
TH0 = TIMER_HIGHT;
TL0 = TIMER_LOW;
TR0 = 1;
ET0 = 1; //开中断T0
TH1 = 0xfa; //晶振为11.0592波特率为9600,SMOD=1,12T,TH1=F6
TR1 = 1;
TI = 1; //发送允许中断,
EA=1;
}
//--------------------------初始化-----------------------------
void initProg(void)
{
initInt(); initUart(); b485Send = 1;
}
//----------------------MAIN_PROG---------------------------------------------
void main(void)
{
initProg(); //初始化
M[0]=0x11;
M[1]=0x22;
M[2]=0x33;
M[3]=0x44;
M[4]=0x55;
M[5]=0x66;
M[6]=0x77;
M[7]=0x88;
M[8]=0x99;
D[0]=0X1122;
D[1]=0x3344;
D[2]=0x5566;
D[3]=0x7788;
D[4]=0X99aa;
while(1)
{
timeProc();///////////////////////////通讯
checkComm0Modbus();///////////////////通讯
/**********************************控制程序*********************************************/
/*测试程序说明 上位机发送 01 06 00 40 56 78 或者01 05 00 00 00 00 蜂鸣器都应该响*/
if(M[0]==0X00|D[0]==0X5678)
{
SPEAK=0;
}
else
SPEAK=1;
/*上位机发送数据说明
读取一个线圈
主机器发送 地址,功能码,寄存器高位,寄存器低位,数据个数高位, 数据个数低位,CRC低位,CRC高位
数组位置 0 1 2 3 4 5 6 7
例如读取MO 发送, 01 01 00 00 00 01
主机器返回 地址,功能码, , 数据个数, 数据1低位 CRC低位,CRC高位
数组位置 0 1 2 3
例如读取MO 返回, 01 01 01 11
读取一个寄存D0 D0 的地址为3F ,D1地址为41 D2地址为43 D3地址为45 D4 地址为47
主机器发送 地址,功能码,寄存器高位,寄存器低位,数据
评论0