基于STM32F767通过STM32CubeMX实现ModbusTCP从站(后续)

本文详细介绍如何在STM32F767上通过STM32CubeMX和FreeModbus库实现ModbusTCP协议,重点解决移植过程中的常见问题,包括避免源码死循环和成功实现读多寄存器功能。

基于STM32F767通过STM32CubeMX实现ModbusTCP读多为寄存器操作(后续)

由于上篇着重介绍了实现功能的代码,以至于我没有和大家讲清楚FreeModbus应该怎么移植,在此先抱歉浪费大家时间了。
接下来我要开始实操怎么成功移植Freemodbus在STM32上(以下方法可以满足所有STM32设备)

实验准备:去FreeModbus官网下载Modbus的源码包,链接直接放上:Freemodbus官网
懒人直接点击Github链接:FreeModbus源码

3、很多人移植这个modbus时出现了加上modbus相关代码时就ping不同的情况,其实是在modbus源码中出现了死循环,如下所示处:
在这里插入图片描述
我的解决方案是使能串口后添加printf函数打印串口的代码在串口文件中,这个死循环即可跳出。
之后就能成功ping通板子,操作modbus了

以下是具体操作:

一、实验步骤

1、找到下载包内demo/STR71XTCP/Port文件夹,单独拿出来放到ModbusPort文件夹下。

2、找到下载包内modbus文件夹拿出来,放到可以ping通的STM32项目里,如图:
在这里插入图片描述
3、打开STM32CubeMX,创建项目,使能LWIP和ETH和串口下载到开发板,并保证可以ping通
一定要串口一定要串口一定要串口,保证mosbus源码不会死循环
在这里插入图片描述
在这里插入图片描述
4、添加串口的目的是让文章开头所说的地方的printf函数有输出的地方,使Mosbus不会因为死循环导致循序卡死
所以我们需要在串口程序部分添加串口用printf函数输出的功能代码

/* USER CODE BEGIN 0 */
/******************printf函数*********************/
#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}
/*************************************************/
/* USER CODE END 0 */

5、将之前下载的MosbusPort和modbus内的文件加到工程里,其中需要加的文件有
在这里插入图片描述
6、点击目标选项
在这里插入图片描述
7、在选项卡C/C++下的包含路径添加modbus相关头文件所在路径
在这里插入图片描述
添加完成后有两种情况,需要添加如下代码

eMBTCPInit( 0 );		//初始化ModbusTCP
eMBEnable();			//使能Modbus

eMBPoll();				//轮询Modbus(该条添加在主循环中)

A.使用了操作系统,则在freertos.c文件下添加如下代码
在这里插入图片描述
B.没有使能操作系统,添加在main.c文件添加如下代码
在这里插入图片描述
8、新建ModbusCB.c文件,放在Modbus目录下,实现各个功能,这里只实现的保持寄存器功能(博主是懒狗,其他请大家照葫芦画瓢)


#include "mb.h"
uint16_t R[15];
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
	static uint8_t flag = 0;
	
//	flag == 0 ? GPIO_SetBits(GPIOC,GPIO_PIN_1) : GPIO_ResetBits(GPIOC,GPIO_PIN_1);  //modify by alan
	flag==0 ? HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	flag ^= 1;
    return eStatus;
}

eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
	eMBErrorCode    eStatus = MB_ENOERR;
	static uint8_t flag = 0;
	int i=0;
	//flag == 0 ? GPIO_SetBits(GPIOC,GPIO_PIN_2) : GPIO_ResetBits(GPIOC,GPIO_PIN_2);  //modify by alan
	flag==0 ? HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	flag ^= 1;
	/*the following code is just for the testing the function of reading register
	 author: Alan
	*/
	R[0]=56;
	R[1]=78;
	R[2]=12;
	R[3]=34;
	for(i=0;i<usNRegs;i++)
	{
	*pucRegBuffer=R[i+usAddress-1]>>8;
	pucRegBuffer++;
	*pucRegBuffer=R[i+usAddress-1]&0xff;
	pucRegBuffer++;
	}
    return eStatus;
}

eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
    static uint8_t flag = 0;
	
	//flag == 0 ? GPIO_SetBits(GPIOC,GPIO_PIN_3) : GPIO_ResetBits(GPIOC,GPIO_PIN_6);  //modify by alan
	flag==0 ? HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
	flag ^= 1;
	return MB_ENOREG;
}

eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    static uint8_t flag = 0;
	
	//flag == 0 ? GPIO_SetBits(GPIOC,GPIO_PIN_4) : GPIO_ResetBits(GPIOC,GPIO_PIN_7);  //modify by alan
	flag==0 ? HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
	flag ^= 1;
	return MB_ENOREG;
}

此时程序基本完成,编译下载

二、实验结果

1.下载完成后先测试能不能ping通,得到下图即可

在这里插入图片描述

2.打开任何可以使用的mosbus测试工具,注意,本次实验为从站设计,所以测试工具设置为主站

填写好开发板IP地址和端口号
在这里插入图片描述
点击连接,等下方出现连接成功提示
在这里插入图片描述
点击读保持寄存器(功能码03)得到如下效果
在这里插入图片描述
如上图,根据ModbusBC.c中设置的R[0]~R[4]的内容分别为56,78,12,34,读取后内存相应位置也变成了对应的数字,实验成功

接下来分析一下发送和返回报文,由图可知

发送报文TX:00 00 00 00 00 06 01 03 00 00 00 10

前6位位MBAP报文头:00(Hi) 00(Lo) 00 00(协议标识,0000为使能modbus) 00 06(报文长度6位)

后6位为modbus报文:01(从机地址) 03(功能码) 00 00(起始地址) 00 10(寄存器数量)
由上图可知,我设定的起始地址为0,长度为16,该数字为10进制,报文内为16进制,所以长度为十进制的16就变为十六进制的10.

接收报文RX:00 00 00 00 00 23 01 03 20 00 38 00 4e 00 0c 00 22 00 00 00 00…

前6位位MBAP报文头:00(Hi) 00(Lo) 00 00(协议标识,0000为使能modbus) 00 23(报文长度23位)

后为modbus报文:01(从机地址) 03(功能码) 20(寄存器内容长度) 00 38(等于十进制的56)00 4e(等于十进制的78) 00 0c(等于十进制的12) 00 22(等于十进制的34) 00 00 00 00 00
之后全为00,表示其他寄存器值为0

实验结束,打完收工!!!!

										Good Game!!!!!!

以上内容欢迎大家转载引用,标明出处即可!!!!!

课程背景Modbus 协议是工业自动化控制系统中常见的通信协议,协议的全面理解是个痛点。本课程主讲老师集10多年在Modbus协议学习、使用中的经验心得,结合当前物联网浪潮下Modbus协议开发的痛点,推出这套面向Modbus 协议初学者的课程。本课程不同于以往市面课程只是协议讲解无实现代码,而是采用讲解与实践并重的方式,结合STM32F103ZET6开发板进行手把手编程实践,十分有利于初学者学习。涵盖了学习者在Modbus协议方面会遇到的方方面面的问题,是目前全网首个对Modbus协议进行全面总结的课程。课程名称   协议讲解及实现>>课程内容1、Modbus 协议的基础。2、Modbus协议栈函数编程实现。3、Modbus协议在串行链路编程实现。4、Modbus协议在以太网链路编程实现。5、常见问题的解决方法。带给您的价值通过学习本课程,您可以做到如下:1、全面彻底的理解Modbus协议。2、理解在串行链路,以太网链路的实现。3、掌握Modbus协议解析的函数编程方法,调试工具的使用。4、掌握多个串口,网口同时运行同一个Modbus协议栈的方法。5、掌握Modbus协议下,负数,浮点数等处理方法。讲师简介许孝刚,山东大学工程硕士,副高职称,技术总监。10多年丰富嵌入式系统开发经验,国家软考“嵌入式系统设计师”。2017年获得“华为开发者社区杰出贡献者”奖励。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值