Giter Site home page Giter Site logo

armink / freemodbus_slave-master-rtt-stm32 Goto Github PK

View Code? Open in Web Editor NEW
1.5K 165.0 806.0 2.83 MB

Add master mode to FreeModbus. | 在 FreeModbus 中添加主机模式

License: Other

C 57.12% C++ 29.82% HTML 2.29% Assembly 10.52% Python 0.18% Objective-C 0.01% Batchfile 0.02% Pawn 0.03%
modbus master freemodbus

freemodbus_slave-master-rtt-stm32's People

Contributors

armink avatar ericqiang avatar guoweilkd avatar mysterywolf avatar podom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

freemodbus_slave-master-rtt-stm32's Issues

增加错误处理接口

目前FreeModbus主机及从机有错误处理的功能,但应该给用户提供相应的回调函数,可添加到port.c中,重写错误处理回调方法。

xMBMasterRTUTransmitFSM函数触发断言

原代码如下:
vMBMasterPortSerialEnable( TRUE, FALSE );
eSndState = STATE_M_TX_XFWR;
这种情况会在接收函数xMBMasterRTUReceiveFSM()触发断言
RT_ASSERT(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR ));

修改如下解决:
eSndState = STATE_M_TX_XFWR;
vMBMasterPortSerialEnable( TRUE, FALSE );
//eSndState = STATE_M_TX_XFWR;

问题原因是状态更新不及时,接收中断触发了,变量状态还没有更新,所以还要提前
不过我不知道原作者和其他用户是否遇到这种问题,所以抛砖引玉,armink看到也请分析一下,谢谢

缓冲区开关

目前协议栈自身带带缓冲区,需要耗费一定的RAM空间,保证了数据被集中管理,再配合我的数据管理模块,还能实现事件通知功能,使得整个软件实现数据驱动的模式。
这种方式虽然有诸多的好处,但是有些用户可能由于硬件资源的限制,可能会放弃协议栈自定义的缓冲区,这样就需要在某些API接口上稍做调整。同时增加缓冲区开关,使得协议栈支持,开启和不开启的缓冲区的两种模式。

超时函数,跑飞

移植到rtt,单步运行到那个判断超时的函数,就停了,跑飞了

Response shifted in ucMasterRTURcvBuf

the problem is triggered following these steps:
1.1 - Plug the USB RS485 interface and run a modbus server script in PC side (uModbus "python")
1.2 - Request reading coils every 3 seconds (Freemodbus running on Atmel SAMDJ17A)
1.3 - Close the script and re-open it on the first read retry after the timeout

So what actually happens here :
Script response is shifted on the ucMasterRTURcvBuf buffer so the response is always incorrect thus read coil timeout
yet the response is not shifted on the USART circular fifo buffer.

关于Master使用方式疑问

首先非常感谢您能开源代码供大家学习。本人菜鸟一枚,有一问题想问,运行master程序的话是不是必须要单独开一个任务(线程)运行eMBMasterPoll,然后在其他任务里执行具体的控制命令?这样做是不是太过麻烦了,我公司有一个大牛自己写的modbus协议,用的ucos2,运行主机时不需要单独建立任务,直接使用控制函数就好,好像是用信号量做的,你的这个是不是也可以这样做。

主机广播写数据时,未更新缓冲区数据

目前FreeModbus主机虽然已经实现,但是如果主机通过广播写数据到从机,从机在主机的缓冲区中的数据目前是未更新。这样的做法看似有些不妥,后期要想办法解决这个问题。
目前的解决方法是,在主机广播发送完成后,轮训读取所有从机此地址的数据,被动更新主机的缓冲区。

Implementing freemodbus slave

Hi Mr.
It's a long time I'm involved in implementing freemodbus on stm32 and still I couldn't do it.
My micro is stm32f103vet6 and want to use UART1 (port A9 , A10) for modbus and use CubeMX, Keil5 and freeRTOS for configuration.
By the way, I want to use modbus slave, RTU / ASCII and just want to read holding registers from micro.
Would you plase, tell me what should I do?
I have followed the instructions in this website:
http://blog.naver.com/eziya76/220970378890
But, when testing with 'Modbus Poll', the 'Time out error' occurs.
Also, I read the 'Read me' from yours and the description inside code and parts of documements of freemodbus, but !!!!!....
This is very important for me, I really appreciate if you help me.
Thank you...

为何还有modbus地址+1和-1(usAddress--; and usRegAddress++;)?

我觉得freemodbus官方末代版本v1.5里,如mbfunccoils.c/line161的 usRegAddress++; 属于莫名其妙的操作, 似乎并没有搞清楚设备地址与通讯地址的关系, 那个usRegAddress++;应当删除,不少人在移植从机版本的时候,把这一系列usRegAddress++;全都删除。 这个++操作应当在应用层里实现,而且不是加1,应当是加1,10001,30001,or 40001.

设备地址 Modbus通讯地址
00001...09999数字量输出 设备地址-00001
10001...19999数字量输入 设备地址-10001
30001...39999输入寄存器 设备地址-30001
40001...49999保持寄存器 设备地址-40001

How to read holding register from slave (the micro is in slave mode)

Hi.
How are you? It’s me again!!!
In slave mode implementation, I want to define 10 registers in the program, so master reads the registers. The registers are not constant, they are registers of ADC channels.
For now, I want to define one constant register, and read it by master. I tried and wrote some codes, but didn’t work.
After that, I think it’s easy to make it ten, and replace the constant register with registers of ADC.
Many thanks….

请问是否有裸机版本的portevent的实现方法?

非常感谢,开源这么实用的modbus master代码。

想请问一下,有实现过裸机下的portevent接口吗?我现在基于这个代码,移植了串口和定时器部分,也参考了slave的event实现方法,能够正常读写从机的寄存器。不过有一个问题:如果调用两次eMBMasterReqWriteHoldingRegister连续写两个寄存器,从modbus slave软件上只能接收到第二次写的数据。我怀疑是和event队列的实现有关系。所以想问问您有没有参考。非常感谢!

errorCode = eMBMasterReqWriteHoldingRegister(MB_SLAVE_ADDR, 0, usModbusUserData[0], 0x100);
HAL_Delay(500);
errorCode = eMBMasterReqWriteHoldingRegister(MB_SLAVE_ADDR, 1, usModbusUserData[1], 0x100);

Modbus-Master错误提出,疑问,建议

库版本:2020-5-11版

错误提出:

  1. vMBMasterCBRequestScuuess函数单词错误success
  2. mb_m.c中没有实现eMBMasterRegisterCB函数

疑问:

  1. 根据Modbus协议规范,主机广播后,从机不用应答; 而在eMBMasterPoll函数中的case EV_MASTER_EXECUTE分支中为何检测到主机为广播时,要为所有从机地址执行(对应功能码的注册函数)?
  2. vMBMasterSetCBRunInMasterMode和xMBMasterGetCBRunInMasterMode是否仅用于如下情况: 同一功能码对应的同一处理函数被同时注册到了主机库和从机库中,在执行该注册函数时,需要判断主调者的(主机/从机)身份?
  3. xMBMasterRunResTake和xMBMasterRunResRlease函数使用了Semaphore机制,是否仅用于如下情况: 在多个任务同时使用Modbus-Master库时,实现该库资源的锁,保证同一时刻仅有一个任务可以使用Master库

建议:

  1. 应该很少能遇到同一终端同时使用Master和Slave模式吧,是否可以将Master和Slave库分成两个独立的库,这样使用和分析时都更简洁
  2. 我看该版本库使用STM3210x单片机; STM32的UART_Rx_DMA有Idle中断,可以直接接收不定长bytes,同时STM32有UART_Tx_DMA. 因此(xMBMasterPortSerialPutByte/GetByte, xMBRTUReceiveFSM/TransmitFSM状态机)都可不用. 将UART_Tx_DMA和UART_Rx_DMA的buffer都指向ucRTUBuf帧缓冲后. 使能Tx_DMA即可发出帧. 在Rx_DMA中断中发出EV_MASTER_FRAME_RECEIVED事件,就可去驱动eMBMasterPoll处理接收到的帧

[email protected]
thanks

port.c 中 EnterCriticalSection()函数填充错误

port.c中的 EnterCriticalSection()函数和 ExitCriticalSection()函数为何填充的是关/开中断的语句?在接收函数和发送函数中都调用了这两个函数,这对中断的响应实时性有太大的影响了?是否应该更改为关调度,开调度。不过感觉关调度和开调度也不是太好

一个关于自动分配从机地址的问题

对于新手来说您的代码对我熟悉modbus和freemodbus的移植有很大的帮助,先谢谢您对开源的支持与帮助,我现在遇到了一个问题,需要连接多个从机,而跟多个从机分配地址是需要多次改动代码烧录非常麻烦,现在想到可以通过识别stm32的cpuid来区分不同的从机,由主机广播来分配从机的地址,请问freemodbus中对于用户自定义的功能码如何添加,从机初始化需要做出哪些修改,能否提一下您的思路,谢谢。

串口波特率问题

晶振是12M的
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
串口设置为
eMBMasterInit(MB_RTU, 2, 38400, MB_PAR_NONE);
但是实际波特率确是56000

不知道怎么回事

关于sem value初始化为1的问题

你好,请问一下,下面sem_init这里的value设置为了0x01,那么take时就算没有接收到任何数据,也能直接return,也就导致了timeout设置失效。为什么要设置为1,而不是设置为0呢?thx.
void vMBMasterOsResInit( void )
{
rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO);
}

这个什么意思

elif (RT_TICK_PER_SECOND == 10000)||(RT_TICK_PER_SECOND == 100000)||(RT_TICK_PER_SECOND == 100000)

0.1ms 0.01ms 0.001ms? 这样的话少了一个零?

发现了一处BUG

    usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
    usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );

应该是
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );

不止一处

增加主机串口可行么

你好,我现在遇到一个问题,由于硬件原因,同一个modbus网络分成了两个串口,分别连接100地址以下的从站和100以上地址的从站。
软件上如何实现将modbus master同时连接到两个串口?

本工程线程SystemMonitor在调用eMBMasterReqxxx函数前,必须要调用 rt_thread_delay?

仓主,SystemMonitor线程在调用eMBMasterReqxxx函数前,必须要调用 rt_thread_delay吗?我在测试时,遇到的问题时,如果没有调用rt_thread_delay的话,线程就卡死了。不知道仓主有没有测试到这个问题。

仓主回答:
@ericQiang 你要等待 Modbus Poll 线程里面 MB_init 初始化成功,才能调用 modbus 相关的 API。

但目前masterPoll线程优先级最高,不存在MB_init初始化失败的情况。并且,我在初始化SystemMonitor线程时将延时设置为200.但问题依然会复现。仓主可否将你提交的工程中,SystemMonitor线程中的几个与rt_thread_delay屏蔽掉测试一下?
谢谢。

完善主机请求api,增加请求结果反馈

之前的主机请求api,执行完成后,只是把数据送到了协议栈,但是最终执行结果没有直接反馈给用户,想要知道结果得通过协议栈错误处理的回调函数。这样的操作流程非常繁琐,所以考虑优化主机请求api,在返回信息中增加命令执行结果。

How to use library

Hi
Thanks for your open source code. That’s very helpful.
I want to use Modbus/slave (ASCII and RTU) on STM32f103VET6. Actually, I’m new to ARM, and really confused. There is explanation in your code, but I don’t know how to implement the code. I should copy all of the code files to micro or just the files in “FreeModbus”? In main code of project, I should include all of the code files?
In my project, there are ten ADC inputs to micro. The micro should read them and save every ADC channel to one register separately. After that, all of the ten registers should be transmitted over Modbus protocol to PLC. So, in the Modbus code, where should I use registers for transmission?
Thank you very much…

STATE_TX_IDLE 状态更新不及时,可能导致协议栈触发断言

在mbrtu.c -> xMBRTUTransmitFSM 中
case STATE_TX_XMIT:
/* check if we are finished. */
if( usSndBufferCount != 0 )
{
xMBPortSerialPutByte( ( CHAR )pucSndBufferCur );
pucSndBufferCur++; /
next byte in sendbuffer. /
usSndBufferCount--;
}
else
{
xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
/
Disable transmitter. This prevents another transmit buffer
* empty interrupt. /
vMBPortSerialEnable( TRUE, FALSE );
eSndState = STATE_TX_IDLE;
}
break;
应该改成:
case STATE_TX_XMIT:
/
check if we are finished. */
if( usSndBufferCount != 0 )
{
xMBPortSerialPutByte( ( CHAR )pucSndBufferCur );
pucSndBufferCur++; /
next byte in sendbuffer. /
usSndBufferCount--;
}
else
{
xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
/
Disable transmitter. This prevents another transmit buffer
* empty interrupt. */
eSndState = STATE_TX_IDLE;
vMBPortSerialEnable( TRUE, FALSE );
//eSndState = STATE_TX_IDLE;
}
break;

否则会出现的现象为: 当vMBPortSerialEnable( TRUE, FALSE );使能接收中断的一瞬间,硬件出现接收中断,进入中断函数,而此时由于eSndState还未完全置为IDLE会造成,接收中断函数进入assert_failed;

485收发引脚切换处理

if (xRxEnable)
{
    /* enable RX interrupt */
    serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
    /* switch 485 to receive mode */
    rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW);
}

在这里控制485的收发引脚被拉低,485进入接收状态,但是有可能485发送还没有完成,因为我们只是把发送的数据送入发送数据寄存器,并没有检测数据有没有发出去,程序在这直接将485置为接收状态,很可能导致最后一个字节不能发出去。

Pin Connection

Where to connect DE and RE Pin of rs485 converter to stm32f4.
And How to configure it?

Thank you.

多处疑似bug

库主是否实机运行过,在移植的过程中,发现代码有多处bug,如操作holding register时(eMBMasterRegHoldingCB函数)的读写方向

switch (eMode)
{
/* read current register values from the protocol stack. */
case MB_REG_READ:
while (usNRegs > 0)
{
*pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
iRegIndex++;
usNRegs--;
}
break;
/
write current register values with new values from the protocol stack. */
case MB_REG_WRITE:
while (usNRegs > 0)
{
pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
break;
}

modbus tcp wifi

Hello
is there any way to use wifi modbus tcp slave on stm or nxp lpc?

TCP master port

Does anybody have tcp port for master? Because I want to try modbus with lwip,.... slave is working, and master not.

很不错,支持高质量开源!

提一个问题:
从机modbus现成Poll之后为啥还要等1ms,不是已经用了事件来暂停线程了吗?

提一个建议:
从机使能接收的函数那里,你加了一个延时函数,其实可以用查询发送完成标志位:

while (!(USARTx->SR & USART_FLAG_TC));

这样不会浪费时间,也不用调整延时时间。

从机性能测试

操作系统:RTT、UCOS或者裸机
命令:读10个连续保持寄存器
时间:5min
上位机软件:Modbus Poll
硬件平台:STM32F103,主频72M,115200波特率

记录内容:命令请求成功及错误帧总数

没有用到的?

vMBMasterSetCBRunInMasterMode(TRUE);
vMBMasterSetCBRunInMasterMode(FALSE);

这个没有用到?

需要接收到串口数据才会发送命令

第一次执行eMBMasterReqReadInputRegister(1,3,2,RT_WAITING_FOREVER);时不发送命令(远程串口调试助手收不到信息),只有当远程串口调试助手发送东西给FreeModbus-STM32后工作就正常了,这是怎么回事?

How to read from slave?

I'm trying to read registers from the slave. But I can't read anything. With the ReqWrite function or FuncWrite function.

How can I read registers from the slave?

Thank You!

请问PLL锁相环在哪里设置的啊

比如别的程序里面会有以下代码设置时钟和分频

ErrorStatus HSEStartUpStatus;
RCC_DeInit(); /* RCC system reset(for debug purpose) /
RCC_HSEConfig(RCC_HSE_ON); /
Enable HSE /
HSEStartUpStatus = RCC_WaitForHSEStartUp(); /
Wait till HSE is ready */

if(HSEStartUpStatus == SUCCESS)
{
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);   /* Enable Prefetch Buffer */
    FLASH_SetLatency(FLASH_Latency_2);                      /* Flash 2 wait state */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);                        /* HCLK = SYSCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);
    RCC_PCLK1Config(RCC_HCLK_Div1);                         /* PCLK2 = HCLK */
    //        RCC_PCLK1Config(RCC_HCLK_Div2);                         /* PCLK1 = HCLK/2 */
    //注:AHB主要负责外部存储器时钟。APB2负责AD,I/O,高级TIM,串口1
    //  APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6);    /* PLLCLK = 12MHz * 6 = 72 MHz */
    RCC_PLLCmd(ENABLE);                                     /* Enable PLL */

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)      /* Wait till PLL is ready */
    {
    }

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);              /* Select PLL as system clock source */

    while(RCC_GetSYSCLKSource() != 0x08)                    /* Wait till PLL is used as system clock source */
    {
    }
}

请问是否有FreeRTOS版本的例程?

感谢楼主的奉献精神。
RTT版本经过修改IO口,已经跑通。
经过几天的移植,在FreeRTOS上可以编译通过,但是在运行 eMBMasterReqReadHoldingRegister(2,0,1, -1); 时就卡死了,动不了。

不知道楼主是否方便提供FreeRTOS版本的例程?万分感谢。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.