您好,欢迎来到爱站旅游。
搜索
您的当前位置:首页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) {

仅供个人学习参考

b485Send=1;//设为发送 sendPosi=0; if(sendCount>1) sendCount--; ACC=sendBuf[0]; TB8=P; SBUF=sendBuf[0]; }//voidbeginSend(void) //读线圈状态 voidreadCoil(void) {

uint8addr; uint8tempAddr; uint8byteCount; uint8bitCount; uint16crcData; uint8position; 仅供个人学习参考

uint8i,k; uint8result; uint16tempData; uint8exit=0;

//addr=(receBuf[2]<<8)+receBuf[3]; //tempAddr=addr&0xfff; 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;kfor(i=0;i<8;i++) {

getCoilVal(tempAddr,&tempData); sendBuf[position]|=tempData<=addr+bitCount) if(tempAddr>=addr+bitCount) {//读完 exit=1; break; } }

if(exit==1) break; }

sendBuf[0]=localAddr; sendBuf[1]=0x01; 仅供个人学习参考

sendBuf[2]=byteCount; byteCount+=3;

crcData=crc16(sendBuf,byteCount); sendBuf[byteCount]=crcData>>8; byteCount++; sendBuf[byteCount]=crcData&0xff; sendCount=byteCount+1; beginSend(); }//voidreadCoil(void) /读寄存器 voidreadRegisters(void) {

uint8addr; uint8tempAddr; uint16result; uint16crcData; uint8readCount; 仅供个人学习参考

uint8byteCount;

uint8finsh;//1完成0出错 uint16i;

uint16tempData=0;

//addr=(receBuf[2]<<8)+receBuf[3]; //tempAddr=addr&0xfff; addr=receBuf[3]; tempAddr=addr; //readCount=(receBuf[4]<<8)+receBuf[5];//要读的个数 readCount=receBuf[5]; byteCount=readCount*2; for(i=0;igetRegisterVal(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;isendBuf[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;itempData=(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: break; case14: break; case15: break; case16: testRegister=tempData; break; default: break; }

returnresult; }//uint8setRegisterVal(uint16addr,uint16data)

仅供个人学习参考

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- azee.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务