[STM32F4] STM32F407ZET7+ETH+LWIP移植freemodbus_TCP

[复制链接]
1707|28
 楼主| 慢醇 发表于 2024-4-10 16:19 | 显示全部楼层 |阅读模式
前言
        本次实验以 STM32F407ZET7 芯片为MCU,使用 8MHz 外部时钟源。以太网PHY层芯片为 LAN8720A,移植FreeModbus实现ModbusTCP网口通信,做客户端(从机)实现网口TCP-Modbus通信。

另:本人首次使用,也是结合网上多个大佬的经验做的,有不足的地方请大家指正,内容比较详细,对像我一样的新手比较友好,如果觉得过细可跳着看!!!

一、STM32Cubemx配置
1、选择STM32F407ZET7芯片创建工程,首先配置RCC、SYS和时钟,配置界面如下(根据自己情况配置就好)

466366164b7621534.png

1071266164b7c14a10.png

1049766164b83b38ad.png

 楼主| 慢醇 发表于 2024-4-10 16:20 | 显示全部楼层
配置ETH,参数默认即可,配置界面如下(我的的引脚有调整,是根据实际电路调整的,大家根据自己情况调整即可)

151466164ba934bf2.png

我配置了一个GPIO_Output作为复位引脚,(低电平复位、默认为高电平)

7878866164bb463d6b.png
 楼主| 慢醇 发表于 2024-4-10 16:20 | 显示全部楼层
配LWIP,我使用的静态IP,配置界面如下

2727966164bcbd501e.png

选LAN8742就可以

7483366164bd2e6bef.png
 楼主| 慢醇 发表于 2024-4-10 16:21 | 显示全部楼层
配置串口,有需要的话方便看数据,配置界面如下
5284366164bf21a8f0.png
 楼主| 慢醇 发表于 2024-4-10 16:21 | 显示全部楼层
到此CubeMX就配置完成可以生成代码了(根据自己用的软件改一下设置即可)
5594666164c070f54b.png

8479466164c0d30495.png
 楼主| 慢醇 发表于 2024-4-10 16:22 | 显示全部楼层
修改程序、移植FreeModbus源码
1、先复位一下芯片(不写也没啥问题)
9480966164c26ae711.png
930066164c2bda461.png
5033166164c320c78a.png
 楼主| 慢醇 发表于 2024-4-10 16:22 | 显示全部楼层
到目前为止,已经初始化完成了,在cmd中可以ping通!!!!!!


5450566164c446098e.png

(设备IP为:192.168.1.10 电脑IP为:192.168.1.200 子网掩码:255.255.255.0 默认网关:192.168.1.1 注意:复位引脚我默认放在了低电平(一直复位状态),根据自己需要将复位引脚电平拉高或者配置一下Cubemx默认放在高电平即可)
 楼主| 慢醇 发表于 2024-4-10 16:23 | 显示全部楼层
FreeModbus源码下载

3808166164c5e58c02.png

下载链接放在下面了,自己下载就可以了!
FreeModbus源码下载链接
icon-default.png?t=N7T8https://www.embedded-experts.at/en/freemodbus-downloads/
 楼主| 慢醇 发表于 2024-4-10 16:23 | 显示全部楼层
移植FreeModbus源码
①在工程文件目录下新建一个 FreeModbus_TCP 文件夹,将需要的文件都移植到该文件夹下
②打开 freemodbus-v1.6 文件夹,点击 modbus 文件夹,将modbus 文件夹中的全部文件移植到新建的 FreeModbus_TCP 文件夹中

2451866164c7e8473f.png
 楼主| 慢醇 发表于 2024-4-10 16:23 | 显示全部楼层
③将freemodbus-v1.6\demo\STR71XTCP中的 port 文件,移植到新建的 FreeModbus_TCP 文件夹中

7808466164c8dd91df.png
 楼主| 慢醇 发表于 2024-4-10 16:24 | 显示全部楼层
④新建的 FreeModbus_TCP 文件夹内容移植最终结果如下:下面的两个文件目前还没有!!

6354766164c9e64e8f.png
 楼主| 慢醇 发表于 2024-4-10 16:24 | 显示全部楼层
⑤导入到工程中
将FreeModbus_TCP 文件夹中的文件导入

选择FreeModbus_TCP 文件夹中的mb.c文件

选择FreeModbus_TCP 文件夹中的 functions 文件夹、 port 文件夹、tcp 文件夹的全部.c文件

结果如下图所示(目前最后一个文件还没有!)

8186066164cb253471.png
 楼主| 慢醇 发表于 2024-4-10 16:24 | 显示全部楼层
⑥点击魔法棒,选择 C/C++,添加文件路径

9543366164cc0baf11.png

5734266164cc8f0c42.png
 楼主| 慢醇 发表于 2024-4-10 16:25 | 显示全部楼层
编辑程序
7240966164cdfa88c3.png

5897766164ce6836ee.png
 楼主| 慢醇 发表于 2024-4-10 16:25 | 显示全部楼层
找不到这个文件在哪的可以在mb.c的头文件中跳转打开!!后面找不到的也一样!

9838366164cf65ea75.png
 楼主| 慢醇 发表于 2024-4-10 16:25 | 显示全部楼层
修改 portevent.c将以下程序,替换原来的程序
  1. /* ----------------------- Modbus includes ----------------------------------*/
  2. #include "mb.h"
  3. #include "mbport.h"

  4. /* ----------------------- Variables ----------------------------------------*/
  5. static eMBEventType eQueuedEvent;
  6. static BOOL     xEventInQueue;

  7. /* ----------------------- Start implementation -----------------------------*/
  8. BOOL
  9. xMBPortEventInit( void )
  10. {
  11.     xEventInQueue = FALSE;
  12.     return TRUE;
  13. }

  14. BOOL
  15. xMBPortEventPost( eMBEventType eEvent )
  16. {
  17.     xEventInQueue = TRUE;
  18.     eQueuedEvent = eEvent;
  19.     return TRUE;
  20. }

  21. BOOL
  22. xMBPortEventGet( eMBEventType * eEvent )
  23. {
  24.     BOOL            xEventHappened = FALSE;

  25.     if( xEventInQueue )
  26.     {
  27.         *eEvent = eQueuedEvent;
  28.         xEventInQueue = FALSE;
  29.         xEventHappened = TRUE;
  30.     }
  31.     return xEventHappened;
  32. }
 楼主| 慢醇 发表于 2024-4-10 16:26 | 显示全部楼层
添加 #include “string.h”  和  #define NETCONN_COPY 0x01
9279966164d15d4898.png
7884666164d18a87df.png
 楼主| 慢醇 发表于 2024-4-10 16:26 | 显示全部楼层
新建User_modbus_TCP.c文件

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "User_modbus_TCP.h"
  4. #include "mb.h"
  5. #include "mbutils.h"

  6. void ModbusTCPInit(void)
  7. {
  8.     eMBTCPInit(MODBUS_TCP_PORT);
  9.     eMBEnable();
  10. }

  11. void ModbusTCPDeInit(void)
  12. {
  13.     eMBDisable();
  14.     eMBClose();
  15. }

  16. void ModbusTCPMain(void)
  17. {
  18.     if (MB_ENOERR != eMBPoll())
  19.     {
  20.         ModbusTCPDeInit();
  21.         ModbusTCPInit();
  22.     }
  23. }

  24. //线圈
  25. #define REG_Coils_START   1
  26. #define REG_Coils_SIZE    10

  27. uint8_t  Coils_Data[REG_Coils_SIZE] = {1,1,0,1,0,0,1,1,1,0};

  28. /**
  29. * @brief: 读线圈---01,写线圈---05
  30. *
  31. * @param pucRegBuffer  缓存指针
  32. * @param usAddress     起始地址
  33. * @param usNCoils      线圈数量
  34. * @param eMode         读写模式
  35. * [url=home.php?mod=space&uid=266161]@return[/url] eMBErrorCode 错误码
  36. */
  37. eMBErrorCode eMBRegCoilsCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode)
  38. {
  39.     uint16_t i = 0,byteOffset=0,bitOffset=0,RegIndex = usAddress - REG_Coils_START-1;
  40.     if ((usAddress >= REG_Coils_START)&&(usAddress + usNCoils <= REG_Coils_START + REG_Coils_SIZE+1))
  41.     {
  42.         if (MB_REG_READ == eMode)
  43.         {
  44.           for(i=0;i<usNCoils;i++)
  45.           {
  46.               byteOffset = i / 8;
  47.               bitOffset = i % 8;
  48.               xMBUtilSetBits(&pucRegBuffer[byteOffset], bitOffset, 1, Coils_Data[RegIndex+i]);
  49.           }
  50.         }
  51.         else
  52.         {
  53.           for(i=0;i<usNCoils;i++)
  54.           {
  55.               byteOffset = i / 8;
  56.               bitOffset = i % 8;
  57.               Coils_Data[RegIndex+i]=xMBUtilGetBits(&pucRegBuffer[byteOffset], bitOffset, 1);
  58.           }
  59.         }
  60.     }
  61.     else
  62.     {
  63.         return MB_ENOREG;
  64.     }
  65.    
  66.     return MB_ENOERR;
  67. }

  68. //离散寄存器
  69. #define REG_DISCRETE_START   10
  70. #define REG_DISCRETE_SIZE    20

  71. uint8_t  Discrete_Data[REG_DISCRETE_SIZE] = {1,1,0,1,0,0,1,1,1,0,1,0,0,1};

  72. /**
  73. * @brief:读离散寄存器---02
  74. *
  75. * @param pucRegBuffer  缓存指针
  76. * @param usAddress     起始地址
  77. * @param usNDiscrete   寄存器个数
  78. * @return eMBErrorCode 返回错误码
  79. */
  80. eMBErrorCode eMBRegDiscreteCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNDiscrete)
  81. {
  82.     uint16_t i = 0,byteOffset=0,bitOffset=0,RegIndex = usAddress - REG_DISCRETE_START-1;
  83.   
  84.     if ((usAddress >= REG_DISCRETE_START)&&(usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISCRETE_SIZE+1))
  85.     {
  86.       for(i=0;i<usNDiscrete;i++)
  87.       {
  88.           byteOffset = i / 8;
  89.           bitOffset = i % 8;
  90.           xMBUtilSetBits(&pucRegBuffer[byteOffset], bitOffset, 1, Discrete_Data[RegIndex+i]);
  91.       }
  92.     }
  93.     else
  94.     {
  95.         return MB_ENOREG;
  96.     }

  97.     return MB_ENOERR;
  98. }

  99. //保持寄存器
  100. #define REG_HOLDING_REGISTER_START   10
  101. #define REG_HOLDING_REGISTER_SIZE    30

  102. uint16_t  Holding_Data[REG_HOLDING_REGISTER_SIZE] =
  103. {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12};

  104. /**
  105. * @brief: 读保持寄存器---03,写保持寄存器---06
  106. *
  107. * @param pucRegBuffer  缓存指针
  108. * @param usAddress     起始地址
  109. * @param usNRegs       寄存器个数
  110. * @param eMode         读写模式
  111. * @return eMBErrorCode 返回错误码
  112. */

  113. eMBErrorCode eMBRegHoldingCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode)
  114. {
  115.     uint16_t i = 0,RegIndex = usAddress - REG_HOLDING_REGISTER_START-1;
  116.   
  117.     if ((usAddress >= REG_HOLDING_REGISTER_START )&&(usAddress + usNRegs <= REG_HOLDING_REGISTER_START  + REG_HOLDING_REGISTER_SIZE+1))
  118.     {
  119.         if (MB_REG_READ == eMode)//读
  120.         {
  121.           for(i=0;i<usNRegs;i++)
  122.           {
  123.             pucRegBuffer[i*2] = (UCHAR)(Holding_Data[RegIndex+i]>>8);
  124.             pucRegBuffer[i*2+1] = (UCHAR)Holding_Data[RegIndex+i];
  125.           }
  126.         }
  127.         else//写
  128.         {
  129.           for(i=0;i<usNRegs;i++)
  130.           {
  131.             Holding_Data[RegIndex+i]=(pucRegBuffer[i*2]<<8)|(pucRegBuffer[i*2+1]);
  132.           }
  133.         }
  134.     }
  135.     else
  136.     {
  137.         return MB_ENOREG;
  138.     }

  139.     return MB_ENOERR;
  140. }

  141. //输入寄存器
  142. #define REG_INPUT_REGISTER_START    1
  143. #define REG_INPUT_REGISTER_SIZE    20

  144. uint16_t  Input_Data[REG_DISCRETE_SIZE] =
  145. {100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119};
  146. /**
  147. * @brief: 读输入寄存器---04
  148. *
  149. * @param pucRegBuffer  缓存指针
  150. * @param usAddress     起始地址
  151. * @param usNRegs       寄存器个数
  152. * @return eMBErrorCode 返回错误码
  153. */
  154. eMBErrorCode eMBRegInputCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs)
  155. {
  156.     uint16_t i = 0,RegIndex = usAddress - REG_INPUT_REGISTER_START-1;
  157.     if ((usAddress >= REG_INPUT_REGISTER_START)&&(usAddress + usNRegs <= REG_INPUT_REGISTER_START + REG_INPUT_REGISTER_SIZE+1))
  158.     {
  159.         for(i=0;i<usNRegs;i++)
  160.         {
  161.           pucRegBuffer[i*2] = (UCHAR)(Input_Data[RegIndex+i]>>8);
  162.           pucRegBuffer[i*2+1] = (UCHAR)Input_Data[RegIndex+i];
  163.         }
  164.     }
  165.     else
  166.     {
  167.         return MB_ENOREG;
  168.     }
  169.    
  170.     return MB_ENOERR;
  171. }
 楼主| 慢醇 发表于 2024-4-10 16:26 | 显示全部楼层
新建User_modbus_TCP.h文件
  1. #ifndef __User_modbbus_TCP_H__
  2. #define        __User_modbbus_TCP_H__

  3. #include "main.h"

  4. #define MODBUS_TCP_PORT 0         //0代表默认即为502,也可以自己设

  5. extern void ModbusTCPInit(void);
  6. extern void ModbusTCPMain(void);

  7. #endif
 楼主| 慢醇 发表于 2024-4-10 16:26 | 显示全部楼层
主程序中
5506266164d4b14c76.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

134

主题

1382

帖子

6

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