ModbusRTU和ModbusTCP协议模板C语言Word文档格式.docx
《ModbusRTU和ModbusTCP协议模板C语言Word文档格式.docx》由会员分享,可在线阅读,更多相关《ModbusRTU和ModbusTCP协议模板C语言Word文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
6个字节部分称为“MBAP报文头”
示例:
005100000009
0051是客户端发出的校验信息,服务端原内容返回即可
0000表示modbus-tcp协议
0009表示后面还有9个字节
后面部分:
011000010001020000
01设备地址
10表示10指令
0001起始地址
0001写寄存器数量
02字节计数
0000数据
响应指令:
005100000006011000010001
System.h:
#ifndef_SYSTEM_H_
#define_SYSTEM_H_
#include"
stm32f10x.h"
//=======================不常改动项==========================================
/******stm32f10x.h第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
CRC_Check.h
#ifndef_CRC_CHECK_H_
#define_CRC_CHECK_H_
system.h"
u16CRC16_Verify(u8*puchMsg,u16usDataLen);
CRC_Check.c
CRC_Check.h"
/*
*高位表
*/
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,
0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
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,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
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,
};
/*******************************************
*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);
}
Modbus_RTU.h
#ifndef_MODBUS_RTU_H_
#define_MODBUS_RTU_H_
/*-----------------------------------------------------
*是否启用“记录写入功能”
*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));
Modbus_RTU.c
Modbus_RTU.h"
#defineModbus_Addr1//modbus地址。
可以定义为在其他地方定义的地址,例如save.localAddr。
//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寄存器的写入操作。
需要将数据存储到其他地方时,需要开启“写入记录功能”。
/*--------------------------------------------------
*读modbus寄存器(16位)写入状态
*start:
起始地址
*length:
寄存器个数
*返回:
0个寄存器有写入操作,返回0
*至少有1个寄存器有写入操作,返回1
--------------------------------------------------*/
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;
*写modbus寄存器(16位)写入状态
起始地址
*sta:
写入状态,0=无写入操作,1=有写入操作。
voidModbus_Write_WRecord(u16start,u16length,u8sta)
if(length==0)return;
=MODBUS_BUFFER_LEN/2)return;
if(sta){
Modbus_WRecord[i/8]|=(u8)1<
(i%8);
}else{
Modbus_WRecord[i/8]&
=~((u8)1<
(i%8));
*读modbus缓存(8位)
*buffer:
将读取的数据存入buffer数组
*addr:
读取长度
0=读取失败,1=读取成功。
u8Modbus_Read_Buffer(u8*buffer,u16addr,u16length)
u8*p_data;
if(addr+length>
MODBUS_BUFFER_LEN)return0;
p_data=Modbus_Buffer+addr;
for(i=0;
length;
{buffer[i]=p_data[i];
return1;
*写modbus缓存(8位)
将buffer数组的数据写入Modbus_Buffer。
写入长度
0=写入失败,1=写入成功。
u8Modbus_Write_Buffer(u8*buffer,u16addr,u16length)
u8*p_save;
p_save=Modbus_Buffer+addr;
{p_save[i]=buffer[i];
*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;
res.int32=num;
temp=res.arr[0];
res.arr[0]=res.arr[3];
res.arr[3]=temp;
temp=res.arr[1];