UCOS-II的OSTimeDlyHMSM(0,0,0,1);延时不准是怎么回事
我将UCOS-II的系统时钟设为1ms,那么OSTimeDlyHMSM(0,0,0,1);的延时时间也应该为1ms,可是我用KEIL进行仿真发现差了很多。执行OSTimeDlyHMSM(0,0,0,1);只有2ns的延时,OSTimeDlyHMSM(0,0,1,0);和OSTimeDlyHMSM(0,1,0,0);也测试过与理论值差了很多分别只有0.2s和11.98731s。
但是用同样的方法测试OSTimeDly(1)函数的延时确实准确的1ms。我也对照了其它ucos-ii程序的OSTimeDlyHMSM(0,0,0,1);函数发现跟我现用的函数内容是一模一样的。不知道用过这函数的朋友出现过我同样的问题吗?还是我漏掉了某重要的部分?望大家指教。 回复【楼主位】415462822 头文字C
我将ucos-ii的系统时钟设为1ms,那么ostimedlyhmsm(0,0,0,1);的延时时间也应该为1ms,可是我用keil进行仿真发现差了很多。执行
ostimedlyhmsm(0,0,0,1);只有2ns的延时,ostimedlyhmsm(0,0,1,0);和ostimedlyhmsm(0,1,0,0);也测试过与理论值差了很多分别只有0.2s和11.98731s。
但是用同样的方法测试ostimedly(1)函数的延时确实准确的1ms。我也对照了其它ucos-ii程序的ostimedlyhmsm(0,0,0,1);函数发现跟我现用的函数内容是一模一样的。不知道用过这函数的朋友出现过我同样的问题吗?还是我漏掉了某重要的部分?望大家指教。
-----------------------------------------------------------------------
你晶振配置的不对?
另外,你一个节拍配置为1MS,这对于单片机来说开销太大了! 速度不够快的话,你延时OSTimeDlyHMSM(0,0,0,1)1MS误差很大的,因为OSTimeDlyHMSM(0,0,0,1)这个函数的延时最终还是换算成OSTimeDly(1)函数来实现延时,加上一些中断响应延时...这个我也测试过,不过不是软仿真,我是用硬件测的! 这个本来就不是很准,要准,必须用中断。 理论上就是这样。
即使没有别的任务运行,最大误差也为一个时钟节拍。
如果有更高优先级任务运行,定时时间到,任务就绪并不一定会立即运行,轮到此任务运行不一定多少时间了。 OSTimeDlyHMSM最小延时为OSTimeDly(1),当设置的值<1Tick时,任务立即就绪,也就是根本不延时;因此,延时不准是因为你函数调用方法的问题,不是晶振或其他因素引起的!你应该看看OSTimeDlyHMSM的源码。 压堆栈,出堆栈都需要时间消耗! 回复【4楼】pbxywyq
-----------------------------------------------------------------------
如果像你所说“当设置的值<1Tick时,任务立即就绪,也就是根本不延时;”,那为什么我使用ostimedlyhmsm(0,0,1,0);延时1s也不准列?它的设置值不是>1Tick吗? 原因已经说过了,再重复一遍。
不管延时多长时间,最终都需要转换为以时钟节拍为单位。
例如,如果时钟节拍设为10ms,也就是说每隔10ms产生一个节拍,
延时1个时钟节拍,则任务挂起,等1一个时钟节拍产生后任务就绪。
时钟节拍的发生和任务是异步的,如果延时操作之后恰好立即产生节拍,则任务立即就绪,延时时间接近0。
如果延时操作前刚发生过节拍,则需等待10ms后才会再发生一次节拍,即延时时间为一个节拍。
同理,延时多个时钟节拍,实际时间应该有最大一个节拍的误差。
另外这个只是任务就绪的时间,如果有高优先级任务在执行,还要一直延时下去。
说的不是很清楚,用图来表示的话会清晰一些。 回复【7楼】health
原因已经说过了,再重复一遍。
不管延时多长时间,最终都需要转换为以时钟节拍为单位。
例如,如果时钟节拍设为10ms,也就是说每隔10ms产生一个节拍,
延时1个时钟节拍,则任务挂起,等1一个时钟节拍产生后任务就绪。
时钟节拍的发生和任务是异步的,如果延时操作之后恰好立即产生节拍,则任务立即就绪,延时时间接近0。
如果延时操作前刚发生过节拍,则需等待10ms后才会再发生一次节拍,即延时时间为一个节拍。
同理,延时多个时钟节拍,实际时间应该有最大一个节拍的误差。
另外这个只是任务就绪的时间,如果有高优先级任务在执行,还要一直延时下去。
说的不是很清楚,用图来表示的话会清晰一些。
-----------------------------------------------------------------------
楼上分析的很透彻!不用图像也很容易理解!
也就说不管你延时多长误差都会在一个时钟接拍内。 回复【7楼】health
原因已经说过了,再重复一遍。
不管延时多长时间,最终都需要转换为以时钟节拍为单位。
例如,如果时钟节拍设为10ms,也就是说每隔10ms产生一个节拍,
延时1个时钟节拍,则任务挂起,等1一个时钟节拍产生后任务就绪。
时钟节拍的发生和任务是异步的,如果延时操作之后恰好立即产生节拍,则任务立即就绪,延时时间接近0。
如果延时操作前刚发生过节拍,则需等待10ms后才会再发生一次节拍,即延时时间为一个节拍。
同理,延时多个时钟节拍,实际时间应该有最大一个节拍的误差。
另外这个只是任务就绪的时间,如果有高优先级任务在执行,还要一直延时下去。
说的不是很清楚,用图来表示的话会清晰一些。
-----------------------------------------------------------------------
我已经明白你的意思了 ostimedly(1);这个函数就等于一个时钟节拍,现定为1ms。
你上面所说的都和这个函数有关。
但我想问的是ostimedlyhmsm(0,0,0,1);这个函数为什么不准确? 它和时钟节拍的关系是什么?
我已经将STM32的系统时钟倍频为72Mhz了,难道还不够快吗?
还是我使用ostimedlyhmsm(0,0,0,1);的方法不正确?
如果不正确的话,如何使用才能得到精确的延时? OSTimeDlyHMSM(0,0,0,1)这个我虽然用过,但没去注意精确地时间,但OSTimeDly(1)的实际运行时间我是在72M的STM32F103系统里面测试过的,一点都不准,是在0~(1/OS_TICKS_PER_SEC)之间。也就是说OS_TICKS_PER_SEC=1000的话,延迟时间是0~1ms的任意值。在Labrosse的书里面,OSTimeDly()项目下明确说明如果要保证1/OS_TICKS_PER_SEC延迟,参数应该为2。
这种实时性强的东西,不要相信仿真,只能相信示波器。
我用的是官方2.86的STM32 Ports,参考书为《MicroC OS II, The Real-Time Kernel, 2nd Ed. - Labrosse 2002.pdf》,你可以用电驴的ed2k网络搜索并下载到。 回复【10楼】june4th 朴正欢
OSTimeDlyHMSM(0,0,0,1)这个我虽然用过,但没去注意精确地时间,但OSTimeDly(1)的实际运行时间我是在72M的STM32F103系统里面测试过的,一点都不准,是在0~(1/OS_TICKS_PER_SEC)之间。也就是说OS_TICKS_PER_SEC=1000的话,延迟时间是0~1ms的任意值。在Labrosse的书里面,OSTimeDly()项目下明确说明如果要保证1/OS_TICKS_PER_SEC延迟,参数应该为2。
这种实时性强的东西,不要相信仿真,只能相信示波器。
-----------------------------------------------------------------------
我已经确定OSTimeDly(1)的准确性了,我将OSTimeDly(1)和滴答时钟(时钟节拍)中断程序同时进行仿真,发现它们的时间是一样的。
我也用硬件验证过OSTimeDlyHMSM(0,0,0,1)这个函数不准。
我在任务里对LED进行取反,使用OSTimeDlyHMSM(0,0,3,0)每隔3s执行一次。但感觉上它1s内就执行完了。如果误差只有几ms的话我就不追究了。但是这个误差实在是太大了。已经影响到使用了。 回复【9楼】415462822 头文字C
回复【7楼】health
原因已经说过了,再重复一遍。
不管延时多长时间,最终都需要转换为以时钟节拍为单位。
例如,如果时钟节拍设为10ms,也就是说每隔10ms产生一个节拍,
延时1个时钟节拍,则任务挂起,等1一个时钟节拍产生后任务就绪。
时钟节拍的发生和任务是异步的,如果延时操作之后恰好立即产生节拍,则任务立即就绪,延时时间接近0。
如果延时操作前刚发生过节拍,则需等待10ms后才会再发生一次节拍,即延时时间为一个节拍。
同理,延时多个时钟节拍,实际时间应该有最大一个节拍的误差。
另外这个只是任务就绪的时间,如果有高优先级任务在执行,还要一直延时下去。
说的不是很清楚,用图来表示的话会清晰一些。
-----------------------------------------------------------------------
我已经......
-----------------------------------------------------------------------
看来你还没有明白.....
你去看看源代码就清楚了! 从来不用OSTimeDlyHMSM,浪费代码空间。
Tick=1ms,要延时3s,只需OSTimeDly(3000)即可,或者OSTimeDly(OS_TICKS_PER_SEC * 3)。 回复【12楼】AVR_DIY 苹果的另一半
-----------------------------------------------------------------------
我觉得是你们没看懂楼主的问题。。。按你说最大误差是1个Tick + 高于本任务优先级的任务。但是楼主已经误差的太大了吧。 回复【14楼】chenfu
回复【12楼】avr_diy 苹果的另一半
-----------------------------------------------------------------------
我觉得是你们没看懂楼主的问题。。。按你说最大误差是1个tick + 高于本任务优先级的任务。但是楼主已经误差的太大了吧。
-----------------------------------------------------------------------
楼上的,KEIL中的仿真能和实际的比吗??? 大家说的都是为什么ostimedlyhmsm(0,0,0,1);的延时会>1ms,但我的问题却是为什么ostimedlyhmsm(0,0,0,1);会<1ms。
虽然大家误解了我的意思,但是通过看的家的回帖,我已经发现什么ostimedlyhmsm(0,0,0,1);会<1ms的原因了。
原因很简单在OS_CFG.H文件中定义了
#define OS_TICKS_PER_SEC 200
它对应的UC/OS-II时钟周期为5ms
但我现在设置的UC/OS-II的时钟周期为1ms,所以应该定义OS_TICKS_PER_SEC为1000。
#define OS_TICKS_PER_SEC 1000
这样定义后,再进行仿真ostimedlyhmsm(0,0,0,1);就约等于1ms了。
谢谢大家了,没有大家的回帖我解决不了这个问题。 我倒! 最终结论:
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603673UK1DIN.JPG
(原文件名:12.JPG) 倒,问问题,竟然也搞乌龙。 回复【19楼】chenfu
-----------------------------------------------------------------------
我没想到会让大家产生误解 mark~~~~ mark ticks抖动引起,或晶振不准。 mark。。。。。。。。。。 学习了 呃 这个还是看配置吧 居然是这么RZ的错误。 要是想要实现1us的延时,怎么实现啊?
页:
[1]