[应用相关] modbus通讯协议-接收部分-求指教

[复制链接]
1568|4
 楼主| garett 发表于 2014-8-2 12:32 | 显示全部楼层 |阅读模式
本帖最后由 garett 于 2014-8-2 17:15 编辑

MODBUS通讯协议。本人写了接收程序。大家一起来验证下。看看有没有什么问题个需要更改的地方。
求交流啊啊啊啊啊。每个功能的具体函数。都暂时控制的。因为还没想清楚用数组还是什么别的方法来控制。

/*获取StartAddr的第i个8位数据 不够补零*/
u8 GetByteData(u16 StartAdd,u16 i);
/*获取StartAddr的第i个数据*/
u16 GetData(u16 StartAdd,u16 i);
/*从StateAddr写入value 8位数据*/
void WriteForceState(u16 StateAddr,u8 value);
/*写寄存器值*/
void WriteRegister(u16 RegAddr,u16 RegData);

工程文件: MODBUS_VER_1.0.zip (991.87 KB, 下载次数: 2)



= =大家一起来纠错啊~~还有说说自己的看法啊。。求交流。。



  1. #define SlaveID             0x01   //主机地址

  2. #define ReadCoilState       1   //读取线圈状态
  3. #define ReadInputState      2   //读取输入状态
  4. #define ReadHoldRegister    3   //读取保持寄存器
  5. #define ReadInputRegister   4   //读取输入寄存器
  6. #define ForceSingleCoilOutputState  5   //强制写单线圈输出状态
  7. #define PresetSingleRegister 6  //预设(写)单寄存器

  8. #define CommIndexSlaveID    0   //地址
  9. #define CommIndexFunction   1   //功能码
  10. #define CommIndexStartAddrH 2   //起始地址高位
  11. #define CommIndexStartAddrL 3   //起始地址低位
  12. #define CommIndexForceState 4   //强制状态
  13. #define CommIndexDataH      4   //数据高位
  14. #define CommIndexDataL      5   //数据低位


  15. #define MaxRegisterLen      20  //寄存器最大长度
  16. #define MaxDataLen          30  //数据最大长度

  17. u8  CommIndexLength=0;          //通信指针长度 在UART接收时设置
  18. u8  CommIndexEnd=0xff;          //通信指针结束 在UART接收时设置

  19. u8  SendBuf[MaxDataLen]=0;               //发送缓冲区
  20. u8  ReceiveBuf[MaxDataLen]=0;            //接收缓冲区
  21. //接收处理
  22. void DisposeReceive(void)
  23. {
  24.     u16 CRC16Temp;              //CRC校验临时存储变量
  25.     if(ReceiveBuf[CommIndexSlaveID]==SlaveID)   //如果接收到的数据地址为从机地址
  26.     {   
  27.         /*计算发送来的数据的CRC校验码*/
  28.         CRC16Temp=GetCRC16(ReceiveBuf,CommIndexLength);
  29.         /*验证计算出来的CRC校验值是否与缓冲区校验值相等*/
  30.         if(CRC16Temp==((u16)ReceiveBuf[CommIndexEnd-1]<<8|(u16)ReceiveBuf[CommIndexEnd]))   
  31.         {   /*CRC校验正确,数据无误*/
  32.             switch(ReceiveBuf[CommIndexFunction])
  33.             {
  34.                 case ReadCoilState:     //1:读取线圈状态
  35.                     ReadCoil();
  36.                     break;
  37.                 case ReadInputState:    //2:读取输入状态
  38.                     ReadInput();
  39.                     break;
  40.                 case ReadHoldRegister:  //3读取保存寄存器
  41.                     ReadHoldReg();
  42.                     break;
  43.                 case ReadInputRegister:  //4读取输入寄存器
  44.                     ReadInputReg();
  45.                     break;
  46.                 case ForceSingleCoilOutputState:    //5强制写单线圈输出状态
  47.                     ForceSingleCoil();
  48.                     break;
  49.                 case PresetSingleRegister:          //6预设(写)单寄存器
  50.                     PresetSingleReg();
  51.                     break;
  52.                 default:
  53.                     break;
  54.             }
  55.         }
  56.         else                            //CRC校验错误
  57.         {
  58.             RequestRetry();             //请求主机重发指令
  59.         }
  60.     }
  61. }
  62. /*
  63. *功能码:0x01 读取线圈状态
  64. *发送:[硬件地址][01][起始地址高][起始地址低][总位数高][总位数低][CRC低][CRC高]
  65. *返回:[硬件地址][01][  字节数  ][  位状态1 ][位状态2 ][位状态n ][CRC低][CRC高]
  66. */
  67. void ReadCoil(void)
  68. {
  69.     u16 StartAdd,BitNum,CRC16Temp,i;
  70.     u8 CommIndexNum;
  71.     StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
  72.     BitNum=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
  73.     BitNum=BitNum/8;
  74.     if(BitNum%8!=0)
  75.         BitNum++;
  76.     SendBuf[CommIndexNum++]=SlaveID;
  77.     SendBuf[CommIndexNum++]=ReadCoilState;
  78.     SendBuf[CommIndexNum++]=(u8)BitNum;
  79.     /*获取X位状态*/
  80.     for(i=0;i<BitNum;i++)
  81.     {   
  82.         /*获取StartAdd的第i个8位数据 不够补0*/
  83.         SendBuf[CommIndexNum++]=GetByteData(StartAdd,i);   
  84.     }
  85.     CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
  86.     SendBuf[CommIndexNum++]=(u8)CRC16Temp>>8;
  87.     SendBuf[CommIndexNum++]=(u8)CRC16Temp;
  88.     //从SendBuf发送CommIndexNum个8位的返回数据
  89.     Uart1_Send(SendBuf,CommIndexNum);
  90.     //结束 清除缓冲区
  91.     memset(SendBuf,0,sizeof(SendBuf));
  92. }   

  93. /*
  94. *功能码:0x02 读取输入状态
  95. *发送:[硬件地址][02][起始地址高][起始地址低][总位数高][总位数低][CRC低][CRC高]
  96. *返回:[硬件地址][02][  字节数  ][  位状态1 ][位状态2 ][位状态n ][CRC低][CRC高]
  97. */
  98. void ReadInput(void)
  99. {
  100.     u16 StartAdd,BitNum,CRC16Temp,i;
  101.     u8 CommIndexNum=0;
  102.     StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
  103.     BitNum=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
  104.     BitNum=BitNum/8;
  105.     if(BitNum%8!=0)
  106.         BitNum++;
  107.     SendBuf[CommIndexNum++]=SlaveID;
  108.     SendBuf[CommIndexNum++]=ReadInputState;
  109.     SendBuf[CommIndexNum++]=(u8)BitNum;
  110.     /*获取X位状态*/
  111.     for(i=0;i<BitNum;i++)
  112.     {   
  113.         /*获取StartAdd的第i个8位数据 不够补0*/
  114.         SendBuf[CommIndexNum++]=GetByteData(StartAdd,i);   
  115.     }
  116.     CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
  117.     SendBuf[CommIndexNum++]=(u8)CRC16Temp>>8;
  118.     SendBuf[CommIndexNum++]=(u8)CRC16Temp;
  119.     //从SendBuf发送CommIndexNum个8位的返回数据
  120.     Uart1_Send(SendBuf,CommIndexNum);
  121.     //结束 清除缓冲区
  122.     memset(SendBuf,0,sizeof(SendBuf));
  123. }

  124. /*
  125. *功能码:0x03 读取保持寄存器
  126. *发送:[硬件地址][03][起始地址高][起始地址低][总寄存器数高][总寄存器数低][    CRC低   ][     CRC高  ]
  127. *返回:[硬件地址][03][  字节数  ][寄存器0高 ][  寄存器0低 ][  寄存器1高 ][  寄存器1低 ][  寄存器n高 ][  寄存器n低 ][  CRC低 ][  CRC高 ]
  128. */
  129. void ReadHoldReg(void)
  130. {
  131.     u16 StartAdd,RegLen,i,DataTemp,CRC16Temp;
  132.     u8  CommIndexNum=0;
  133.     //获取起始地址
  134.     StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
  135.     //获取读取长度
  136.     RegLen=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];

  137.     SendBuf[CommIndexNum++]=SlaveID;
  138.     SendBuf[CommIndexNum++]=ReadHoldRegister;
  139.     SendBuf[CommIndexNum++]=(u8)(RegLen*2);
  140.     for(i=0;i<RegLen;i++)
  141.     {
  142.         /*获取16位数据并返回赋给[寄存器n高][寄存器n低]*/
  143.         DataTemp=GetData(StartAdd,i);
  144.         SendBuf[CommIndexNum++] = (u8)(DataTemp>>8);
  145.         SendBuf[CommIndexNum++] = (u8)(DataTemp&0x00ff);
  146.     }
  147.     CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
  148.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
  149.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
  150.     //从SendBuf发送CommIndexNum个8位的返回数据
  151.     Uart1_Send(SendBuf,CommIndexNum);
  152.     //结束 清除缓冲区
  153.     memset(SendBuf,0,sizeof(SendBuf));
  154. }

  155. /*
  156. *功能码:0x04 读取输入寄存器
  157. *发送:[硬件地址][04][起始地址高][起始地址低][总寄存器数高][总寄存器数低][    CRC低   ][     CRC高  ]
  158. *返回:[硬件地址][04][  字节数  ][寄存器0高 ][  寄存器0低 ][  寄存器1高 ][  寄存器1低 ][  寄存器n高 ][  寄存器n低 ][  CRC低 ][  CRC高 ]
  159. */
  160. void ReadInputReg(void)
  161. {
  162.     u16 StartAdd,RegLen,i,DataTemp,CRC16Temp;
  163.     u8  CommIndexNum=0;
  164.     //获取起始地址
  165.     StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
  166.     //获取读取长度
  167.     RegLen=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];

  168.     SendBuf[CommIndexNum++]=SlaveID;
  169.     SendBuf[CommIndexNum++]=ReadHoldRegister;
  170.     SendBuf[CommIndexNum++]=(u8)(RegLen*2);
  171.     for(i=0;i<RegLen;i++)
  172.     {
  173.         /*获取16位数据并返回赋给[寄存器n高][寄存器n低]*/
  174.         DataTemp=GetData(StartAdd,i);         
  175.         SendBuf[CommIndexNum++] = (u8)(DataTemp>>8);
  176.         SendBuf[CommIndexNum++] = (u8)(DataTemp&0x00ff);
  177.     }
  178.     CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
  179.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
  180.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
  181.     //串口发送返回数据
  182.     Uart1_Send(SendBuf,CommIndexNum);
  183.     //结束 清除缓冲区
  184.     memset(SendBuf,0,sizeof(SendBuf));
  185. }

  186. /*
  187. *功能码:0x05 强制(写)单线圈(输出状态)
  188. *发送:[硬件地址][05][线圈地址高][线圈地址低][ 强制状态 ][ CRC低 ][ CRC高 ]
  189. *返回:[硬件地址][05][线圈地址高][线圈地址低][ 强制状态 ][ CRC低 ][ CRC高 ]
  190. */
  191. void ForceSingleCoil(void)
  192. {
  193.     u16 CoilAddr,CRC16Temp;
  194.     u8  ForceState,CommIndexNum=0;
  195.     CoilAddr=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
  196.     ForceState=ReceiveBuf[CommIndexForceState];
  197.     //从CoilAddr写入ForceState 8位数据
  198.     WriteForceState(CoilAddr,ForceState);

  199.     SendBuf[CommIndexNum++]=SlaveID;
  200.     SendBuf[CommIndexNum++]=ForceSingleCoilOutputState;
  201.     SendBuf[CommIndexNum++]=(u8)CoilAddr>>8;
  202.     SendBuf[CommIndexNum++]=(u8)CoilAddr&0x00ff;
  203.     SendBuf[CommIndexNum++]=ForceState;
  204.     CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
  205.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
  206.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
  207.     //串口发送返回数据
  208.     Uart1_Send(SendBuf,CommIndexNum);
  209.     //结束 清除缓冲区
  210.     memset(SendBuf,0,sizeof(SendBuf));
  211. }

  212. /*
  213. *功能码:0x06 预设(写)单寄存器
  214. *发送:[硬件地址][06][寄存器地址高][寄存器地址低][寄存器值高][寄存器值低][ CRC低 ][ CRC高 ]
  215. *返回:[硬件地址][06][寄存器地址高][寄存器地址低][寄存器值高][寄存器值低][ CRC低 ][ CRC高 ]
  216. */
  217. void PresetSingleReg(void)
  218. {
  219.     u16 RegAddr,RegData,CRC16Temp;
  220.     u8 CommIndexNum=0;
  221.     RegAddr=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
  222.     RegData=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
  223.     /*写寄存器值*/
  224.     WriteRegister(RegAddr,RegData);

  225.     SendBuf[CommIndexNum++]=SlaveID;
  226.     SendBuf[CommIndexNum++]=PresetSingleRegister;
  227.     SendBuf[CommIndexNum++]=(u8)RegAddr>>8;
  228.     SendBuf[CommIndexNum++]=(u8)RegAddr&0x00ff;
  229.     SendBuf[CommIndexNum++]=(u8)RegData>>8;
  230.     SendBuf[CommIndexNum++]=(u8)RegData&0x00ff;
  231.     CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
  232.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
  233.     SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
  234.     //串口发送返回数据
  235.     Uart1_Send(SendBuf,CommIndexNum);
  236.     //结束 清除缓冲区
  237.     memset(SendBuf,0,sizeof(SendBuf));
  238. }

  239. /*
  240. *CRC校验错误 请求主机重发指令
  241. */
  242. void RequestRetry(void)            
  243. {

  244. }

 楼主| garett 发表于 2014-8-2 12:40 | 显示全部楼层
。。为啥添加附件不能超过1M。。超过了。。怎么上传工程??。。。
mmuuss586 发表于 2014-8-2 15:23 | 显示全部楼层
garett 发表于 2014-8-2 12:40
。。为啥添加附件不能超过1M。。超过了。。怎么上传工程??。。。

我记得好像是4M;
可能你级别太低,有限制吧;
分卷压缩试下;
 楼主| garett 发表于 2014-8-2 17:14 | 显示全部楼层
mmuuss586 发表于 2014-8-2 15:23
我记得好像是4M;
可能你级别太低,有限制吧;
分卷压缩试下;

MODBUS_VER_1.0.zip (991.87 KB, 下载次数: 2)


= =上传了!!求看!
szjyp226 发表于 2014-8-4 09:21 | 显示全部楼层
:lol  虽然不太明白。。但是帮楼主顶一个 希望楼主早点解决问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

21

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部