Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Modbus
《内核学习营》+水一方+modbus_RTU从机实验
发布于 2018-09-18 14:58:02 浏览:5594
订阅该版
* 本帖最后由 吉帅虎 于 2018-9-18 14:58 编辑 * Modbus是一种工业领域通信协议的标准协议,在工业领域应用特别广泛。我当前的项目中即要用到modbus从机,也要用到modbus主机,使用的RTU模式。 ********************************************************************************************* 硬件:自用STM32F103VCT6板卡 实验目的:实现Modbus_RTU从机协议 扩展功能:1、使用env配置modbus_RTU从机工程 2、完成modbus_RTU功能的测试 软件平台:env_released_1.0.0 ,mdk5.25 ********************************************************************************************* 由于RTT组件里面已经包含了modbus组件。因此只需要使用env的menuconfig命令配置一下即可把freemodbus的代码添加到自己的标准功能里面。如下图 配置完成后,freemodbus的相关代码就添加到了工程中,编译可以直接通过。件下图:  之后添加modbus的初始化代码,即新建线程,初始化modbus需要的硬件和软件配置 ```#include
#include
#include "Define.h" #include "mb.h" #include "mbport.h" #include "mbproto.h" ALIGN(RT_ALIGN_SIZE) static rt_uint8_t mbslave_stack[ 512 ]; /* 线程的TCB控制块 ,句柄*/ static struct rt_thread mbslave_thread; static void mbslave_thread_entry(void *parameter) { eMBInit( MB_RTU, 0x01,0x01, 9600, MB_PAR_NONE ); //初始化 eMBEnable(); //使能 for(;;) { // Call the main polling loop of the Modbus protocol stack. eMBPoll(); } } int mbslave_init(void) { rt_err_t result; /* init led thread */ result = rt_thread_init(&mbslave_thread, "mbslave", mbslave_thread_entry, RT_NULL, (rt_uint8_t *)&mbslave_stack[0], sizeof(mbslave_stack), 5, 100); if (result == RT_EOK) { rt_thread_startup(&mbslave_thread); } return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(mbslave_init, Init Modbus Slave mode); ``` Freemodbus使用上还是比较简单的,使用的时候主要有三个函数。eMBInit( MB_RTU, 0x01,0x01, 9600, MB_PAR_NONE ); 初始化modbus的相关参数,第一个参数是模式,一般串口传输都使用RTU模式,我用的也是RTU模式,还有ASCII模式,据说一般用以太网传输的时候用,我没有用过,也没有见 用过的。第二个参数是modbus从机地址,了解modbus的都知道是什么意思,接下来是串口号,这个算是自定义的参数,1-4表示USART1——USART4,应该是对原来Freemodbus函数进行了适配工作,代码如下: ```#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); #endif /* set serial name */ if (ucPORT == 1) { #if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1) extern struct rt_serial_device serial1; serial = &serial1; #endif } else if (ucPORT == 2) { #if defined(RT_USING_UART2) extern struct rt_serial_device serial2; serial = &serial2; #endif } else if (ucPORT == 3) { #if defined(RT_USING_UART3) extern struct rt_serial_device serial3; serial = &serial3; #endif }``` eMBEnable();函数是使能modbus协议,在这里我决定用“启动”比较合适,调用此函数开始启动modbus协议。接下来的函数就是具体的协议执行过程中eMBPoll();具体功能要在这个函数里面实现。这个函数的具体文件在user_mb_app.c文件里面。 不过接下来的工作有点儿麻烦,不知道是env的配置有问题还是其他原因,添加到工程里面的代码不全,导致出现编译问题。  在modbus.c(自己写的创建modbus线程的函数文件)里添加相应的头文件后,文件依然存在,但是显然并不是大问题,找到函数原型所在的文件,添加到代码中,并添加相应的头文件即可, 最终我使用的freemodbus里的文件如下图。  其中带_m的文件我感觉应该是modbus主机模式下用到的文件,但是还没有 测试,不太确认。 到此为止,文件里正常编译,使用modbus调试助手也可以调试通过,我用的是modscan软件。连接正常后的效果如下图  通过串口监视助手监视数据的传输,见下图  至此说明modbus协议运行正常,切没有丢帧现象。不过我刚开始的时候在modscan上面数据基本正常,但是经常中断链接,监视串口数据发现经常是发送两三帧才能收到一帧回复的数据。经过分析和学习营的网友提示,调高了系统tick,从100调到了1000,并加上了modbus线程的时间片。道理也比较简单,系统tick较低时,可能出现相应数据不及时的现象,导致数据丢失或者堵塞。这一点儿需要详细了解Freemodbus的数据处理机制才能从根本上了解并提出更好的办法。但是我以前自己写的modbus协议不存在这个问题,只要下一条指令不覆盖新的指令,就一定有机会执行,这一点可能需要慢慢去了解,也是本次学习遗留的问题。 细心的网友可能会发现,到这里modbus的modbus的移植其实不难算结束,因为modbus对应的指令并没有和具体的功能对应上,modbus里面读写线圈,读离散输入值,读写保持寄存器,读外部输入寄存器等功能并没有与具体的应用关联上,这些具体功能都要在user_mb_app.c文件里实现。user_mb_app.c里定义了modbus从机所需要的变量,实际使用的时候要根据自己的需求进行修改。我在测试过程中只是用了离散输入值,即开关量的状态。并对应到按键输入上,在我的KR.c文件里的按键状态放到了离散输入值对应的变量里面。实现了使用modbus协议读取按键状态的操作。 ```/*------------------------Slave mode use these variables----------------------*/ //Slave mode:DiscreteInputs variables USHORT usSDiscInStart = S_DISCRETE_INPUT_START; #if S_DISCRETE_INPUT_NDISCRETES%8 UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1]; #else UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ; #endif //Slave mode:Coils variables USHORT usSCoilStart = S_COIL_START; #if S_COIL_NCOILS%8 UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ; #else UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ; #endif //Slave mode:InputRegister variables USHORT usSRegInStart = S_REG_INPUT_START; USHORT usSRegInBuf[S_REG_INPUT_NREGS] ; //Slave mode:HoldingRegister variables USHORT usSRegHoldStart = S_REG_HOLDING_START; USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ; ``` 在最终的应用中,我觉得应该是两个线程间通过通讯实现数据的传递。这个功能将在我最终的demo中实现。
查看更多
4
个回答
默认排序
按发布时间排序
yqiu
2018-09-18
这家伙很懒,什么也没写!
挺好的,写的很清晰。
armink
2018-09-18
这家伙很懒,什么也没写!
写的很全面!
sharp
2018-09-23
这家伙很懒,什么也没写!
很好,觉得很受用
armxu
2018-11-22
这家伙很懒,什么也没写!
请问能共享一下源代码?
撰写答案
登录
注册新账号
关注者
0
被浏览
5.6k
关于作者
吉帅虎
这家伙很懒,什么也没写!
提问
12
回答
12
被采纳
0
关注TA
发私信
相关问题
1
ModbusRTU协议栈漏发送最后一个字节
2
3.0 增加freemodbus,编译不过
3
RT_THREAD上面的串口MODBUSRTU为啥没功能码?
4
关于 freemodbus 里存在的一点问题分享
5
请教如何使用组件里的FreeMODBUS
6
求一个FreeModbus的从机测试程序
7
FreeModbus的从机调试说明(含测试程序)
8
rtt_freemodbus
9
freemodbus怎么配置到uart
10
FreeModeBus从机调试问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
pkgs --upgrade报错SSL未验证问题解决记录
2
CherryUSB STM32 glue 新增初始化
3
在LPC1114上移植 RT-Thread Nano 3.1.5
4
求助can通讯下怎末运用485
5
STM32F407ZGT适配串口V2驱动
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
cubemx
I2C_IIC
UART
ESP8266
WIZnet_W5500
BSP
ota在线升级
PWM
flash
packages_软件包
freemodbus
潘多拉开发板_Pandora
ADC
GD32
定时器
flashDB
编译报错
keil_MDK
socket
中断
rt_mq_消息队列_msg_queue
Debug
ulog
SFUD
msh
C++_cpp
at_device
本月问答贡献
出出啊
1524
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
818
个答案
179
次被采纳
crystal266
555
个答案
162
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
10
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部