你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32驱动w5500移植FreeModbus实现ModbusTCP

[复制链接]
STMCU小助手 发布时间:2022-4-23 16:17
首先我们下载FreeModbus源码,然后放到自己的工程中,新建一个MODBUS_TCP和PORT_TCP文件夹,然后将相关文件复制到里面,如下图所示:
20200323102539294.png

然后修改porttcp中的代码:
首先定义一个数组用于接收数据:
  1. static UCHAR    aucTCPBuf[MB_TCP_BUF_SIZE];           //接收缓冲区
复制代码

然后在xMBTCPPortInit中初始化socket连接,然后监听端口。

  1. BOOL
  2. xMBTCPPortInit( USHORT usTCPPort )
  3. {
  4.     BOOL bOkay = FALSE;

  5.     // 侦听端口 Modbus-TCP 端口
  6.         socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);
  7.         listen_tcp_socket(SOCK_TCP_PORT);

  8.     bOkay = TRUE;
  9.     return bOkay;
  10. }
复制代码

然后在xMBTCPPortSendResponse函数中发送数据

  1. BOOL
  2. xMBTCPPortSendResponse(const UCHAR * pucMBTCPFrame, USHORT usTCPLength )
  3. {
  4.         send_tcp_socket_data(SOCK_TCP_PORT,(UCHAR*)pucMBTCPFrame,usTCPLength);        
  5.     return TRUE;
  6. }
复制代码

然后在xMBPortTCPPool执行接收和其他操作

  1. BOOL
  2. xMBPortTCPPool( void )
  3. {  
  4.         unsigned short int us_rlen;
  5.         unsigned char i;
  6.         i=get_tcp_socket_state(SOCK_TCP_PORT);

  7.         if(i==SOCK_ESTABLISHED_TCP)
  8.         {
  9.                 if(get_tcp_socket_irq(SOCK_TCP_PORT) & Sn_IR_CON_TCP)                //查看中断有没有发生
  10.                 {
  11.                         clear_tcp_socket_irq(SOCK_TCP_PORT, Sn_IR_CON_TCP);         /*清除接收中断标志位*/                                                         
  12.                 }
  13.                 us_rlen=get_tcp_rx_buffer_size(SOCK_TCP_PORT);                                 //获取接收到的数据字节                                                   /*定义len为已接收数据的长度*/
  14.                 if(us_rlen==0)                                                                                                //没有接收到数据
  15.                         return FALSE;                                                                                        //返回
  16.                 else
  17.                 {
  18.                         recv_tcp_socket_data(SOCK_TCP_PORT,aucTCPBuf,us_rlen);         //接收数据                                                                            /*接收来自Server的数据*/
  19.                         printf("receive\r\n");
  20.                         usTCPBufLen=us_rlen;
  21.                 }
  22.                 ( void )xMBPortEventPost( EV_FRAME_RECEIVED );                        //发送已接收到新数据到Modbus-TCP状态机
  23.         }
  24.         else if(i==SOCK_CLOSED_TCP)                                                                        //如果socket关闭
  25.         {
  26.                 socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);//重新初始化
  27.         }
  28.         else if(i==SOCK_INIT_TCP)                                                                //如果socket初始化完毕,监听端口
  29.         {
  30.                 listen_tcp_socket(SOCK_TCP_PORT);
  31.         }
  32.         else if(i==SOCK_CLOSE_WAIT_TCP)                                                        //如果socket等待关闭,关闭socket连接
  33.         {
  34.                 close_tcp_socket(SOCK_TCP_PORT);
  35.         }

  36.         return TRUE;
  37. }
复制代码

其次还要实现读线圈、写线圈、读离散输入、写保持寄存器、读保持寄存器、读输入寄存器等功能,如下:

  1. #define REG_INPUT_START       0x0001        //输入寄存器起始地址
  2. #define REG_INPUT_NREGS       8                        //输入寄存器数量

  3. #define REG_HOLDING_START     0x0001        //保持寄存器起始地址
  4. #define REG_HOLDING_NREGS     8                        //保持寄存器数量

  5. #define REG_COILS_START       0x0001        //线圈起始地址
  6. #define REG_COILS_SIZE        16                        //线圈数量

  7. #define REG_DISCRETE_START    0x0001        //开关寄存器其实地址
  8. #define REG_DISCRETE_SIZE     16                        //开关寄存器数量
  9. //输入寄存器内容
  10. uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
  11. //保持寄存器内容               
  12. uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007};                                       
  13. //线圈状态
  14. uint8_t ucRegCoilsBuf[REG_COILS_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
  15. //离散寄存器内容
  16. uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x01};

  17. /****************************************************************************
  18. * 名          称:eMBRegInputCB
  19. * 功    能:读取输入寄存器,对应功能码是 04 eMBFuncReadInputRegister
  20. * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
  21. *                                                usAddress: 寄存器地址
  22. *                                                usNRegs: 要读取的寄存器个数
  23. * 出口参数:
  24. * 注          意:上位机发来的 帧格式是: SlaveAddr(1 Byte)+FuncCode(1 Byte)
  25. *                                                                +StartAddrHiByte(1 Byte)+StartAddrLoByte(1 Byte)
  26. *                                                                +LenAddrHiByte(1 Byte)+LenAddrLoByte(1 Byte)+
  27. *                                                                +CRCAddrHiByte(1 Byte)+CRCAddrLoByte(1 Byte)
  28. *                                                        3 区
  29. ****************************************************************************/
  30. eMBErrorCode
  31. eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
  32. {
  33.     eMBErrorCode    eStatus = MB_ENOERR;
  34.     int             iRegIndex;

  35.     if( ( usAddress >= REG_INPUT_START )
  36.         && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
  37.     {
  38.         iRegIndex = ( int )( usAddress - REG_INPUT_START );
  39.         while( usNRegs > 0 )
  40.         {
  41.             *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] >> 8 );
  42.             *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] & 0xFF );
  43.             iRegIndex++;
  44.             usNRegs--;
  45.         }
  46.     }
  47.     else
  48.     {
  49.         eStatus = MB_ENOREG;
  50.     }

  51.     return eStatus;
  52. }

  53. /****************************************************************************
  54. * 名          称:eMBRegHoldingCB
  55. * 功    能:对应功能码有:06 写保持寄存器 eMBFuncWriteHoldingRegister
  56. *                                                                                                        16 写多个保持寄存器 eMBFuncWriteMultipleHoldingRegister
  57. *                                                                                                        03 读保持寄存器 eMBFuncReadHoldingRegister
  58. *                                                                                                        23 读写多个保持寄存器 eMBFuncReadWriteMultipleHoldingRegister
  59. * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
  60. *                                                usAddress: 寄存器地址
  61. *                                                usNRegs: 要读写的寄存器个数
  62. *                                                eMode: 功能码
  63. * 出口参数:
  64. * 注          意:4 区
  65. ****************************************************************************/
  66. eMBErrorCode
  67. eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
  68. {
  69.         eMBErrorCode    eStatus = MB_ENOERR;
  70.         int             iRegIndex;


  71.         if((usAddress >= REG_HOLDING_START)&&\
  72.                 ((usAddress+usNRegs) <= (REG_HOLDING_START + REG_HOLDING_NREGS)))
  73.         {
  74.                 iRegIndex = (int)(usAddress - REG_HOLDING_START);
  75.                 switch(eMode)
  76.                 {                                       
  77.                         case MB_REG_READ://读 MB_REG_READ = 0
  78.                                 while(usNRegs > 0)
  79.                                 {
  80.                                         *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] >> 8);            
  81.                                         *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] & 0xFF);
  82.                                         iRegIndex++;
  83.                                         usNRegs--;                                       
  84.                                 }                           
  85.                         break;
  86.                         case MB_REG_WRITE://写 MB_REG_WRITE = 0
  87.                                 while(usNRegs > 0)
  88.                                 {         
  89.                                         usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
  90.                                         usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
  91.                                         iRegIndex++;
  92.                                         usNRegs--;
  93.                                 }
  94.                         break;                                
  95.                 }
  96.         }
  97.         else//错误
  98.         {
  99.                 eStatus = MB_ENOREG;
  100.         }        
  101.         
  102.         return eStatus;
  103. }

  104. /****************************************************************************
  105. * 名          称:eMBRegCoilsCB
  106. * 功    能:对应功能码有:01 读线圈 eMBFuncReadCoils
  107. *                                                  05 写线圈 eMBFuncWriteCoil
  108. *                                                  15 写多个线圈 eMBFuncWriteMultipleCoils
  109. * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
  110. *                                                usAddress: 线圈地址
  111. *                                                usNCoils: 要读写的线圈个数
  112. *                                                eMode: 功能码
  113. * 出口参数:
  114. * 注          意:如继电器
  115. *                                                0 区
  116. ****************************************************************************/
  117. eMBErrorCode
  118. eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
  119. {
  120.         eMBErrorCode    eStatus = MB_ENOERR;
  121.         int             iRegIndex;
  122.         u8 i;
  123.         USHORT readNumber=usNCoils;
  124.         USHORT coilValue=0x0000;
  125.         if((usAddress >= REG_COILS_START)&&\
  126.         ((usAddress+usNCoils) <= (REG_COILS_START + REG_COILS_SIZE)))
  127.         {
  128.                 iRegIndex = (int)(usAddress + usNCoils-REG_COILS_START);
  129.                 switch(eMode)
  130.                 {                                       
  131.                         case MB_REG_READ://读 MB_REG_READ = 0
  132.                                 for(i=0;i<usNCoils;i++)
  133.                                 {
  134.                                         readNumber--;
  135.                                         iRegIndex--;
  136.                                         coilValue|=ucRegCoilsBuf[iRegIndex]<<readNumber;
  137.                                 }
  138.                                 if(usNCoils<=8)
  139.                                 {
  140.                                         * pucRegBuffer=coilValue;
  141.                                 }
  142.                                 else
  143.                                 {
  144.                                         * pucRegBuffer++ = (coilValue)&0x00ff;
  145.                                         * pucRegBuffer++ = (coilValue>>8)&0x00ff;
  146.                                 }
  147.                         break;                           
  148.                         case MB_REG_WRITE://写 MB_REG_WRITE = 1
  149.                                 while(usNCoils > 0)
  150.                                 {         
  151.                                         //                         usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
  152.                                         //           usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
  153.                                                 iRegIndex++;
  154.                                                 usNCoils--;
  155.                                 }
  156.                         break;
  157.                 }
  158.         }
  159.         else//错误
  160.         {
  161.                 eStatus = MB_ENOREG;
  162.         }        

  163.         return eStatus;
  164. }
  165. /****************************************************************************
  166. * 名          称:eMBRegDiscreteCB
  167. * 功    能:读取离散寄存器,对应功能码有:02 读离散寄存器 eMBFuncReadDiscreteInputs
  168. * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
  169. *                                                usAddress: 寄存器地址
  170. *                                                usNDiscrete: 要读取的寄存器个数
  171. * 出口参数:
  172. * 注          意:1 区
  173. ****************************************************************************/
  174. eMBErrorCode
  175. eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
  176. {
  177.         eMBErrorCode    eStatus = MB_ENOERR;
  178.         int             iRegIndex;
  179.         u8 i;
  180.         USHORT readNumber=usNDiscrete;
  181.         USHORT coilValue=0x0000;
  182.         iRegIndex = (int)(usAddress + usNDiscrete-REG_DISCRETE_START);
  183.         if((usAddress >= REG_DISCRETE_START)&&\
  184.         ((usAddress+usNDiscrete) <= (REG_DISCRETE_START + REG_DISCRETE_SIZE)))
  185.         {
  186.                 for(i=0;i<usNDiscrete;i++)
  187.                 {
  188.                         readNumber--;
  189.                         iRegIndex--;
  190.                         coilValue|=ucRegDiscreteBuf[iRegIndex]<<readNumber;
  191.                 }
  192.                 if(usNDiscrete<=8)
  193.                 {
  194.                         * pucRegBuffer=coilValue;
  195.                 }
  196.                 else
  197.                 {
  198.                         * pucRegBuffer++ = (coilValue)&0x00ff;
  199.                         * pucRegBuffer++ = (coilValue>>8)&0x00ff;
  200.                 }
  201.         }
  202.         else
  203.         {
  204.                 eStatus = MB_ENOREG;
  205.         }
  206.     return eStatus;
  207. }




复制代码


收藏 评论0 发布时间:2022-4-23 16:17

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版