重庆网站推广外包企业,河南便宜网站建设费用,简单网页模板免费下载,石家庄二手房前言
本次实验以 STM32F407VET6 芯片为MCU#xff0c;使用 25MHz 外部时钟源。 以太网PHY层芯片为 LAN8720A#xff0c;移植FreeModbus实现ModbusTCP网口通信。 具体内容参考文章#xff1a;【HAL库】STM32CubeMX开发----STM32F407----ETHLAN8720ALWIP----ping通
本次移植…
前言
本次实验以 STM32F407VET6 芯片为MCU使用 25MHz 外部时钟源。 以太网PHY层芯片为 LAN8720A移植FreeModbus实现ModbusTCP网口通信。 具体内容参考文章【HAL库】STM32CubeMX开发----STM32F407----ETHLAN8720ALWIP----ping通
本次移植FreeModbus中的TCP功能做客户端从机实现网口TCP-Modbus通信。
一、FreeModbus源码下载
FreeModbus源码下载链接https://www.embedded-experts.at/en/freemodbus-downloads/
点击下载
源码压缩包如下 二、移植FreeModbus源码----新建TCP功能文件
本次实验要实现FreeModbus的TCP功能新建一个 FreeModbus_TCP 文件夹将需要的文件都移植具体文件移植如下
步骤1
打开 freemodbus-v1.6 文件夹点击 modbus 文件夹。 步骤2
将modbus 文件夹中的全部文件移植到新建的 FreeModbus_TCP 文件夹中。
步骤3
将freemodbus-v1.6\demo\STR71XTCP中的 port 文件移植到新建的 FreeModbus_TCP 文件夹中。 步骤4
移植最终结果新建的 FreeModbus_TCP 文件夹内容如下 三、移植FreeModbus源码----TCP功能文件 移植 到STM32工程文件中。
本次使用的是能够实现以太网ping通的STM32F407工程。 工程源码STM32F407-ETHLAN8720ALWIP-无操作系统-ping通----程序源码
步骤1
将FreeModbus_TCP 文件夹复制到工程文件中。 步骤2
使用keil5打开工程将FreeModbus_TCP 文件夹中的文件导入。 选择FreeModbus_TCP 文件夹中的 functions 文件夹的全部.c文件。 选择FreeModbus_TCP 文件夹中的 port 文件夹的全部.c文件。 选择FreeModbus_TCP 文件夹中的 tcp 文件夹的全部.c文件。 选择FreeModbus_TCP 文件夹中的mb.c文件。
最终结果如下 步骤3
点击魔法棒选择 C/C添加文件路径。 添加文件路径 添加结果如下 编译程序会出现一些错误下面编辑程序消除错误。
四、移植FreeModbus源码----编辑程序
步骤1修改 mbconfig.h
关闭 MB_ASCII 和 MB_RTU打开 MB_TCP。 步骤2修改 port.h
将27行#include “71x_type.h” 注释掉。 将39行到46行的注释打开。 具体代码如下 步骤3修改 portevent.c
将以下程序替换原来的程序。
/* ----------------------- Modbus includes ----------------------------------*/
#include mb.h
#include mbport.h/* ----------------------- Variables ----------------------------------------*/
static eMBEventType eQueuedEvent;
static BOOL xEventInQueue;/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortEventInit( void )
{xEventInQueue FALSE;return TRUE;
}BOOL
xMBPortEventPost( eMBEventType eEvent )
{xEventInQueue TRUE;eQueuedEvent eEvent;return TRUE;
}BOOL
xMBPortEventGet( eMBEventType * eEvent )
{BOOL xEventHappened FALSE;if( xEventInQueue ){*eEvent eQueuedEvent;xEventInQueue FALSE;xEventHappened TRUE;}return xEventHappened;
}步骤4修改 porttcp.c
在24行添加 #include “string.h”。 在43行添加 #define NETCONN_COPY 0x01。 将120行和135行的 vPortEnterCritical( );注释掉。 将148行的 vMBPortEventClose( ); 注释掉。
步骤5修改 mb.c
将232行的 ENTER_CRITICAL_SECTION( );注释掉。 将261行的 EXIT_CRITICAL_SECTION( );注释掉。 步骤6新建文件
User_modbus_TCP.c文件
#include stdio.h
#include string.h
#include User_modbus_TCP.h
#include mb.h
#include mbutils.hvoid ModbusTCPInit(void)
{eMBTCPInit(MODBUS_TCP_PORT);eMBEnable();
}void ModbusTCPDeInit(void)
{eMBDisable();eMBClose();
}void ModbusTCPMain(void)
{if (MB_ENOERR ! eMBPoll()){ModbusTCPDeInit();ModbusTCPInit();}
}//线圈
#define REG_Coils_START 1
#define REG_Coils_SIZE 10uint8_t Coils_Data[REG_Coils_SIZE] {1,1,0,1,0,0,1,1,1,0};/*** brief: 读线圈---01写线圈---05** param pucRegBuffer 缓存指针* param usAddress 起始地址* param usNCoils 线圈数量* param eMode 读写模式* return eMBErrorCode 错误码*/
eMBErrorCode eMBRegCoilsCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode)
{uint16_t i 0,byteOffset0,bitOffset0,RegIndex usAddress - REG_Coils_START-1;if ((usAddress REG_Coils_START)(usAddress usNCoils REG_Coils_START REG_Coils_SIZE1)){if (MB_REG_READ eMode){for(i0;iusNCoils;i){byteOffset i / 8;bitOffset i % 8;xMBUtilSetBits(pucRegBuffer[byteOffset], bitOffset, 1, Coils_Data[RegIndexi]);}}else{for(i0;iusNCoils;i){byteOffset i / 8;bitOffset i % 8;Coils_Data[RegIndexi]xMBUtilGetBits(pucRegBuffer[byteOffset], bitOffset, 1);}}}else{return MB_ENOREG;}return MB_ENOERR;
}//离散寄存器
#define REG_DISCRETE_START 10
#define REG_DISCRETE_SIZE 20uint8_t Discrete_Data[REG_DISCRETE_SIZE] {1,1,0,1,0,0,1,1,1,0,1,0,0,1};/*** brief:读离散寄存器---02** param pucRegBuffer 缓存指针* param usAddress 起始地址* param usNDiscrete 寄存器个数* return eMBErrorCode 返回错误码*/
eMBErrorCode eMBRegDiscreteCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNDiscrete)
{uint16_t i 0,byteOffset0,bitOffset0,RegIndex usAddress - REG_DISCRETE_START-1;if ((usAddress REG_DISCRETE_START)(usAddress usNDiscrete REG_DISCRETE_START REG_DISCRETE_SIZE1)){for(i0;iusNDiscrete;i){byteOffset i / 8;bitOffset i % 8;xMBUtilSetBits(pucRegBuffer[byteOffset], bitOffset, 1, Discrete_Data[RegIndexi]);}}else{return MB_ENOREG;}return MB_ENOERR;
}//保持寄存器
#define REG_HOLDING_REGISTER_START 10
#define REG_HOLDING_REGISTER_SIZE 30uint16_t Holding_Data[REG_HOLDING_REGISTER_SIZE]
{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12};/*** brief: 读保持寄存器---03写保持寄存器---06** param pucRegBuffer 缓存指针* param usAddress 起始地址* param usNRegs 寄存器个数* param eMode 读写模式* return eMBErrorCode 返回错误码*/eMBErrorCode eMBRegHoldingCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode)
{uint16_t i 0,RegIndex usAddress - REG_HOLDING_REGISTER_START-1;if ((usAddress REG_HOLDING_REGISTER_START )(usAddress usNRegs REG_HOLDING_REGISTER_START REG_HOLDING_REGISTER_SIZE1)){if (MB_REG_READ eMode)//读{for(i0;iusNRegs;i){pucRegBuffer[i*2] (UCHAR)(Holding_Data[RegIndexi]8);pucRegBuffer[i*21] (UCHAR)Holding_Data[RegIndexi];}}else//写{for(i0;iusNRegs;i){Holding_Data[RegIndexi](pucRegBuffer[i*2]8)|(pucRegBuffer[i*21]);}}}else{return MB_ENOREG;}return MB_ENOERR;
}//输入寄存器
#define REG_INPUT_REGISTER_START 1
#define REG_INPUT_REGISTER_SIZE 20uint16_t Input_Data[REG_DISCRETE_SIZE]
{100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119};
/*** brief: 读输入寄存器---04** param pucRegBuffer 缓存指针* param usAddress 起始地址* param usNRegs 寄存器个数* return eMBErrorCode 返回错误码*/
eMBErrorCode eMBRegInputCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs)
{uint16_t i 0,RegIndex usAddress - REG_INPUT_REGISTER_START-1;if ((usAddress REG_INPUT_REGISTER_START)(usAddress usNRegs REG_INPUT_REGISTER_START REG_INPUT_REGISTER_SIZE1)){for(i0;iusNRegs;i){pucRegBuffer[i*2] (UCHAR)(Input_Data[RegIndexi]8);pucRegBuffer[i*21] (UCHAR)Input_Data[RegIndexi];}}else{return MB_ENOREG;}return MB_ENOERR;
}/**********************printf重定向****************************/
//取消ARM的半主机工作模式
#pragma import(__use_no_semihosting)//标准库需要的支持函数
struct __FILE
{ int handle;
};
FILE __stdout;
void _sys_exit(int x) //定义_sys_exit()以避免使用半主机模式
{ x x;
} int fputc(int ch, FILE *f)
{ return ch;
}需要加上printf重定向关于printf重定向的文章不加上程序就会卡死我也不知道什么原因有哪位大神知道可以评论说一下非常感谢。
User_modbus_TCP.h文件
#ifndef __User_modbbus_TCP_H__
#define __User_modbbus_TCP_H__#include main.h#define MODBUS_TCP_PORT 4002extern void ModbusTCPInit(void);
extern void ModbusTCPMain(void);#endif步骤7在主函数中调用ModbusTCP
在主函数初始化中调用 ModbusTCPInit(); 在主函数while运行中调用 ModbusTCPMain(); 五、移植FreeModbus源码----测试验证
使用 Modbus Poll 软件测试 ModbusTCP 功能。 Modbus Poll 软件----下载和安装
步骤1打开Modbus Poll 软件 步骤2打开连接配置窗口配置连接
点击菜单栏Connection-“Connect…”或者按快捷键F3弹出连接配置窗口。 选择 ModbusTCP/IP然后配置IP地址然后选择端口其他时间都是默认值然后点击 OK 。 步骤3配置窗口信息
点击Setup-“Read/Write Definition…”或者按快捷键F8。 设置从机地址功能码起始地址寄存器数量等信息然后点击OK。 步骤4测试结果
功能码 01读取线圈测试结果与程序一致。 功能码 02读取离散寄存器测试结果与程序一致。 功能码 03读取保持寄存器测试结果与程序一致。 功能码 04读取输入寄存器测试结果与程序一致。