C语言编写modbus协议.docx
《C语言编写modbus协议.docx》由会员分享,可在线阅读,更多相关《C语言编写modbus协议.docx(20页珍藏版)》请在冰豆网上搜索。
C语言编写modbus协议
C语言编写modbus协议
modbus.c
#include"main.h"
//字地址0-255(只取低8位)
//位地址0-255(只取低8位)
/*CRC高位字节值表*/
constuint8codeauchCRCHi[]={
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
};
/*CRC低位字节值表*/
constuint8codeauchCRCLo[]={
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
};
uint8testCoil;//用于测试位地址1
uint16testRegister;//用于测试字址址16
uint8localAddr=1;//单片机控制板的地址
uint8sendCount;//发送字节个数
uint8receCount;//接收到的字节个数
uint8sendPosi;//发送位置
uint16crc16(uint8*puchMsg,uint16usDataLen)
{
uint8uchCRCHi=0xFF;/*高CRC字节初始化*/
uint8uchCRCLo=0xFF;/*低CRC字节初始化*/
uint32uIndex;/*CRC循环中的索引*/
while(usDataLen--)/*传输消息缓冲区*/
{
uIndex=uchCRCHi^*puchMsg++;/*计算CRC*/
uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
uchCRCLo=auchCRCLo[uIndex];
}
return(uchCRCHi<<8|uchCRCLo);
}//uint16crc16(uint8*puchMsg,uint16usDataLen)
//开始发送
voidbeginSend(void)
//readCount=(receBuf[4]<<8)+receBuf[5];//要读的个数
readCount=receBuf[5];
byteCount=readCount*2;
for(i=0;i{
getRegisterVal(tempAddr,&tempData);
sendBuf[i+3]=tempData>>8;
sendBuf[i+4]=tempData&0xff;
}
sendBuf[0]=localAddr;
sendBuf[1]=3;
sendBuf[2]=byteCount;
byteCount+=3;
crcData=crc16(sendBuf,byteCount);
sendBuf[byteCount]=crcData>>8;
byteCount++;
sendBuf[byteCount]=crcData&0xff;
sendCount=byteCount+1;
beginSend();
}//voidreadRegisters(void)
//强制单个线圈
voidforceSingleCoil(void)
{
uint8addr;
uint8tempAddr;
uint16tempData;
uint8onOff;
uint8i;
//addr=(receBuf[2]<<8)+receBuf[3];
//tempAddr=addr&0xfff;
addr=receBuf[3];
tempAddr=addr;
//onOff=(receBuf[4]<<8)+receBuf[5];
onOff=receBuf[4];
//if(onOff==0xff00)
if(onOff==0xff)
{//设为ON
tempData=1;
}
//elseif(onOff==0x0000)
elseif(onOff==0x00)
{//设为OFF
tempData=0;
}
setCoilVal(tempAddr,tempData);
for(i=0;i{
sendBuf[i]=receBuf[i];
}
sendCount=receCount;
beginSend();
}//voidforceSingleCoil(void)
//设置多个寄存器
voidpresetMultipleRegisters(void)
{
uint8addr;
uint8tempAddr;
uint8byteCount;
uint8setCount;
uint16crcData;
uint16tempData;
uint8finsh;//为1时完成为0时出错
uint8i;
//addr=(receBuf[2]<<8)+receBuf[3];
//tempAddr=addr&0xfff;
addr=receBuf[3];
tempAddr=addr&0xff;
//setCount=(receBuf[4]<<8)+receBuf[5];
setCount=receBuf[5];
byteCount=receBuf[6];
for(i=0;i{
tempData=(receBuf[i*2+7]<<8)+receBuf[i*2+8];
setRegisterVal(tempAddr,tempData);
}
sendBuf[0]=localAddr;
sendBuf[1]=16;
sendBuf[2]=addr>>8;
sendBuf[3]=addr&0xff;
sendBuf[4]=setCount>>8;
sendBuf[5]=setCount&0xff;
crcData=crc16(sendBuf,6);
sendBuf[6]=crcData>>8;
sendBuf[7]=crcData&0xff;
sendCount=8;
beginSend();
}//voidpresetMultipleRegisters(void)
//检查uart0数据
voidcheckComm0Modbus(void)
{
uint16crcData;
uint16tempData;
if(receCount>4)
{
switch(receBuf[1])
{
case1:
//读取线圈状态(读取点16位以内)
case3:
//读取保持寄存器(一个或多个)
case5:
//强制单个线圈
case6:
//设置单个寄存器
if(receCount>=8)
{//接收完成一组数据
//应该关闭接收中断
if(receBuf[0]==localAddr&&checkoutError==0)
{
crcData=crc16(receBuf,6);
if(crcData==receBuf[7]+(receBuf[6]<<8))
{//校验正确
if(receBuf[1]==1)
{//读取线圈状态(读取点16位以内)
readCoil();
}
elseif(receBuf[1]==3)
{//读取保持寄存器(一个或多个)
readRegisters();
}
elseif(receBuf[1]==5)
{//强制单个线圈
forceSingleCoil();
}
elseif(receBuf[1]==6)
{
//presetSingleRegister();
}
}
}
receCount=0;
checkoutError=0;
}
break;
case15:
//设置多个线圈
tempData=receBuf[6];
tempData+=9;//数据个数
if(receCount>=tempData)
{
if(receBuf[0]==localAddr&&checkoutError==0)
{
crcData=crc16(receBuf,tempData-2);
if(crcData==(receBuf[tempData-2]<<8)+receBuf[tempData-1])
{
//forceMultipleCoils();
}
}
receCount=0;
checkoutError=0;
}
break;
case16:
//设置多个寄存器
tempData=(receBuf[4]<<8)+receBuf[5];
tempData=tempData*2;//数据个数
tempData+=9;
if(receCount>=tempData)
{
if(receBuf[0]==localAddr&&checkoutError==0)
{
crcData=crc16(receBuf,tempData-2);
if(crcData==(receBuf[tempData-2]<<8)+receBuf[tempData-1])
{
presetMultipleRegisters();
}
}
receCount=0;
checkoutError=0;
}
break;
default:
break;
}
}
}//voidcheckComm0(void)
//取线圈状态返回0表示成功
uint16getCoilVal(uint16addr,uint16*tempData)
{
uint16result=0;
uint16tempAddr;
tempAddr=addr&0xfff;
//只取低8位地址
switch(tempAddr&0xff)
{
case0:
break;
case1:
*tempData=testCoil;
break;
case2:
break;
case3:
break;
case4:
break;
case5:
break;
case6:
break;
case7:
break;
case8:
break;
case9:
break;
case10:
break;
case11:
break;
case12:
break;
case13:
break;
case14:
break;
case15:
break;
case16:
break;
default:
break;
}
returnresult;
}//uint16getCoilVal(uint16addr,uint16*data)
//设定线圈状态返回0表示成功
uint16setCoilVal(uint16addr,uint16tempData)
{
uint16result=0;
uint16tempAddr;
tempAddr=addr&0xfff;
switch(tempAddr&0xff)
{
case0:
break;
case1:
testCoil=tempData;
break;
case2:
break;
case3:
break;
case4:
break;
case5:
break;
case6:
break;
case7:
break;
case8:
break;
case9:
break;
case10:
break;
case11:
break;
case12:
break;
case13:
break;
case14:
break;
case15:
break;
case16:
break;
default:
break;
}
returnresult;
}//uint16setCoilVal(uint16addr,uint16data)
//取寄存器值返回0表示成功
uint16getRegisterVal(uint16addr,uint16*tempData)
{
uint16result=0;
uint16tempAddr;
tempAddr=addr&0xfff;
switch(tempAddr&0xff)
{
case0:
break;
case1:
break;
case2:
break;
case3:
break;
case4:
break;
case5:
break;
case6:
break;
case7:
break;
case8:
break;
case9:
break;
case10:
break;
case11:
break;
case12:
break;
case13:
break;
case14:
break;
case15:
break;
case16:
*tempData=testRegister;
break;
default:
break;
}
returnresult;
}//uint16getRegisterVal(uint16addr,uint16&data)
//设置寄存器值返回0表示成功
uint16setRegisterVal(uint16addr,uint16tempData)
{
uint16result=0;
uint16tempAddr;
tempAddr=addr&0xfff;
switch(tempAddr&0xff)
{
case0:
break;
case1:
break;
case2:
break;
case3:
break;
case4:
break;
case5:
break;
case6:
break;
case7:
break;
case8:
break;
case9:
break;
case10:
break;
case11:
break;
case12:
break;
case13: