搜索
bottom↓
回复: 51

怎样提升C#的定时器精度

[复制链接]

出0入0汤圆

发表于 2017-10-23 11:03:22 | 显示全部楼层 |阅读模式
最近在用C#做串口通信方面的控制,发现一个问题,定时一点不准,我想定时器10ms,发现不行,

有没有办法定时器精度做到20ms,实在不行30ms也可以,好吧40ms也中。

用过的来说说吧,哈哈

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2017-10-23 11:18:49 | 显示全部楼层
确实是的  c#的定时器不准确

出0入0汤圆

 楼主| 发表于 2017-10-23 11:20:39 | 显示全部楼层
-佛听- 发表于 2017-10-23 11:18
确实是的  c#的定时器不准确

有解决的办法没

出0入0汤圆

发表于 2017-10-23 11:24:10 | 显示全部楼层
本帖最后由 rqiang 于 2017-10-23 11:25 编辑

https://msdn.microsoft.com/zh-cn ... agnostics.stopwatch(v=vs.110).aspx
这个可以拿来检测时间,比较准

出0入0汤圆

 楼主| 发表于 2017-10-23 11:26:48 | 显示全部楼层
rqiang 发表于 2017-10-23 11:24
https://msdn.microsoft.com/zh-cn/library/system.diagnostics.stopwatch(v=vs.110).aspx
这个可以拿来检 ...

这个只能用来检测时间对吧?但是我要的中断触发啊

出0入0汤圆

发表于 2017-10-23 11:27:00 | 显示全部楼层
调用C/C++的DLL

出0入0汤圆

发表于 2017-10-23 11:27:31 | 显示全部楼层
有内核的定时函数接口   可以有几ms的精度吧

出0入0汤圆

发表于 2017-10-23 11:32:00 来自手机 | 显示全部楼层
多媒体定时器1ms精度

出0入0汤圆

发表于 2017-10-23 11:32:09 | 显示全部楼层
霸气侧漏 发表于 2017-10-23 11:26
这个只能用来检测时间对吧?但是我要的中断触发啊

MS级中断没有用过,估计不行

出0入0汤圆

 楼主| 发表于 2017-10-23 11:32:53 | 显示全部楼层
panjun10 发表于 2017-10-23 11:32
多媒体定时器1ms精度

多媒体定时器1ms精度

我搜搜看,还有这个定时器,

出0入0汤圆

发表于 2017-10-23 11:33:01 | 显示全部楼层
Win 就不是一个实时系统,想做的精确定时很困难。
说说我的想法,win系统时间片据说是20ms。非计算密集型的程序,在1ms 只内应该就会因为阻塞或者主动放弃CPU(Sleep(XX))而让出 CPU。计算密集型应该最多20ms 就被强制放弃CPU。

一般合格程序员写的程序(非计算密集型)基本能在1ms 让出CPU。

你能做的是:用户任务近可能少,关闭也行占用CPU比较高的进程和服务
1.使用线程,将优先级调至最高
2.关闭系统不必要服务
3.任务管理器查看那个程序,占用CPU较高,看看是否能优化调或者关了,如杀毒软件。

对操作系统或者.net Framework 内部造成的定时不准确,就没办法了,但是操作系统应该没有啥,计算密集型的任务。至于.net Framework  在GC的时候可能会卡一下吧。


出0入0汤圆

 楼主| 发表于 2017-10-23 11:40:36 | 显示全部楼层
semonpic 发表于 2017-10-23 11:33
Win 就不是一个实时系统,想做的精确定时很困难。
说说我的想法,win系统时间片据说是20ms。非计算密集型的 ...

这样啊,谢谢大神的指点,我去试试看

出0入0汤圆

发表于 2017-10-23 11:56:52 | 显示全部楼层
霸气侧漏 发表于 2017-10-23 11:40
这样啊,谢谢大神的指点,我去试试看

或者用那个time watch来做闭环  应该可以做到ms级别

出0入0汤圆

发表于 2017-10-23 12:01:23 来自手机 | 显示全部楼层
多媒体定时器,或者用线程设置优先级高然后获取系统时间死等我做到了1ms

出0入0汤圆

 楼主| 发表于 2017-10-23 12:16:37 | 显示全部楼层
q457344370 发表于 2017-10-23 12:01
多媒体定时器,或者用线程设置优先级高然后获取系统时间死等我做到了1ms

来点代码先,哈哈

出0入0汤圆

发表于 2017-10-23 15:48:23 | 显示全部楼层
换个想法了,试一试,用
  1. //------独立线程--------
  2. while {
  3.       Thread.Sleep(XX);
  4.       //do something
  5. }
复制代码

出0入0汤圆

发表于 2017-10-23 17:41:41 | 显示全部楼层
还是多媒体定时器的回调方式吧,等效MCU的中断

出0入0汤圆

发表于 2017-10-24 13:25:13 | 显示全部楼层
.net 有4种定时器,用System.Timers.Timer更精确些,触发间隔要大于16ms

出0入0汤圆

 楼主| 发表于 2017-10-24 13:38:55 | 显示全部楼层
uid81 发表于 2017-10-24 13:25
.net 有4种定时器,用System.Timers.Timer更精确些,触发间隔要大于16ms

30ms也是没问题的
头像被屏蔽

出0入0汤圆

发表于 2017-10-24 13:52:00 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

 楼主| 发表于 2017-10-24 13:53:19 | 显示全部楼层
立创商城-技术 发表于 2017-10-24 13:52
做个外置硬件的计时单元也不错吧!
比如 用CH9326 (USB HID 免驱)+ RTC芯片或MCU,轻松实现一个USB RTC。 ...

这个不现实,虽然也能解决问题,还是软件级别的解决方案比较好
头像被屏蔽

出0入0汤圆

发表于 2017-10-24 16:26:30 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

 楼主| 发表于 2017-10-24 21:42:13 | 显示全部楼层
立创商城-技术 发表于 2017-10-24 16:26
用软件也可以,比如用VC做一个DLL,精度其实很高,延时xx微秒(uS) 都可以。 然后C#调用DLL。  ...

没这样搞过,有例程没有,

出0入0汤圆

发表于 2017-10-24 22:04:28 来自手机 | 显示全部楼层
延时uS是可以,但不能稳定的延时。

出0入0汤圆

发表于 2017-10-24 22:05:30 来自手机 | 显示全部楼层
Win 就不是一个实时系统,想做的精确定时很困难。

出0入0汤圆

 楼主| 发表于 2017-10-24 22:20:54 | 显示全部楼层
ordinary 发表于 2017-10-24 22:05
Win 就不是一个实时系统,想做的精确定时很困难。

这个我知道,就是不太清楚怎么搞定,很少用C#

出0入20汤圆

发表于 2017-10-25 00:45:26 | 显示全部楼层
用C#做10ms级别的精确控制不是一件容易的事情,因为包括.NET framework在内的整个系统不是给强实时应用准备的.
但是大部分情况下,解决问题不是只有一种方法的,比如LZ的串口应用,在合理设置串口buffer threshold的情况下是完全可以用事件响应的方式做到很高的实时性的.实在不行,就用最基本的字节中断,自己去拼数据,灵活且响应快.
同时多线程环境下,如果os的负担不重每个线程的轮询比例比较均匀也是可以获得比较好的实时性的.(我一般都这么搞,本身C#写这一类应用就超级方便,而且大部分时候响应速度都够用,毕竟系统跑满的情况比较少)

出0入0汤圆

发表于 2017-10-25 07:25:30 来自手机 | 显示全部楼层
开个线程,用gettickcount计数,这个本来就不是实时操作糸统

出300入477汤圆

发表于 2017-10-25 07:34:06 来自手机 | 显示全部楼层
semonpic 发表于 2017-10-23 11:33
Win 就不是一个实时系统,想做的精确定时很困难。
说说我的想法,win系统时间片据说是20ms。非计算密集型的 ...

操作系统的计算密集型任务也有哦,常见的杀毒软件360防火墙之类都是。它是驱动层的比你优先级高,想干啥都行。
哈哈… 你程序写的再好,遇到客户装上全套这种东西,包你卡的跟啥一样!

出0入0汤圆

 楼主| 发表于 2017-10-25 09:10:01 | 显示全部楼层
redroof 发表于 2017-10-25 07:34
操作系统的计算密集型任务也有哦,常见的杀毒软件360防火墙之类都是。它是驱动层的比你优先级高,想干啥 ...

这他妈就尴尬了,目前只给公司内部测试用,应该没问题

出0入0汤圆

发表于 2017-10-25 10:01:27 | 显示全部楼层
以前测试,VC多媒体定时器,关掉别的乱七八糟软件,定时1MS,99%以上周期准确,偶有跳到几个MS到10多个MS时候
如果开了别的乱七八糟软件,那就无法预测了,至少你不可能比杀毒软件之类更优先,马云马化腾360之类全家桶也是牛逼哄哄,神仙也无招。
-----------结论:电脑高精度定时只能在理想环境下保证基本正确的ms级别,不具有广泛性(你不能保证运行环境)。

出0入0汤圆

发表于 2017-10-25 10:04:48 | 显示全部楼层
不会有谁为了运行你的软件把浏览器扣扣淘宝等等等等神马统统统统杀掉进程。 什么都不干光看着屏幕界面。

出300入477汤圆

发表于 2017-10-25 10:12:44 | 显示全部楼层
huangqi412 发表于 2017-10-25 10:04
不会有谁为了运行你的软件把浏览器扣扣淘宝等等等等神马统统统统杀掉进程。 什么都不干光看着屏幕界面。 ...

做工业自动化监控的机器,你或许可以这么要求客户。
当然如果有笨蛋非要在控制着价值几百万的生产线的电脑上安装360全家桶之类,那么神仙也帮不了你
在大部分管理正确的这种机器上,你安装任何软件都要跟他们管理员申请的。

出10入210汤圆

发表于 2017-10-25 23:20:34 来自手机 | 显示全部楼层
霸气侧漏 发表于 2017-10-23 11:20
有解决的办法没

运行程序后,在任务管理器中找到进程,点鼠标右键,设置优先级,改为“实时“,看看有没有效果。

出0入0汤圆

 楼主| 发表于 2017-10-25 23:38:08 来自手机 | 显示全部楼层
rainbow 发表于 2017-10-25 23:20
运行程序后,在任务管理器中找到进程,点鼠标右键,设置优先级,改为“实时“,看看有没有效果。 ...

我试试看,嘿嘿

出10入210汤圆

发表于 2017-10-26 00:46:07 | 显示全部楼层

有区别吗?

出0入85汤圆

发表于 2017-10-26 10:58:51 | 显示全部楼层
使用串口通讯,需要1mS定时的精度 意义何在?串口本来就很慢,实时性要求这么高有意义?

出0入0汤圆

发表于 2017-10-26 13:44:44 | 显示全部楼层

多媒体定时器MmTimer的网上例子很多,你自己找吧,
下边是用线程死等的,可以做到很小的周期,但是比较耗资源,且周期不太稳定
  1. int pengding = 0;
  2. Thread trans_thread;
  3. private void CanTrans_Thread()
  4. {
  5.     while (true)
  6.     {
  7.         int id;
  8.         int dlc;
  9.         long oldTime = DateTime.Now.Ticks;
  10.         long nowTime;
  11.         long time;
  12.         long cnt;
  13.         byte[] dat = new byte[8];
  14.         bool rx_frame = false;
  15.         int idle_counter = 0;
  16.         while (true)
  17.         {
  18.             rx_frame = false;
  19.             while (ReadData != null && ReadData(out id, ref dat, out dlc, out time) == true)
  20.             {
  21.                 if (id == rx_id && dlc == 8)
  22.                 {
  23.                     /*
  24.                     ** Response Pending
  25.                     */
  26.                     if (dat[0] == 0x03
  27.                         && dat[1] == 0x7F
  28.                         && dat[3] == 0x78)
  29.                     {
  30.                         pengding = 5000;
  31.                         RxFrameEvent(id, dat, dlc, time);
  32.                         break;
  33.                     }
  34.                     pengding = 0;
  35.                     RxFrameEvent(id, dat, dlc, time);
  36.                     Array.Copy(dat, can_rx_info.frame, SF_DL_MAX_BYTES + 1);
  37.                     break;
  38.                 }
  39.             }
  40.             nowTime = DateTime.Now.Ticks;
  41.             cnt = nowTime - oldTime;
  42.             if (cnt >= 5000 || rx_frame)
  43.             {
  44.                 oldTime = nowTime;
  45.                 if (pengding == 0)
  46.                 {
  47.                     CanTrans_Counter((int)(cnt + 5000) / 10000);
  48.                 }
  49.                 else
  50.                 {
  51.                     pengding--;
  52.                 }
  53.             }

  54.             if (pengding == 0)
  55.             {
  56.                 CanTrans_Manage();
  57.             }

  58.             if (can_rx_info.rx_in_progress || can_tx_info.tx_in_progress || rx_frame)
  59.             {
  60.                 idle_counter = 0;
  61.             }
  62.             else
  63.             {
  64.                 if (idle_counter >= 100)
  65.                 {
  66.                     Thread.Sleep(5);
  67.                 }
  68.                 else
  69.                 {
  70.                     idle_counter++;
  71.                 }
  72.             }
  73.         }
  74.     }
  75. }

  76. /// <summary>
  77. /// 传输层开启
  78. /// </summary>
  79. public void Start()
  80. {
  81.     pengding = 0;
  82.     can_tx_info = new tx_info();
  83.     can_rx_info = new rx_info();

  84.     trans_thread = new Thread(new ThreadStart(CanTrans_Thread));
  85.     trans_thread.IsBackground = true;
  86.     trans_thread.Priority = ThreadPriority.Highest;
  87.     trans_thread.Start();

  88.     testerPresentStart();
  89. }
复制代码

出0入475汤圆

发表于 2017-10-26 15:25:54 | 显示全部楼层
晕,原来这里也有这个讨论,
昨天我还在另外一个帖子里面问呢,
https://www.amobbs.com/forum.php ... p;page=1#pid9960896

我不是搞上位机软件的,但是实际中发现的确好多情况下每个sleep()就是15.625ms的感觉,
然后不知道有没有usleep()函数,

出0入475汤圆

发表于 2017-10-26 15:30:15 | 显示全部楼层
marshallemon 发表于 2017-10-26 10:58
使用串口通讯,需要1mS定时的精度 意义何在?串口本来就很慢,实时性要求这么高有意义? ...

比如说一秒钟发1000帧信息,那么基本上就是1ms一次了,即使不用均匀分布的绝对1ms一次,但是平均下来是也可以,问题是现在简单方式就做不到1ms的定时,就如楼主所说的一样。

然后一毫秒钟以内发一帧信息的话,115200应该发几个字节也是可以的,在退步,楼主说的那样,哪怕10ms也行,这样很多通信帧就可以完成了

出0入0汤圆

发表于 2017-10-27 00:17:07 | 显示全部楼层
通过结果可以看出Sleep, GetTickCount都是10~35ms左右的时间跳跃,timeGetTime为1ms,QueryPerformanceCounter和QueryPerformanceFrequency根据CPU频率计时,可以到100ns。

出0入93汤圆

发表于 2017-10-27 07:06:29 来自手机 | 显示全部楼层
立创商城-技术 发表于 2017-10-24 16:26
用软件也可以,比如用VC做一个DLL,精度其实很高,延时xx微秒(uS) 都可以。 然后C#调用DLL。  ...

精度高有个蛋用,进程一切换就煞笔了。vc嵌入汇编还能搞到ns级定时呢,然并卵。应用又没办法关中断

出0入93汤圆

发表于 2017-10-27 07:15:47 来自手机 | 显示全部楼层
huangqi412 发表于 2017-10-25 10:01
以前测试,VC多媒体定时器,关掉别的乱七八糟软件,定时1MS,99%以上周期准确,偶有跳到几个MS到10多个MS时 ...

所以要保证精确度,只能是驱动,或者换系统,比如wince,对付1ms还算可以的。我测试过usb的sof包,真的是1ms一次哪怕电脑CPU占用100%了,要不然usb就掉了。而高精度定时器其实是高精度计时器,能保证啥时开启,却无法保证啥时关闭,这就悲剧了

出0入0汤圆

 楼主| 发表于 2017-10-27 12:23:30 | 显示全部楼层
takashiki 发表于 2017-10-27 07:15
所以要保证精确度,只能是驱动,或者换系统,比如wince,对付1ms还算可以的。我测试过usb的sof包,真的是 ...

应该是这样的

出0入85汤圆

发表于 2017-10-27 12:41:21 | 显示全部楼层
1a2b3c 发表于 2017-10-26 15:30
比如说一秒钟发1000帧信息,那么基本上就是1ms一次了,即使不用均匀分布的绝对1ms一次,但是平均下来是也 ...



我比较好奇的是,哪种场合需要这种机制?难道准备使用串口搞高速运动控制?为了弥补win的实时性的缺陷,把这1000帧拆分成多帧,下位机使用FIFO不行吗?非要1mS发送一帧?而且对于下位机来说实现高波特率貌似是通过降低采样率来实现的,这样用可靠性值得怀疑

出0入475汤圆

发表于 2017-10-27 12:48:54 来自手机 | 显示全部楼层
marshallemon 发表于 2017-10-27 12:41
我比较好奇的是,哪种场合需要这种机制?难道准备使用串口搞高速运动控制?为了弥补win的实时性的缺陷 ...

千奇百怪的应用太多了,所以实际中完全存在我说的这个情况,因为我做的一个东西恰好就是要这样,而且还是国际标准...哈哈,

出0入0汤圆

 楼主| 发表于 2017-11-14 14:15:21 | 显示全部楼层
rqiang 发表于 2017-10-23 11:24
https://msdn.microsoft.com/zh-cn/library/system.diagnostics.stopwatch(v=vs.110).aspx
这个可以拿来检 ...

再请教C#精度定时问题
https://www.amobbs.com/thread-5683320-1-1.html
(出处: amoBBS 阿莫电子论坛)


请看看这个帖子,谢谢

出0入0汤圆

 楼主| 发表于 2017-11-14 14:16:04 | 显示全部楼层
1a2b3c 发表于 2017-10-26 15:25
晕,原来这里也有这个讨论,
昨天我还在另外一个帖子里面问呢,
https://www.amobbs.com/forum.php?mod=vie ...

再请教C#精度定时问题
https://www.amobbs.com/thread-5683320-1-1.html
(出处: amoBBS 阿莫电子论坛)


最新成果,但是精度还是有问题

出0入0汤圆

 楼主| 发表于 2017-11-29 08:39:33 来自手机 | 显示全部楼层
浮华一生 发表于 2017-10-23 11:27
有内核的定时函数接口   可以有几ms的精度吧

那个函数,指点一下先

出0入0汤圆

 楼主| 发表于 2017-11-29 08:41:10 来自手机 | 显示全部楼层
q457344370 发表于 2017-10-26 13:44
多媒体定时器MmTimer的网上例子很多,你自己找吧,
下边是用线程死等的,可以做到很小的周期,但是比较耗 ...

谢谢,我现在用多媒体定时器

出0入0汤圆

 楼主| 发表于 2017-11-29 08:41:44 来自手机 | 显示全部楼层
q457344370 发表于 2017-10-26 13:44
多媒体定时器MmTimer的网上例子很多,你自己找吧,
下边是用线程死等的,可以做到很小的周期,但是比较耗 ...

谢谢,我现在用多媒体定时器

出50入135汤圆

发表于 2023-6-6 15:12:58 | 显示全部楼层
DPC定时器,我测试1MS的周期,最大抖动 +-0.2ms
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 07:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表