Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Modbus
《内核学习营》+水一方+modbus_RTU主机实验
发布于 2018-09-18 22:54:43 浏览:4986
订阅该版
* 本帖最后由 吉帅虎 于 2018-9-19 09:39 编辑 * 本帖接上一帖,《内核学习营》+水一方+modbus_RTU从机实验。[https://www.rt-thread.org/qa/for ... 032&page=1#pid38019](https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=8032&page=1#pid38019) RTT组件里的Freemodbus可以同时支持modbus_RTU主机和从机协议,但要注意需要使用两个不同的串口。在实际应用中,一般不会出现一个串口同时需要支持modbus从机又modbus主机的时候。反正我没有见过。有这种需求的童鞋们可以提出来。 本帖感谢前辈[align=center][armink](https://www.rt-thread.org/qa/space-uid-6104.html)做出的指导。[https://www.rt-thread.org/qa/for ... s%E4%B8%BB%E6%9C%BA](https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=3145&highlight=modbus%E4%B8%BB%E6%9C%BA) ********************************************************************************************* 硬件:自用STM32F103VCT6板卡 实验目的:实现Modbus_RTU主机协议 扩展功能:1、使用env配置modbus_RTU主机工程 2、完成modbus_RTU主机功能的测试 软件平台:env_released_1.0.0 ,mdk5.25 ********************************************************************************************* 上一个帖子里提到了,在Freemodbus代码里面带_m的文件是执行modbus主机协议相关的文件,不带_m的是从机协议相关的文件。从机协议调通后,主机也很简单。但是不同的是主机需要调用eMBMasterInit( MB_RTU, 0x04, 9600, MB_PAR_NONE );eMBMasterEnable();eMBMasterPoll();三个函数。另外与从机协议不同的是modbus从机只需要被动的接收主机的指令,做出相应的相应即可。而主机则需要定时或者根据某个外部条件触发一次读或者写操作。我在调试过程中只使用了写单个保持寄存器一个指定,并且是定时发送。其实指令暂未测试。 主机初始化代码如下: ``` static void mbmaster_thread_entry(void *parameter) { // rt_uint8_t buff[3]; #if defined(RTU_MSATER_USING_USART1) eMBMasterInit( MB_RTU, 0x01, 9600, MB_PAR_NONE ); //初始化 #endif #if defined(RTU_MSATER_USING_USART2) eMBMasterInit( MB_RTU, 0x02, 9600, MB_PAR_NONE ); //初始化 #endif #if defined(RTU_MSATER_USING_USART3) eMBMasterInit( MB_RTU, 0x03, 9600, MB_PAR_NONE ); //初始化 #endif #if defined(RTU_MSATER_USING_USART4) eMBMasterInit( MB_RTU, 0x04, 9600, MB_PAR_NONE ); //初始化 #endif eMBMasterEnable(); //使能 for(;;) { //eMBMasterRegInputCB(buff,0x01,2); // Call the main polling loop of the Modbus protocol stack. eMBMasterPoll(); // rt_thread_delay(RT_TICK_PER_SECOND); } } ``` 测试代码,测试代码中列出了常用的指令。我在[align=center][armink](https://www.rt-thread.org/qa/space-uid-6104.html)代码的基础上做了一些注释,希望对后来者有些帮助。不过其中0x17(23)指令我从来没有用过,不过看着对于大量数据的读写应该比较简单。 ``` ALIGN(RT_ALIGN_SIZE) static rt_uint8_t SysMonitor_stack[ 512 ]; /* 线程的TCB控制块 ,句柄*/ static struct rt_thread SysMonitor_thread; void thread_entry_SysMonitor(void* parameter) { eMBMasterReqErrCode errorCode = MB_MRE_NO_ERR; uint16_t errorCount = 0; uint16_t Count = 0; while (1) { Count++; rt_thread_delay(RT_TICK_PER_SECOND); //01,0x01,读线圈状态************************************************************************ //参数:从机地址;线圈起始地址;线圈个数;超时时间 //errorCode = eMBMasterReqReadCoils(1,3,8,RT_WAITING_FOREVER); //02,0x02,读离散输入寄存器**************************************************************** //参数:从机地址;离散输入寄存器起始地址;寄存器个数;超时时间 //errorCode = eMBMasterReqReadDiscreteInputs(1,3,8,RT_WAITING_FOREVER); //03,0x03,读保持寄存器,即读参数************************************************************** //参数:从机地址;保持寄存器起始地址;寄存器个数;超时时间 //errorCode = eMBMasterReqReadHoldingRegister(1,3,2,RT_WAITING_FOREVER); //04,0x04,读输入寄存器********************************************************************** //参数:从机地址;输入寄存器起始地址;寄存器个数;超时时间 //errorCode = eMBMasterReqReadInputRegister(1,3,2,RT_WAITING_FOREVER); //05,0x05,写单个线圈(继电器)********************************************************************* //参数:从机地址;线圈地址;线圈状态(0xFF00表示线圈ON,0x0000表示线圈OFF);超时时间 //errorCode = eMBMasterReqWriteCoil(1,1,0xFF00,RT_WAITING_FOREVER); //15,0x0F,写多个线圈(继电器)******************************************************************** //参数:从机地址;线圈起始地址;线圈个数;线圈状态(对应bit为1表示线圈ON,对应bit为0表示线圈OFF)指针;超时时间 //errorCode = eMBMasterReqWriteMultipleCoils(1,3,5,ucModbusUserData,RT_WAITING_FOREVER); //06,0x06,修改单个保持寄存器,即写单个参数**************************************************** //参数:从机地址;保持寄存器地址;修改后的寄存器值;超时时间 errorCode = eMBMasterReqWriteHoldingRegister(1,3,Count,RT_WAITING_FOREVER); //16,0x10,修改单个保持寄存器,即写多个参数**************************************************** //参数:从机地址;保持寄存器起始地址;寄存器个数;要修改的寄存器值指针;超时时间 //errorCode = eMBMasterReqWriteMultipleHoldingRegister(1,3,2,usModbusUserData,RT_WAITING_FOREVER); //23,0x17,读写多个寄存器,不常用********************************************************************* //参数:从机地址;读寄存器起始地址;读寄存器个数;写寄存器的数据指针;写寄存器起始地址;写寄存器个数;超时时间 //errorCode = eMBMasterReqReadWriteMultipleHoldingRegister(1,3,2,usModbusUserData,5,2,RT_WAITING_FOREVER); //记录出错次数 if (errorCode != MB_MRE_NO_ERR) { errorCount++; } } }``` 根据上述代码、每秒钟会修改一次Count的值,并使用0x06指令写到寄存器3(从0开始)中,使用Modbus Slave软件进行测试,结果如下: ![TIM图片20180918224305.png](/uploads/201809/18/224332eygzlyunfgollacu.png) 串口监视软件监视到的数据如下: ![TIM图片20180918224349.png](/uploads/201809/18/224422bwm738h2skgisese.png) 至此基本可以认为modbus主机代码移植成功,具体的应用要在thread_entry_SysMonitor线程中根据实际情况确定。 在实际使用中,针对具体的功能,一般可能会根据实际板卡修改不同的串口号。为此,我在env的menuconfig菜单中进行了修改。可以通过env配置modbus主机和从机使用的串口 ![TIM图片20180918224710.png](/uploads/201809/18/224800ypyj43gbyb5szmfz.png)![TIM图片20180918224727.png](/uploads/201809/18/224800lr7l9mib7pilxyy2.png) 相应的Kconfig路径为如下 ![TIM图片20180918224907.png](/uploads/201809/18/224955x0a0z1esrl2ilp1p.png) 对应的文件修改为如下: ``` config RT_USING_MODBUS bool "Enable Modbus stack" default n if RT_USING_MODBUS config RT_MODBUS_MASTER_RTU bool "RTU master mode" default n choice prompt "RTU master Port" default RTU_MSATER_USING_USART1 config RTU_MSATER_USING_USART1 bool "USART1" config RTU_MSATER_USING_USART2 bool "USART2" config RTU_MSATER_USING_USART3 bool "USART3" config RTU_MSATER_USING_USART4 bool "USART4" endchoice config RT_MODBUS_SLAVE_RTU bool "RTU slave mode" default n choice prompt "RTU slave Port" default RTU_SLAVE_USING_USART1 config RTU_SLAVE_USING_USART1 bool "USART1" config RTU_SLAVE_USING_USART2 bool "USART2" config RTU_SLAVE_USING_USART3 bool "USART3" config RTU_SLAVE_USING_USART4 bool "USART4" endchoice if RT_MODBUS_SLAVE_RTU config RT_MODBUS_SLAVE_USE_CONTROL_PIN bool "Use Contorl Pin" default n if RT_MODBUS_SLAVE_USE_CONTROL_PIN config MODBUS_SLAVE_RT_CONTROL_PIN_INDEX int "pin index for RS485 TX/RX select" default 10 endif endif endif endmenu ``` 对于串口的选择,见上面的初始化代码。此配置只选择modbus主机或者从机使用的串口号,相应的串口还需要在env中使用menuconfig命令使能。 再一点就是使用485通讯时的收发控制管脚选择,env中只有一个从机的控制管脚选项。但是在主机上应该也有一个对应的控制管脚。这一点我还没有仔细看,实际使用的时候需要加上。这也算是后续优化空间吧。有做这个实验的朋友也可以一块改一下。 ![TIM图片20180918225218.png](/uploads/201809/18/225411dn5w1nozw5aln57b.png) 另外分享一个modbus和Freemodbus相关的资料以供大家学习 ![Modbus协议中文版【完整版】.pdf](/uploads/201809/18/225741wcfqacq9acve0i8t.attach) ![Freemodbus完全分析.pdf](/uploads/201809/18/225740qu81wtsz1tlxvtuv.attach)
查看更多
7
个回答
默认排序
按发布时间排序
hyz_rtt
2018-09-25
这家伙很懒,什么也没写!
可以分享下modbus slave软件嘛,谢谢
hyz_rtt
2018-09-26
这家伙很懒,什么也没写!
点赞,注释很好,对于串口增加了宏定义选择
吉帅虎
2018-10-12
这家伙很懒,什么也没写!
[attach]6472[/attach] Modbus主机调试软件
armxu
2018-11-23
这家伙很懒,什么也没写!
//04,0x04,读输入寄存器********************************************************************** freemodbus 主站 //参数:从机地址;输入寄存器起始地址;寄存器个数;超时时间 errorCode = eMBMasterReqReadInputRegister(1,2,2,RT_WAITING_FOREVER); 问题是如何读取从站返回的数据?用哪个函数?
MTYGH
2019-02-14
这家伙很懒,什么也没写!
>//04,0x04,读输入寄存器********************************************************************** >freem ... --- 您好,请问您怎么获取到从机返回的数据的呢?我看过git上的源码和教程,但是打出来里面的数据为空
cyz13
2019-08-14
这家伙很懒,什么也没写!
您好,请问如果是两个不同的串口都是freemodbus主机模式,那这个函数//errorCode = eMBMasterReqReadHoldingRegister(1,3,2,RT_WAITING_FOREVER);怎么判断是哪个主机读取从机的寄存器呢?
hsrock
2019-08-20
这家伙很懒,什么也没写!
这个不错,最近正在研究这个,感谢分享
撰写答案
登录
注册新账号
关注者
0
被浏览
5k
关于作者
吉帅虎
这家伙很懒,什么也没写!
提问
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
在用clangd开发RTT吗,快来试试如何简单获得清晰干净的工作区
2
GD32F450 片内 flash驱动适配
3
STM32H7R7运行CherryUSB
4
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
5
使用RC522软件包驱动FM1722
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
6
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部