1、C语言编写modbus协议 modbus.c #include "main.h" //字地址 0 - 255 (只取低8位) //位地址 0 - 255 (只取低8位) /* CRC 高位字节值表 */ const uint8 code auchCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
2、 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, 0
3、x00, 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, 0x0
4、0, 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, 0
5、xC0, 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, 0xC
6、1, 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低位字节值表*/ const uint8 code auchCRCLo[] = { 0x0
7、0, 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, 0
8、xD4, 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, 0xE
9、8, 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,
10、 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, 0
11、x91, 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, 0x8
12、5, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 } ; uint8 testCoil; //用于测试 位地址1 uint16 testRegister; //用于测试 字址址16 uint8 localAddr = 1; //单片机控制板的地址 uint8 sendCount; //发送字节个数 uint8 receCount; //接收到的字节个数 uint8 sendPosi; //发送位置 uint16 crc16(uin
13、t8 *puchMsg, uint16 usDataLen) { uint8 uchCRCHi = 0xFF ; /* 高CRC字节初始化 */ uint8 uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */ uint32 uIndex ; /* CRC循环中的索引 */ while (usDataLen--) /* 传输消息缓冲区 */ { uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; uc
14、hCRCLo = auchCRCLo[uIndex] ; } return (uchCRCHi << 8 | uchCRCLo) ; }//uint16 crc16(uint8 *puchMsg, uint16 usDataLen) //开始发送 void beginSend(void) { b485Send = 1; //设为发送 sendPosi = 0; if(sendCount > 1) sendCount--; ACC = sendBuf[0]; TB8 = P; SBUF = sendBuf[0]; }//voi
15、d beginSend(void) //读线圈状态 void readCoil(void) { uint8 addr; uint8 tempAddr; uint8 byteCount; uint8 bitCount; uint16 crcData; uint8 position; uint8 i,k; uint8 result; uint16 tempData; uint8 exit = 0; //addr = (receBuf[2]<<8) + receBuf[3]; //tempAddr = addr & 0xfff;
16、addr = receBuf[3];
tempAddr = addr;
//bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数
bitCount = receBuf[5];
byteCount = bitCount / 8; //字节个数
if(bitCount%8 != 0)
byteCount++;
for(k=0;k 17、i=0;i<8;i++)
{
getCoilVal(tempAddr,&tempData);
sendBuf[position] |= tempData << i;
tempAddr++;
if(tempAddr >= addr+bitCount)
if(tempAddr >= addr+bitCount)
{ //读完
exit = 1;
break;
}
}
if(exit == 1)
break;
}
sendBuf[0] = localAddr;
sendBuf 18、[1] = 0x01;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData >> 8;
byteCount++;
sendBuf[byteCount] = crcData & 0xff;
sendCount = byteCount + 1;
beginSend();
}//void readCoil(void)
/读寄存器
void readRegisters(void)
{
u 19、int8 addr;
uint8 tempAddr;
uint16 result;
uint16 crcData;
uint8 readCount;
uint8 byteCount;
uint8 finsh; //1完成 0出错
uint16 i;
uint16 tempData = 0;
//addr = (receBuf[2]<<8) + receBuf[3];
//tempAddr = addr & 0xfff;
addr = receBuf[3];
tempAddr = addr;
//readCount = (re 20、ceBuf[4]<<8) + receBuf[5]; //要读的个数
readCount = receBuf[5];
byteCount = readCount * 2;
for(i=0;i 21、Buf[1] = 3;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc16(sendBuf,byteCount);
sendBuf[byteCount] = crcData >> 8;
byteCount++;
sendBuf[byteCount] = crcData & 0xff;
sendCount = byteCount + 1;
beginSend();
}//void readRegisters(void)
//强制单个线圈
void forceSingleCoil(void 22、)
{
uint8 addr;
uint8 tempAddr;
uint16 tempData;
uint8 onOff;
uint8 i;
//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(onOf 23、f == 0xff)
{ //设为ON
tempData = 1;
}
//else if(onOff == 0x0000)
else if(onOff == 0x00)
{ //设为OFF
tempData = 0;
}
setCoilVal(tempAddr,tempData);
for(i=0;i 24、)
//设置多个寄存器
void presetMultipleRegisters(void)
{
uint8 addr;
uint8 tempAddr;
uint8 byteCount;
uint8 setCount;
uint16 crcData;
uint16 tempData;
uint8 finsh; //为1时完成 为0时出错
uint8 i;
//addr = (receBuf[2]<<8) + receBuf[3];
//tempAddr = addr & 0xfff;
addr = receBuf[3];
t 25、empAddr = addr & 0xff;
//setCount = (receBuf[4]<<8) + receBuf[5];
setCount = receBuf[5];
byteCount = receBuf[6];
for(i=0;i 26、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();
}//void presetMultipleRegisters(void)
//检查uart 27、0数据
void checkComm0Modbus(void)
{
uint16 crcData;
uint16 tempData;
if(receCount > 4)
{
switch(receBuf[1])
{
case 1://读取线圈状态(读取点 16位以内)
case 3://读取保持寄存器(一个或多个)
case 5://强制单个线圈
case 6://设置单个寄存器
if(receCount >= 8)
{//接收完成一组数据
//应该关闭接收中断
if(rec 28、eBuf[0]==localAddr && checkoutError==0)
{
crcData = crc16(receBuf,6);
if(crcData == receBuf[7]+(receBuf[6]<<8))
{//校验正确
if(receBuf[1] == 1)
{//读取线圈状态(读取点 16位以内)
readCoil();
}
else if(receBuf[1] == 3)
{//读取保 29、持寄存器(一个或多个)
readRegisters();
}
else if(receBuf[1] == 5)
{//强制单个线圈
forceSingleCoil();
}
else if(receBuf[1] == 6)
{
//presetSingleRegister();
}
}
}
receCount = 0; 30、
checkoutError = 0;
}
break;
case 15://设置多个线圈
tempData = receBuf[6];
tempData += 9; //数据个数
if(receCount >= tempData)
{
if(receBuf[0]==localAddr && checkoutError==0)
{
crcData = crc16(receBuf,tempData-2);
if(crcData == (rec 31、eBuf[tempData-2]<<8)+ receBuf[tempData-1])
{
//forceMultipleCoils();
}
}
receCount = 0;
checkoutError = 0;
}
break;
case 16://设置多个寄存器
tempData = (receBuf[4]<<8) + receBuf[5];
tempData = tempData * 2; //数据个数
temp 32、Data += 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();
}
}
33、 receCount = 0;
checkoutError = 0;
}
break;
default:
break;
}
}
}//void checkComm0(void)
//取线圈状态 返回0表示成功
uint16 getCoilVal(uint16 addr,uint16 *tempData)
{
uint16 result = 0;
uint16 tempAddr;
tempAddr = addr & 0xfff;
//只取低8位地址
switch(te 34、mpAddr & 0xff)
{
case 0:
break;
case 1:
*tempData = testCoil;
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10 35、
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
case 15:
break;
case 16:
break;
default:
break;
}
return result;
}//uint16 getCoilVal(uint16 addr,uint16 *data)
//设定线圈状态 返回0表示成功
uint16 36、 setCoilVal(uint16 addr,uint16 tempData)
{
uint16 result = 0;
uint16 tempAddr;
tempAddr = addr & 0xfff;
switch(tempAddr & 0xff)
{
case 0:
break;
case 1:
testCoil = tempData;
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 37、 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
case 15:
break;
case 16:
break;
38、default:
break;
}
return result;
}//uint16 setCoilVal(uint16 addr,uint16 data)
//取寄存器值 返回0表示成功
uint16 getRegisterVal(uint16 addr,uint16 *tempData)
{
uint16 result = 0;
uint16 tempAddr;
tempAddr = addr & 0xfff;
switch(tempAddr & 0xff)
{
case 0:
break;
case 1 39、
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
40、
break;
case 14:
break;
case 15:
break;
case 16:
*tempData = testRegister;
break;
default:
break;
}
return result;
}//uint16 getRegisterVal(uint16 addr,uint16 &data)
//设置寄存器值 返回0表示成功
uint16 setRegisterVal(uint16 addr,uint16 tempDat 41、a)
{
uint16 result = 0;
uint16 tempAddr;
tempAddr = addr & 0xfff;
switch(tempAddr & 0xff)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
brea 42、k;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
case 15:
break;
case 16:
testRegister = tempData;
break;
default:
break;
}
return result;
}//uint8 setRegisterVal(uint16 addr,uint16 data)
©2010-2025 宁波自信网络信息技术有限公司 版权所有
客服电话:4009-655-100 投诉/维权电话:18658249818