文章目录
- 一、背景
- 二、参考教程与实验材料
-
- [2.1 参考教程](#2.1 参考教程)
- [2.2 实验准备](#2.2 实验准备)
- 三、移植过程
- 四、实验结果
-
- [读取保持寄存器 03](#读取保持寄存器 03)
- [写入保持寄存器 16](#写入保持寄存器 16)
- 五、源码分享
一、背景
在先前已经通过cubemx实现以太网,并且能ping通,现在需要在此基础上移植freemodbus从机程序。
上一期:
【LWIP学习】dp83848与STM32f407re的接线并实现ping通
二、参考教程与实验材料
2.1 参考教程
博客:
基于STM32F767通过STM32CubeMX实现ModbusTCP从站(后续)
教程配套代码:
F7_ModbusTCP
此次移植非常顺利,感谢博主
2.2 实验准备
freemodbus官网或Github链接:FreeModbus源码
三、移植过程
-
确保当前工程能ping通,并且打开了串口
-
将mudbus文件夹放入工程,找到下载包内demo/STR71XTCP/Port文件夹,单独拿出来放到ModbusPort文件夹下。
如图:

-
将之前下载的MosbusPort和modbus内的文件加到工程里,其中需要加的文件有

-
编译之后发现有错,下载教程中给的代码,依照代码进行修改。
按我的回忆,修改了以下内容:
4.1 portevent.c 全部改成了博主的写的
4.2 porttcp.c 注释了vMBPortEventClose( );等函数
4.3 port.h全部改成博主给的
4.4 由于没放入acii和rtu相关文件,会报错找不到函数,把支持给关闭,修改mbconfig.h
所有的修改都可以参考博主给的代码
-
没有使能操作系统,添加在main.c文件添加如下代码

-
添加user_mb_app.c和user_mb_app.h在这里写回调函数,复制博主的ModbusCB.c文件
-
编译成功
-
下载后能ping通

-
使用modbus poll测试,能读取保持寄存器
9.1 modbus poll配置
选择TCP连接,我的stm32配置的ip是192.168.1.111
server port没改,还是502连接后的现象表示能成功读取寄存器,但是不能写保持寄存器

-
完善user_mb_app.c和user_mb_app.h
写入以下代码,可以实现读和写保持寄存器
user_mb_app.c
c
/**
******************************************************************************
* @文件
* @作者
* @版本
* @日期
* @概要
******************************************************************************
* @注意事项
*
*
*
******************************************************************************
*/
/* 头文件 --------------------------------------------------------------*/
#include "mb.h"
#include "user_mb_app.h"
/* 私有数据类型 --------------------------------------------------------------*/
/* 保持寄存器缓冲区 */
USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS];
/* 私有定义 --------------------------------------------------------------*/
/* 私有宏定义 --------------------------------------------------------------*/
/* 私有变量 --------------------------------------------------------------*/
/* 私有函数声明 --------------------------------------------------------------*/
/**
* @功能
* @参数
* @返回值
*/
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
return eStatus;
}
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int i=0;
USHORT usRegValue;
/* 检查地址范围 */
if( (usAddress < 1) || (usAddress + usNRegs > S_REG_HOLDING_NREGS + 1) )
{
return MB_ENOREG; // 地址超出范围
}
if( eMode == MB_REG_READ )
{
/* 读取模式:将寄存器值写入缓冲区(大端字节序) */
for(i=0; i<usNRegs; i++)
{
*pucRegBuffer = usSRegHoldBuf[i+usAddress-1] >> 8; // 高字节
pucRegBuffer++;
*pucRegBuffer = usSRegHoldBuf[i+usAddress-1] & 0xff; // 低字节
pucRegBuffer++;
}
}
else if( eMode == MB_REG_WRITE )
{
/* 写入模式:从缓冲区读取数据并写入寄存器(大端字节序) */
for(i=0; i<usNRegs; i++)
{
// 从缓冲区读取大端字节序数据
usRegValue = (*pucRegBuffer << 8); // 高字节
pucRegBuffer++;
usRegValue |= (*pucRegBuffer & 0xff); // 低字节
pucRegBuffer++;
// 写入到寄存器数组
usSRegHoldBuf[i+usAddress-1] = usRegValue;
}
}
else
{
eStatus = MB_EINVAL; // 无效的模式
}
return eStatus;
}
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
return MB_ENOREG;
}
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
return MB_ENOREG;
}
/**
* @}
*/
/*******************文件结尾**************************************************/
user_mb_app.h
c
#ifndef USER_MB_APP_H
#define USER_MB_APP_H
/* 保持寄存器数量定义 */
#define S_REG_HOLDING_NREGS 400
#endif /* USER_MB_APP_H */
四、实验结果
读取保持寄存器 03

写入保持寄存器 16
