C语言编写modbus协议.docx
- 文档编号:28818447
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:20
- 大小:43.15KB
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:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 编写 modbus 协议