哪位朋友有modbus通讯协议编写成C++代码,指导一下

m0_37669975 2017-03-30 09:22:31
看了modbus通讯协议 但是要编写代码时 还是没有头绪? 麻烦哪位朋友帮帮指导一下~! 谢谢!
...全文
1128 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
m0_37669975 2017-05-09
  • 打赏
  • 举报
回复
modbus协议 详解 哪位朋友有这方面的资料 麻烦发一份 谢谢大家!
m0_37669975 2017-04-09
  • 打赏
  • 举报
回复
modbus协议 哪位朋友说说
m0_37669975 2017-04-02
  • 打赏
  • 举报
回复
要实现主机~~~libmodbus 开源库 怎么在QT 用 c++里面使用
灌水号 2017-04-01
  • 打赏
  • 举报
回复
你想实现主机还是从机?从机的话建议用freemodbus.主机用libmodbus凑合用.
xxxzzw 2017-03-31
  • 打赏
  • 举报
回复
DSP 服务器端代码 #include "Modbus.h" #include "parameter.h" //只执行一次,而且对时间要求不严格,不需保密的程序,放至FLASH或ExRam #pragma CODE_SECTION(ModbusRecv,"ExRamfunction") #pragma CODE_SECTION(CalcCrcFast,"ExRamfunction") #pragma CODE_SECTION(MarkCompute, "ExRamfunction") #pragma DATA_SECTION(m_auchCRCHi,"FlashCode") #pragma DATA_SECTION(m_auchCRCLo,"FlashCode") extern int GetCoilVal(Uint16 Addr,Uint16 *ReadState); extern int SetCoilVal(Uint16 Addr,Uint16 TempData); Uint16 MarkCompute(Uint16 DataSrc,Uint16 DataAnd,Uint16 DataOr); //正常校验码低位在前,高位在后 Uint16 LOHI = 1; /* * Modbus通信协议处理 * Modbus故障代码: * 0x01 非法功能码 0x80+原功能码 * 0x02 非法数据地址 0x80+原功能码 * 0x03 非法数据值 0x80+原功能码 * 0x04 寄存器操作失败 0x80+原功能码 */ int //当协议被正确解释时,返回以字节计数的返回给主站的数据长度 ModbusRecv( unsigned char *chRecvBuffer,//接收缓冲区 int iRecvLen,//接收的数据长度 unsigned char *chSendBuffer,//发送缓冲区指针 int iSendBufLen,//发送缓冲区长度 int iAddress//站地址 ) { int16 iSendLen = 0; unsigned int iErrorCode = 0; int iTemp; Uint16 AddrStart = 0; //起始地址 Uint16 ByteCount = 0; //读取数据区字节个数 Uint16 TempData = 0; int i = 0; Uint16 OrMark = 0; Uint16 AndMark = 0; int16 iCount = 0; Uint16 iDataAddr = 0; //缓冲区长度太小,无法应答报文 if(iSendBufLen < 6 ) return 0; //地址不正确 //if((chRecvBuffer[0] != 0xFF)&&(chRecvBuffer[0] != iAddress)) if((chRecvBuffer[0] != 0xFF)&&(chRecvBuffer[0] != sData.iSlaveAddr)) return 0; //数据校验不正确,//正常校验码低位在前,高位在后 if(CalcCrcFast(chRecvBuffer,iRecvLen) != 0x0000) return 0; switch(chRecvBuffer[1])//判断功能码 { case 0x03: //读寄存器操作功能 ReadHoldRegisters(); case 0x04: //ReadInputRegisters() AddrStart = chRecvBuffer[2] * 256 + chRecvBuffer[3]; // 起始地址 iCount = chRecvBuffer[4] * 256 + chRecvBuffer[5]; // 寄存器数量 if((iCount * 2 <= iSendBufLen - 5)//寄存器数量小于(发送缓冲区长度-5)/2 &&(iCount <= 123)) //允许读取的最大寄存器数量 {//最多允许读取的寄存器数量 chSendBuffer[0] = chRecvBuffer[0]; // 应答地址 chSendBuffer[1] = chRecvBuffer[1]; // 应答功能码 chSendBuffer[2] = ((2*iCount) & 0x00ff); // 以字节计数的数据长度 iSendLen = 3; while((iCount > 0)&&(iErrorCode == 0)) { iTemp = ParaRead(AddrStart,chSendBuffer+iSendLen,0); //GetInputRegisterVal(TempAddr, &TempData); if(iTemp > 0) { iSendLen += iTemp; //修正缓冲区指针 iCount -=iTemp/2; //修正寄存器数量 AddrStart +=iTemp/2; //修正读取的参数序号 }else { iErrorCode = 0x02; } } } else iErrorCode = 0x04;//寄存器操作失败 break; case 0x06://写单个寄存器 PresetSingleRegister(); if ( iRecvLen >= 8 )//寄存器的长度不一定是两个字节 { AddrStart = chRecvBuffer[2] * 256 + chRecvBuffer[3]; // 地址 //iDataValue = chRecvBuffer[4] * 256 + chRecvBuffer[5]; chSendBuffer[0] = chRecvBuffer[0]; chSendBuffer[1] = chRecvBuffer[1]; chSendBuffer[2] = chRecvBuffer[2]; chSendBuffer[3] = chRecvBuffer[3]; iSendLen = 4; //检查寄存器地址是否有效 iTemp = ParaWrite(AddrStart,chRecvBuffer+iSendLen,chSendBuffer+iSendLen,0); if( iTemp > 0) //寄存器地址有效 { iSendLen += iTemp; } else//寄存器操作失败 iErrorCode = 0x04; } else//非法数据 iErrorCode = 0x03; break; case 0x10://设置多个寄存器 PresetMultipleRegisters(); AddrStart = chRecvBuffer[2] * 256 + chRecvBuffer[3]; // 起始地址 iCount = chRecvBuffer[4] * 256 + chRecvBuffer[5]; // 寄存器数量 //iDataLen = chRecvBuffer[6]; //数据长度 for(i=0;i<6;i++) { chSendBuffer[i] = chRecvBuffer[i]; } iSendLen = 6; iDataAddr = 7; //指针指向第一个寄存器位置 //寄存器数量>0,数据长度有效iDataLen+6+2 < SCI_BUF_LEN,数据长度>0 if((iCount > 0)&&(iDataAddr + 2 + iCount*2 <= iRecvLen)&&(chRecvBuffer[6] == (iCount*2))) { while((iCount > 0)&&(iErrorCode == 0)) { iTemp = ParaWrite(AddrStart,chRecvBuffer+iDataAddr, chSendBuffer + iSendLen,0); if(iTemp > 0) { iDataAddr += iTemp; //移动数据指针 iCount -= iTemp/2; //寄存器数量减一 AddrStart += iTemp/2; //指向下一个寄存器 }else {//写寄存器操作失败 iErrorCode = 0x04; } } }else { iErrorCode = 0x03; } break; case 0x01: //ReadCoil(void); case 0x02: //ReadInputState(void); AddrStart = (chRecvBuffer[2] << 8) + chRecvBuffer[3]; iCount = (chRecvBuffer[4] << 8) + chRecvBuffer[5]; chSendBuffer[0] = chRecvBuffer[0]; chSendBuffer[1] = chRecvBuffer[1]; chSendBuffer[2] = (iCount + 7)>>3; iSendLen = 3; i = 0; while(iCount > 0 && iErrorCode == 0) { if( i == 0) chSendBuffer[iSendLen] = 0; if(GetCoilVal(AddrStart, &TempData)) { chSendBuffer[iSendLen] &= ~(1 << i);//清除原值 chSendBuffer[iSendLen] |= TempData << i;//写入新值 i++; AddrStart++; iCount--; if(i ==8) { i = 0; iSendLen++; } }else iErrorCode = 0x02; } if(iErrorCode == 0 && i > 0) iSendLen++; break; case 0x05: //ForceSingleCoil(void); //写单个线圈 AddrStart = (chRecvBuffer[2] << 8) + chRecvBuffer[3]; TempData = (chRecvBuffer[4] << 8) + chRecvBuffer[5]; if(SetCoilVal(AddrStart, TempData)) { GetCoilVal(AddrStart, &TempData); chSendBuffer[0] = chRecvBuffer[0]; chSendBuffer[1] = chRecvBuffer[1]; chSendBuffer[2] = chRecvBuffer[2]; chSendBuffer[3] = chRecvBuffer[3]; chSendBuffer[4] = (TempData >> 8) & 0x00FF;//chRecvBuffer[4]; chSendBuffer[5] = TempData & 0x00FF; //chRecvBuffer[5]; iSendLen = 6; }else//非法数据值 iErrorCode = 0x03; break; case 15: //设置多个继电器 ForceMultipleCoils(); AddrStart = (chRecvBuffer[2] << 8) + chRecvBuffer[3]; iCount = (chRecvBuffer[4] << 8) + chRecvBuffer[5]; ByteCount = (iCount + 7) >> 3; iDataAddr = 7; if(ByteCount == chRecvBuffer[6] && iDataAddr + 2 + ByteCount <= iSendBufLen) { i = 0; while(iCount > 0 && iErrorCode == 0) { if(SetCoilVal(AddrStart, (chRecvBuffer[iDataAddr] >> i) & 0x01)) { i++; AddrStart++; iCount--; if(i == 8) { i = 0; iDataAddr++; } }else iErrorCode = 0x02; } if(iErrorCode == 0) { chSendBuffer[0] = chRecvBuffer[0]; chSendBuffer[1] = chRecvBuffer[1]; chSendBuffer[2] = chRecvBuffer[2]; chSendBuffer[3] = chRecvBuffer[3]; chSendBuffer[4] = chRecvBuffer[4]; chSendBuffer[5] = chRecvBuffer[5]; iSendLen = 6; } }else//非法数据值 iErrorCode = 0x03; break; case 22: //掩码设置保持寄存器 MaskWrite4XRegister(); AddrStart = (chRecvBuffer[2] << 8) + chRecvBuffer[3]; AndMark = (chRecvBuffer[4] << 8) + chRecvBuffer[5]; OrMark = (chRecvBuffer[6] << 8) + chRecvBuffer[7]; if(ParaRead(AddrStart,(unsigned char*)&TempData,1) > 0) { TempData = MarkCompute(TempData, AndMark, OrMark); ParaWrite(AddrStart,(unsigned char*)&TempData,chSendBuffer+iSendLen,0); } for (i = 0; i < 8; i++) { chSendBuffer[i] = chRecvBuffer[i]; } iSendLen = 8; break; default://非法功能码 iErrorCode = 0x01; break; } if( iErrorCode )//返回错误信息 { chSendBuffer[0] = chRecvBuffer[0]; chSendBuffer[1] = chRecvBuffer[1] + 0x80; chSendBuffer[2] = iErrorCode; iSendLen = 3; } TempData=CalcCrcFast(chSendBuffer,iSendLen); //正常校验码低位在前,高位在后,为什么是反的???? //chSendBuffer[iSendLen] = (TempData & 0x00FF); //chSendBuffer[iSendLen + 1] = ((TempData >> 8) & 0x00FF); chSendBuffer[iSendLen] = ((TempData >> 8) & 0x00FF); chSendBuffer[iSendLen+1] = (TempData & 0x00FF); iSendLen += 2; //站地址与本站相符时,才会返回数据,对于广播数据,只响应,不返回结果 if(chRecvBuffer[0] == sData.iSlaveAddr) return iSendLen; return 0; } unsigned int CalcCrcFast(unsigned char*puchMsg,unsigned short usDataLen) { unsigned char uchCRCHi=0xFF ; unsigned char uchCRCLo=0xFF ; unsigned short uIndex ; while(usDataLen--) { uIndex=uchCRCHi^*puchMsg++; uchCRCHi=uchCRCLo^m_auchCRCHi[uIndex]; uchCRCLo=m_auchCRCLo[uIndex]; } return(uchCRCHi<<8 | uchCRCLo); }
m0_37669975 2017-03-31
  • 打赏
  • 举报
回复
谢谢~! 有可以运行的源代码 吗 可以让我下载 谢谢~!

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧