//modbus协议--51端程序的实现
//RTU需要一个定时器来判断3.5个流逝时间。
#define ENABLE 1
#define DISABLE 0
#define TRUE 1
#define FAULT 0
#define RECEIVE_EN 0
#define TRANSFER_EN 1
#define MAX_RXBUF 0x20
extern unsigned char emissivity;
extern unsigned char tx_count,txbuf[15];
extern unsigned char rx_count,rxbuf[15];
extern unsigned char tx_number,rx_number;
extern bit MODBUS_T35,rx_ok;
unsigned char rx_temp;
void InitTimer1() //针对标准8051
{
TMOD=(TMOD|0xf0)&0x1f; //将T1设为16位定时器
TF1=0;
TH1=0x62; //设T1位3.5位的接收时间35bit/9600bit/s=3.646ms
TL1=0x80;//晶振为11.0592MHz,T=65535-3.646ms*11.0592MHz/12=0x6280
ET1=1; //允许T1中断
TR1=1; //T1开始计数
}
void timer1() interrupt 3 using 2 //定时器中断
{
TH1=0x62; //3.646ms interrupt
TL1=0x80;
MODBUS_T35=ENABLE;
if(rx_count>=5) //超时后,若接收缓冲区有数则判断为收到一帧
{
rx_ok=TRUE;
}
}
void scomm() interrupt 4 using 3 //modbus RTU模式
{
if(TI)
{
TI = 0;
if(tx_count < tx_number) //是否发送结束
{
SBUF = txbuf[tx_count];
}
tx_count++;
}
if(RI)
{
rx_temp=SBUF;
if(rx_ok==FAULT) //已接收到一帧数据,在未处理之前收到的数舍弃
{
if(rx_count
rxbuf[rx_count]=rx_temp;
rx_count++;
}
TH1=0x62; //timer1 reset,count again
TL1=0x80;
RI=0;
}
}
//在主循环中判断标志rx_ok来执行帧处理。
if(rx_ok)
{
ParseFrame();
KB0=1;
REN=0;
tx_count=0;
TI=1; //启动发送响应帧
rx_count=0;
rx_ok=0;
}
WORD MAKEWORD(a, b)
{
int_byte itemp;
itemp.items.high=a;
itemp.items.low=b;
return (itemp.item);
}
// 解析帧并发送响应帧 (在帧完整的前提下调用)
bit ParseFrame()
{
unsigned char byAddr ; // 地址
unsigned char byFunCode ; // 功能代码
int_byte wCRC;
wCRC.item = MAKEWORD(rxbuf[rx_count-1], rxbuf[rx_count-2]);
if(wCRC.item != CRC(rxbuf, rx_count-2)) // 判断校验是否正确
return FALSE;
// 正式解析
byAddr = rxbuf[0]; // 地址
byFunCode = rxbuf[1]; // 功能代码
// 如果地址不对
if( (byAddr != m_byAddress) && (byAddr != 0) )
return FALSE;
if(byAddr == m_byAddress)
{
AddSendByte(m_byAddress) ; // 地址
switch( byFunCode )
{
case 3: // 读保持寄存器
Fun3(3);
break;
....// 添加命令散转
......
default:
ErroRespond(1);
return FALSE;
break;
}
}
wCRC.item = CRC(txbuf,tx_number);
AddSendByte(wCRC.items.low);
AddSendByte(wCRC.items.high);
return TRUE;
}
// 根据接收帧模式发送相应,模式的数据
BOOL AddSendByte(const BYTE byData)
{
txbuf[tx_number]=byData;
tx_number++;
if(tx_number>30)return FALSE;
return TRUE;
}
// 异常响应 描述 响应解释
// 01 无效功能 变送器不允许执行收到的功能
// 02 无效地址 数据栏中的地址是不允许的
// 03 无效数据 数据栏中的数据是不允许的
// 06 忙 收到的消息没错,但从机正在执行一个长的程序命令
bit ErroRespond(const unsigned char byErroCode)
{
// printf("
ErroRespond%02X
", byErroCode);
if( !AddSendByte(rxbuf[1] | 0x80) )
return FALSE;
return AddSendByte(byErroCode);
}
//***CRC Calculation for MODBUS Protocol for VC++***//
//数组snd为地址等传输字节,num为字节数//
unsigned int CRC(unsigned char *snd, unsigned char num)
{
unsigned char i, j;
unsigned int c,crc=0xFFFF;
for(i = 0; i < num; i ++)
{
c = snd & 0x00FF;
crc ^= c;
for(j = 0;j < 8; j ++)
{
if (crc & 0x0001)
{
crc>>=1;
crc^=0xA001;
}
else crc>>=1;
}
}
return(crc);
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
http://freemodbus.berlios.de/
About
FreeMODBUS is a free implementation of the popular Modbus protocol specially targeted for embedded systems. Modbus is a popular network protocol in the industrial manufacturing environment. A Modbus communication stack requires two layers. The Modbus Application Protocol which defines the data model and functions and a Network layer. In its current version FreeMODBUS provides an implementation of the Modbus Application Protocol v1.1a and supports RTU/ASCII transmission modes defined in the Modbus over serial line specification 1.0. Since version 0.7 FreeModbus also supports Modbus TCP defined in Modbus Messaging on TCP/IP Implementation Guide v1.0a. It is licensed under the BSD[1] which permits its usage in commercial environments. The following Modbus functions are currently supported:
Read Input Register (0x04)
Read Holding Registers (0x03)
Write Single Register (0x06)
Write Multiple Registers (0x10)
Read/Write Multiple Registers (0x17)
Read Coils (0x01)
Write Single Coil (0x05)
Write Multiple Coils (0x0F)
Read Discrete Inputs (0x02)
Report Slave ID (0x11)
The implementation is based upon the most recent standards and should be fully standard compliant. Receiving and transmitting of Modbus RTU/ASCII frames is implemented as a state machines which is driven by callbacks from the hardware abstraction layer. This makes porting to new platforms easy. If a frame is complete it is passed to the Modbus Application Layer where its content is inspected. Hooks are available in the Application Layer to add new Modbus functions.
If Modbus TCP is used the porting layer must send an event to the protocol stack if a new frame is ready for processing. The protocol stack then calls a function which returns the received Modbus TCP frame and processes it. If valid a response is created and the porting layer is supplied with the Modbus response. It should then send the
response back to the client.
--------------------------------------------------------------------------------
- Home
- Examples
- HW/SW requirements
--------------------------------------------------------------------------------
- Ports ASCII/RTU
- FreeRTOS/STR71X
- AVR ATMega8/16/32/128/168/169
- Freescale MCF5235
- TI MSP430
- LPC214X
- Z8 Encore!/Z8F6422
- Win32
- Linux/Cygwin
- FreeRTOS/AT91SAM7X
- Ports TCP
- Win32
- lwIP/MCF5235
- lwIP/STR71X
- Documentation
- API documentation
--------------------------------------------------------------------------------
- Downloads
--------------------------------------------------------------------------------
- Credits
- Contact
- Links
希望对大家用得着!
一周热门 更多>