ModbusRTU和ModbusTCP协议模板.docx
- 文档编号:18311431
- 上传时间:2023-08-15
- 格式:DOCX
- 页数:32
- 大小:103.98KB
ModbusRTU和ModbusTCP协议模板.docx
《ModbusRTU和ModbusTCP协议模板.docx》由会员分享,可在线阅读,更多相关《ModbusRTU和ModbusTCP协议模板.docx(32页珍藏版)》请在冰点文库上搜索。
ModbusRTU和ModbusTCP协议模板
--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--
Modbus-RTU和Modbus-TCP协议模板(C语言)(总33页)
Modbus-RTU和Modbus-TCP协议模板(C语言)
简介:
在单片机内部实现modbus协议,可以简单地将变量的值映射到modbus寄存器地址,这种方法是高效的,但是有以下缺点:
1、通常不支持一条指令操作多个变量(寄存器);2、可移植性较差。
本模板使用8位数组模拟modbus寄存器。
06,10指令均对数组进行写操作,同时记录寄存器的写入操作,在其他地方定时判断“写入标志”,将“写入标志”置位的“模拟寄存器”的值转移到相关变量,或进行其他操作。
03指令读取最新数据,要求定时将变量的值写入“模拟寄存器”。
本模板缺点是占用资源较多、效率较低,优点是完整支持了modbus的03,06,10指令。
Modbus-RTU简介:
1、Modbus读寄存器指令(0x03)
地址(1B)+功能码(1B)+起始地址(2B)+寄存器数量(2B)+CRC(2B)
返回:
地址(1B)+功能码(1B)+字节数(1B)+数据值(2*“寄存器数量”Bytes或者“字节数”)+CRC(2B)
2、Modbus写单个寄存器指令(0x06)
地址(1B)+功能码(1B)+寄存器地址(2B)+数据值(2B)+CRC(2B)
返回:
地址(1B)+功能码(1B)+寄存器地址(2B)+数据值(2B)+CRC(2B)(返回与发送的指令相同)
3、Modbus写多个寄存器指令(0x10)
地址(1B)+功能码(1B)+起始地址(2B)+写寄存器数量(2Bn)+字节计数(1Bn*2)+数据(n*2B)+CRC(2B)
返回:
地址(1B)+功能码(1B)+起始地址(2B)+写寄存器数量(2B)+CRC(2B)
Modbus-TCP简介:
在MODBUS-RTU前添加6个字节,并删除MODBUS-RTU的CRC校验。
示例指令:
005100000009011000010001020000
6个字节部分称为“MBAP报文头”
示例:
005100000009
0051是客户端发出的校验信息,服务端原内容返回即可
0000表示modbus-tcp协议
0009表示后面还有9个字节
后面部分:
011000010001020000
01设备地址
10表示10指令
0001起始地址
0001写寄存器数量
02字节计数
0000数据
响应指令:
005100000006011000010001
:
#ifndef_SYSTEM_H_
#define_SYSTEM_H_
#include""
//=======================不常改动项==========================================
/******第505、506、507行已经定义了u32,u16和u8******/
//typedefunsignedcharu8;
//typedefunsignedshortintu16;
//typedefunsignedintu32;
//typedefunsignedcharINT8U;
//typedefunsignedshortintINT16U;
//typedefunsignedintINT32U;
//typedefsignedcharint8_t;
//typedefsignedshortintint16_t;
//typedefsignedintint32_t;
//typedefsignedlonglongintint64_t
typedefunsignedlonglongintu64;
typedefunsignedcharbool_t;
#defineFALSE0
#defineTRUE!
FALSE
#defineNULL0
#endif
#ifndef_CRC_CHECK_H_
#define_CRC_CHECK_H_
#include""
u16CRC16_Verify(u8*puchMsg,u16usDataLen);
#endif
#include""
/*
*高位表
*/
staticconstu8auchCRCHi[]={
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
0x40
};
/*
*低位表
*/
staticconstu8auchCRCLo[]={
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,
0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,
0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,
0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,
0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,
0x37,0xF5,0x35,0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,
0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,
0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,
0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,
0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,
0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,
0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91,
0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,
0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,0x88,
0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,
0x40
};
/*******************************************
*16位CRC校验函数,查表法
*******************************************/
u16CRC16_Verify(u8*puchMsg,u16usDataLen)
{
u8uchCRCHi=0xFF;
u8uchCRCLo=0xFF;
u16uIndex;
while(usDataLen--)
{
uIndex=uchCRCHi^*puchMsg++;
uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
uchCRCLo=auchCRCLo[uIndex];
}
//return(((u16)(uchCRCLo)<<8)|uchCRCHi);
return(((u16)(uchCRCHi)<<8)|uchCRCLo);
}
#ifndef_MODBUS_RTU_H_
#define_MODBUS_RTU_H_
#include""
/*-----------------------------------------------------
*是否启用“记录写入功能”
*0=不记录写入操作,1=记录写入操作。
*需要将数据存储到其他地方时,需要开启“记录写入功能”。
-----------------------------------------------------*/
#defineREC_WRITE1
/*---------------------------------------
*定义MODBUS缓存大小(8位)
*寄存器数量=MODBUS_BUFFER_LEN/2
---------------------------------------*/
#defineMODBUS_BUFFER_LEN4000
#defineMODBUS_IDLE_REG0xFFFF//MODBUS空闲寄存器地址。
表示未配置,不允许操作。
externu8*Modbus_sBuf;
externu8Modbus_Buffer[MODBUS_BUFFER_LEN];
externu16Modbus_Start_Addr;
externu8Modbus_Swap_Endian;
u16Modbus_16BitsSwapEndian(u16num);
u32Modbus_32BitsSwapEndian(u32num);
u64Modbus_64BitsSwapEndian(u64num);
u8Modbus_Read_WRecord(u16start,u16length);
voidModbus_Write_WRecord(u16start,u16length,u8sta);
u8Modbus_Read_Buffer(u8*buffer,u16addr,u16length);
u8Modbus_Write_Buffer(u8*buffer,u16addr,u16length);
voidModbus_Example(void);
voidModbus_WRecod_Example(void);
voidModbus_Init(void);
u8Modbus_RTU_Handler(u8*rBuf,void(*Send_Function)(u8*string,u16x));
#endif
#include""
#include""
#defineModbus_Addr1//modbus地址。
可以定义为在其他地方定义的地址,例如。
//u8*Modbus_sBuf=Usart_sBuf;//发送缓存
u8Modbus_sBuf[128];//由外部定义时,使用上面的定义方法。
u8Modbus_Buffer[MODBUS_BUFFER_LEN];//modbus缓存(定义为8位方便传输)
u16Modbus_Start_Addr=0;//modbus起始地址
u8Modbus_Swap_Endian=1;//0=不转换字节顺序,1=允许转换字节顺序(51单片机设为0,STM32设为1)
#ifREC_WRITE
u8Modbus_WRecord[MODBUS_BUFFER_LEN/16+1];//记录modbus寄存器的写入操作。
需要将数据存储到其他地方时,需要开启“写入记录功能”。
#endif
/*--------------------------------------------------
*读modbus寄存器(16位)写入状态
*start:
起始地址
*length:
寄存器个数
*返回:
0个寄存器有写入操作,返回0
*至少有1个寄存器有写入操作,返回1
--------------------------------------------------*/
#ifREC_WRITE
u8Modbus_Read_WRecord(u16start,u16length)
{
u16i;
u16end;
if(length==0)return0;
end=start+length-1;
if(end>=MODBUS_BUFFER_LEN/2)return0;
for(i=start;i<=end;i++)
{
if(Modbus_WRecord[i/8]&(u8)1<<(i%8))return1;
}
return0;
}
#endif
/*--------------------------------------------------
*写modbus寄存器(16位)写入状态
*start:
起始地址
*length:
寄存器个数
*sta:
写入状态,0=无写入操作,1=有写入操作。
--------------------------------------------------*/
#ifREC_WRITE
voidModbus_Write_WRecord(u16start,u16length,u8sta)
{
u16i;
u16end;
if(length==0)return;
end=start+length-1;
if(end>=MODBUS_BUFFER_LEN/2)return;
if(sta){
for(i=start;i<=end;i++)
Modbus_WRecord[i/8]|=(u8)1<<(i%8);
}else{
for(i=start;i<=end;i++)
Modbus_WRecord[i/8]&=~((u8)1<<(i%8));
}
}
#endif
/*--------------------------------------------------
*读modbus缓存(8位)
*buffer:
将读取的数据存入buffer数组
*addr:
起始地址
*length:
读取长度
*返回:
0=读取失败,1=读取成功。
--------------------------------------------------*/
u8Modbus_Read_Buffer(u8*buffer,u16addr,u16length)
{
u16i;
u8*p_data;
if(length==0)return0;
if(addr+length>MODBUS_BUFFER_LEN)return0;
p_data=Modbus_Buffer+addr;
for(i=0;i {buffer[i]=p_data[i];} return1; } /*-------------------------------------------------- *写modbus缓存(8位) *buffer: 将buffer数组的数据写入Modbus_Buffer。 *addr: 起始地址 *length: 写入长度 *返回: 0=写入失败,1=写入成功。 --------------------------------------------------*/ u8Modbus_Write_Buffer(u8*buffer,u16addr,u16length) { u16i; u8*p_save; if(length==0)return0; if(addr+length>MODBUS_BUFFER_LEN)return0; p_save=Modbus_Buffer+addr; for(i=0;i {p_save[i]=buffer[i];} return1; } /*-------------------------------------------------- *16位变量存储顺序转换 --------------------------------------------------*/ u16Modbus_16BitsSwapEndian(u16num) { if(Modbus_Swap_Endian) { returnnum<<8|num>>8; }elsereturnnum; } /*-------------------------------------------------- *32位变量存储顺序转换 --------------------------------------------------*/ typedefunion { chararr[4]; int32_tint32; floatf; }MODBUS_UNION32; u32Modbus_32BitsSwapEndian(u32num) { u8temp; MODBUS_UNION32res; if(Modbus_Swap_Endian) { =num; temp=[0]; [0]=[3]; [3]=temp; temp=[1]; [1]=[2]; [2]=temp; return; }elsereturnnum; } /*-----------------------
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ModbusRTU ModbusTCP 协议 模板