ucos中的modbus 怎么能做到实时响应?
做了3个任务, 两个任务采集网口数据Task_TcpClient1( void * p_arg ) Task_TcpClient2( void * p_arg )另一个任务采进行MODBUS 通讯,
把网口的通讯任务优先级设置为5,MODBUS任务优先级设置为4, 网口的数据可以不用实时响应,
但是MODBUS必须实时响应
函数如下
网口采集1
voidTask_TcpClient1( void * p_arg )
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE)
{ //任务体,通常写成一个死循环
ucKLTCPFrame=0x01;
xMBTCPPortSendResponse( ucKLTCPFrame, 12 );
do_tcp_client();
OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); //相对性延时1000个时钟节拍(1s)
}
}
网口采集2
voidTask_TcpClient2( void * p_arg )
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE)
{ //任务体,通常写成一个死循环
ucKLTCPFrame=0x02;
xMBTCPPortSendResponse( ucKLTCPFrame, 12 );
do_tcp_client_1();
OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); //相对性延时1000个时钟节拍(1s)
}
}
MODBUS任务
voidTask_Modbus ( void * p_arg )
{
OS_ERR err;
CPU_SR_ALLOC();
(void)p_arg;
while (DEF_TRUE)
{ //任务体,通常写成一个死循环
if(Uart2_rev_flag == 0x01)
{
Uart2_rev_flag = 0x00;//接收一帧数据标志清零
OS_CRITICAL_ENTER(); //进入临界段,避免串口打印被打断
ParseRecieve();//MOBUS处理函数
GPIO_ResetBits(GPIOA,GPIO_Pin_1);//485接收使能,关闭发送使能
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//允许接收中断
OS_CRITICAL_EXIT(); //退出临界段
}
// OSTimeDlyHMSM(0, 0,0,50,OS_OPT_TIME_HMSM_STRICT,&err); //延时阻塞50ms
// OSSched();
// OSTimeDly ( 10, OS_OPT_TIME_PERIODIC, & err ); //周期性延时5000个时钟节拍(5s)
}
现在现象 modbus任务中 把延时函数 加上 防止的时候 modbus数据 有时候能采集到, 但是 非常慢,有时候发送的数据根本没有接收到
如果把延时函数换成 OSSched(); 任务切换,可以实时响应, 但是,网口的数就采集不到了,请教下各位有啥情况
{:dizzy:} 调试了一天,偶尔一次发送少量的数据,可以事实得到响应,
如果不断发送不同指令的MODBUS指令数据,或一直发送STM32 偶尔能得到相应 ,有时候完全采集不到功能吗指令
想了一天,不断的发送MODBUS 不就是不断的进入中断, 从而使ucos的其他任务轮询不上, 或执行其他任务时候,本身任务进入临界段, 或不允许打断任务
这时候 ,modbus中断发过来的命令就忽略了,
有什么好的办法,能实时接收到 MODBUS 不同的命令并储存到内存中呢 试试DMA传输数据 感觉写法不是很好,既然用上OS了,怎么用标志位来传送信息,你在串口中断中使用信号量来传递数据收到信息,Modbus任务Pend在此信号量上。
从你贴上的代码来看,当前的写法,Modbus任务如果没有延时函数调用,其它比它优先级低的任务没有运行的机会! 一般的流程是使用中断来接收串口的数据并保存在缓冲区内,等收到完整的一帧数据后通过信号量来通知相应的任务来处理此帧数据。一般中断的接收方式不会轻易丢失数据。 electrlife 发表于 2016-6-13 22:13
感觉写法不是很好,既然用上OS了,怎么用标志位来传送信息,你在串口中断中使用信号量来传递数据收到信息, ...
由于刚用UCOS 不算熟悉, 由于MODBUS 中断有2个, 一个是时间判断3.5t一个串口中断, 多了有点不会用
就直接移植 自己编写的MODBUS, modbus中的用红色标志, 是三种方法都试过了, 所以有时间延时, 如果没有掩饰就切换任务了
monkhooder 发表于 2016-6-13 21:58
试试DMA传输数据
谢谢,我也想过,关键是modbus中断处理中, 不能丢数据 有OS就要评估调度延时问题 NJ8888 发表于 2016-6-13 22:42
有OS就要评估调度延时问题
因为网络数据平时变化不大, 所以今天调试时候 特意把3个网络的数据延时加长了,优先级设置小些(与MODBUS 任务命令, 设置大了 ,现象没啥两样)
modbus 读和写的命令 和根据数据处理命令延时时间比较短 既然modbus有实时交互,你可以考虑另外一个辅助单片机裸奔处理这个事 NJ8888 发表于 2016-6-13 23:04
既然modbus有实时交互,你可以考虑另外一个辅助单片机裸奔处理这个事
目前,硬件只能这样了,也不算 MODBUS 也不算什么太实时,触摸屏3秒读一次CUP里的数据,由于地址不连续,所以向CPU发完一次命令 需要2秒 多才能完成(数据实时性不强,因为采集的是温度,湿度数据...)
要控制动作的MODBUS 指令因为是人为控制,有随机性,一定随机响应,,平时这种指令并不是总发的, (由于触摸屏和相关的变量连接 平时总发没用的01 功能码)
串口使用DMA接收和发送,UCOS中开一个任务延迟一定时间间隔读DMA的接收数量,如果和上次读的一致延时增加,直到3.5T后发消息处理数据! 这个就2秒多了,并且modbus中轮询任务间隔时间是很短的。并且有容错重发机制。 shian0551 发表于 2016-6-14 09:41
这个就2秒多了,并且modbus中轮询任务间隔时间是很短的。并且有容错重发机制。 ...
试着把读取的命令用时间间隔开, 发送,可以缩短发送的时间 jiangzhimin 发表于 2016-6-13 22:37
谢谢,我也想过,关键是modbus中断处理中, 不能丢数据
使用DMA并不意味着会丢数据 MODBUS收到数据和处理数据一定要分开,收到的数据先缓冲起来。 netawater 发表于 2016-6-14 10:13
MODBUS收到数据和处理数据一定要分开,收到的数据先缓冲起来。
呵呵做农业喷灌的大侠,正在考虑用楼上的DMA加串口,有没有想你说的收到的数据和处理的数据分开的示例
关键因为屏连接 着变量,屏空闲时候 不断的发 01没用功能码,不断的串口中断,很麻烦 影响别的任务执行, 如果使用按键发送,一次性发送命令多, 不容易操作 jiangzhimin 发表于 2016-6-14 10:38
呵呵做农业喷灌的大侠,正在考虑用楼上的DMA加串口,有没有想你说的收到的数据和处理的数据分开的示例
...
表示看不懂说什么。
这是我用UCOS III的串口
实时没问题
你可以参考一下
while (DEF_TRUE) /* Task body, always written as an infinite loop. */
{
//
len = Serial_Rd((SERIAL_IF_NBR )App_SerTraceIF_Nbr,
(void *)buf,
(CPU_SIZE_T )100,
(CPU_INT32U )10,
(SERIAL_ERR *)&serial_err);
if(len>0)
{
BSP_LED_Toggle(3u);
MBPoll(buf,&len);
Serial_Wr((SERIAL_IF_NBR )App_SerTraceIF_Nbr,
(void *)buf,
(CPU_SIZE_T )len,
(CPU_INT32U )0,
(SERIAL_ERR *)&serial_err);
}
} os_mbx_init
_init_box
isr_mbx_receive
os_mbx_wait
os_mbx_send
上了系统,这些系统级的调度不用上,当然没有好的实时性了 ccyhyxt 发表于 2016-6-14 14:26
这是我用UCOS III的串口
实时没问题
你可以参考一下
看的似都非都, 不过还是要谢谢您{:smile:}
没办法只能参考下http://www.cnblogs.com/zjutlitao/p/3917638.html 这篇文章上个消息队列试一试, 不知道能不能成功 jiangzhimin 发表于 2016-6-14 14:45
看的似都非都, 不过还是要谢谢您
没办法只能参考下http://www.cnblogs.com/zjutlitao/p/39176 ...
按照例子没有处理成功, 找遍资料 个别做的 ucos 移植freemodbus 例子, 可是压根就没有啥信号量
只能求助哪个大神把关于消息或信号量的例子发送 参考下了 ucos iii 本就有串口的驱动,所以我上面的程序,直接读写就行了 各位大神, ucos 中断的频率多高,可以不影响别其他任务的执行啊(假如系统时钟节拍是1ms) Modbus那个线程你如果把延时去掉的话应该一直占用cpu吧?另外两个线程应该是不跑的。 我不用OS,两个串口走两路MODBUS表示无压力。单片机作MODBUS从机,而且是两路一直读,没停止过。 electrlife 发表于 2016-6-13 22:20
一般的流程是使用中断来接收串口的数据并保存在缓冲区内,等收到完整的一帧数据后通过信号量来通知相应的任 ...
正解,直接中断缓冲保存数据,帧完成后发信号量给任务,任务再处理后,回复数据,也采用中断方式! gliet_su 发表于 2016-6-15 21:51
我不用OS,两个串口走两路MODBUS表示无压力。单片机作MODBUS从机,而且是两路一直读,没停止过。 ...
您有的什么型号,stm 系列?我的是F103XXZET6,现在不担心处理modbus问题, 我担心mcu不断处理modbus 指令, 不停进入中断,
从而别的任务得不到执行。所以问下各位,ucos 这样频繁进中断,处理modbus指令, 别的任务有机会得到执行吗, 或有啥好办好处理下 lingdianhao 发表于 2016-6-15 22:30
正解,直接中断缓冲保存数据,帧完成后发信号量给任务,任务再处理后,回复数据,也采用中断方式! ...
顶,这个问题与OS没什么关系,有没有OS都应该这么处理 串口速率必比CPU时钟满很多,不可能处理不了其他任务 jiangzhimin 发表于 2016-6-15 22:44
您有的什么型号,stm 系列?我的是F103XXZET6,现在不担心处理modbus问题, 我担心mcu不断处理modbus...
你不做复杂的算法,简单的数据处理,完全够用。你说你的进入中断次数多,导致任务没有机会执行。这个不可能。串口多少M,cpu主频多少M,你cpu使用率可能不到1%,ucos统计任务可以测cpu使用率,打出来看看,cpu使用率占了多少。 lingdianhao 发表于 2016-6-15 22:30
正解,直接中断缓冲保存数据,帧完成后发信号量给任务,任务再处理后,回复数据,也采用中断方式! ...
如果裸机时候,中断回复采用中断方式这个方法也不错呵呵,但是ucos 在中断时候可以OSSemPost 信号量, 看资料中断中好像不能用OSSemPend 等待信号量 本帖最后由 jiangzhimin 于 2016-6-16 10:31 编辑
这是自己写的大家帮忙看下 哪有不妥的地方这段程序是 单个少量的命令可以接受, 不间断的发送 就反应不过来
看了一下楼主自己最后改写的,在处理数据任务中PEND信号,应该是死等,然后里面应该不能有延迟函数,有数据就需要马上处理完,然后等待下一次数据。
mozid7 发表于 2016-6-20 22:55
看了一下楼主自己最后改写的,在处理数据任务中PEND信号,应该是死等,然后里面应该不能有延迟函数,有数据 ...
peng 的后边参数 不是死等待的参数
另外没有延时函数怎么切换任务, 我第一幅图,红色标记 用了三种方法切换任务, 不用延时 是可以响应,但是 切换不了任务 jiangzhimin 发表于 2016-6-21 08:41
peng 的后边参数 不是死等待的参数
另外没有延时函数怎么切换任务, 我第一幅图,红色标记 用了三种方法 ...
如果没记错的话,OSSemPend这个接口也会进行一次任务切换,所以没有特殊需要可以不用使用别的接口进行任务切换,可以翻翻ucos的手册了解一下。 不需要延时的,楼上解释对的
页:
[1]