色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

rt-thread 驅動篇(八)hwtimer 重載算法優化

出出 ? 來源:出出 ? 作者:出出 ? 2022-06-23 10:10 ? 次閱讀

硬件定時器

區別于 rt-thread 內核實現的兩種定時器,這種定時器依賴芯片內置的定時器外設,依靠穩定高速的晶振實現精確定時,可以實現 rt_timer 無法達到的定時精度。硬件定時器最重要的兩個參數是定時器時鐘和定時器重載值。

定時器時鐘越高,定時器精度越高;重載值越大,實現的定時時間越長。

在定時器時鐘一定的前提下,重載值就決定了定時器定時時間的準確性。

兩種計算重載值算法

hwtimer.c 文件 `timeout_calc` 函數實現

   float overflow;
   float timeout;
   rt_uint32_t counter;
   int i, index = 0;
   float tv_sec;
   float devi_min = 1;
   float devi;
   /* changed to second */
   overflow = timer->maxcnt/(float)timer->freq;
   tv_sec = tv->sec + tv->usec/(float)1000000;

   if (tv_sec < (1/(float)timer->freq))
   {
       /* little timeout */
       i = 0;
       timeout = 1/(float)timer->freq;
   }
   else
   {
       for (i = 1; i > 0; i ++)
       {
           timeout = tv_sec/i;

           if (timeout <= overflow)
           {
               counter = timeout*timer->freq;
               devi = tv_sec - (counter/(float)timer->freq)*i;
               /* Minimum calculation error */
               if (devi > devi_min)
               {
                   i = index;
                   timeout = tv_sec/i;
                   break;
               }
               else if (devi == 0)
               {
                   break;
               }
               else if (devi < devi_min)
               {
                   devi_min = devi;
                   index = i;
               }
           }
       }
   }

   timer->cycles = i;
   timer->reload = i;
   timer->period_sec = timeout;
   counter = timeout*timer->freq;

   return counter;

第二種實現,

   rt_uint32_t counter, reload;
   rt_uint32_t timer_cnt;
   int i, index = 0, n0, n1;
   float tv_sec;
   rt_uint32_t dev, dev_min;
   /* changed to second */
   tv_sec = tv->sec + tv->usec/(float)1000000.0;
   timer_cnt = tv_sec * timer->freq;

   if (timer_cnt == 0) {
       timer_cnt = 1;
   }
   if (timer_cnt < timer->maxcnt) {
       timer->cycles = timer->reload = 1;
       timer->period_sec = tv_sec;
       counter = timer_cnt;
       return counter;
   }
   if (timer_cnt % timer->maxcnt == 0) {
       timer->cycles = timer->reload = timer_cnt / timer->maxcnt;
       timer->period_sec = tv_sec;
       counter = timer_cnt;
       return counter;
   }
   n0 = timer_cnt / timer->maxcnt + 1;
   n1 = timer_cnt / 2;
   dev_min = n0;
   for (i = n0; i < n1; i++) {
       reload = (rt_uint32_t)(timer_cnt / i);
       dev = timer_cnt - reload * i;
       if (dev == 0) {
           // end
           index = i;
           break;
       } else if (dev < dev_min) {
           dev_min = dev;
           index = i;
       }
   }
   timer->cycles = timer->reload = index;
   timer->period_sec = index / timer->freq;
   counter = timer_cnt / index;
   return counter;

測試環境

定時器頻率設定 1M。定時器最大重載值 65535。

系統:win10

IDE:Qt Creator

最大定時范圍

兩種算法,最主要的差別在于前一種用 float 運算,因為 float 可以表達的值范圍更大,定時時間可以更長。

而在 1M 定時器時鐘前提下,用 32 位無符號整型 timer_cnt,最大可以處理時間僅有 4294.967295s。

精度 PK

image.png

這里不支持嵌入 html 表格,只好貼圖了

分別選各個量級的時間,用兩種算法計算,第二種算法可以把誤差降低到0,但是也暴露出一些問題,在某些時間,例如 3.230970s、12.230970s、14.230970s... 誤差是很小,定時器重載值也很小,這是我們不愿意看到的。

第一種算法,在計算大于 1000 的數時,誤差也隨之增大。比如 1000s 誤差為 3.236ms;4293.0s 誤差為 64.080ms。

運算速度 PK

測試方法:抽取某幾個時間值,循環 1M 次運算,計量 1M 次運算總耗時時間。

time float uint32
3.317s 98.736ms 3000+s
7.537s 178.545ms 21.921ms
7.000537s 168.549ms 175.530ms
999.999s 17407.468ms 30866.978ms
999.000999s 17458.347ms 337.047ms

從抽取的幾個值測試結果看,第一種算法耗時比較穩定,第二種算法對不同值的運算時間差異很大。特別的,3.317s 這個值用第二種算法,1M 次運算總耗時時間可能達到 3000s。

從上一小節的精度比對可以看出,第二種算法對精度要求太高了。下面降低第二種算法的精度,達到和第一種一樣的精度再重復一次。修改代碼如下

       if (dev == 0) {
           // end
           index = i;
           break;
       } else if (dev > dev_min) {
           break;
       } else if (dev < dev_min) {
           dev_min = dev;
           index = i;
       }

再次測試結果:

time float uint32
3.317s 104.720ms 20.945ms
3.000317s 91.728ms 21.941ms
7.537s 179.519ms 21.941ms
7.000537s 168.549ms 20.944ms
999.999s 17480.734ms 27.927ms
999.000999s 17366.539ms 20.944ms

我們可以看出來,在相同精度條件下,第二種算法的運算速度比第一種快很多,而且耗時反而變得更集中。

其實,對結束條件再次修正,將 `dev == 0` 的嚴苛誤差條件換成 `dev <= 1` 也不會出現上面 3000+s 慢速。

       if (dev <= 1) {
           // end
           index = i;
           break;
       } else if (dev > dev_min) {
           break;
       } else if (dev < dev_min) {
           dev_min = dev;
           index = i;
       }

超過 4295s 的超長定時

需要修改 `rt_uint64_t timer_cnt` 的定義為 64 位無符號整型 `rt_uint64_t timer_cnt` 。

又因為定時時間很長很長,對誤差要求可以降低一些,對第二種算法做的第二處修改:

       if (dev <= 500) {
           // end
           index = i;
           break;
       } else if (dev < dev_min) {
           dev_min = dev;
           index = i;
       }
image.png

超長時間,第二種算法的表現也很優秀。第三組數據第一種方法竟然出錯了,沒算出結果。

下面是 10k 次(沒有進行 1W 次是因為有些時間太長了)運算時間統計

time float uint32
9999.537s 1741.341ms 5.010ms
19999.999s 3481.173ms 27.926ms
1999999.999s - 2616.001ms

返璞歸真

以上是對兩種算法從不同角度進行的比對測驗。看似用 float 可以計算更大的定時數,但是,測試結果并不那么理想。使用 64位整型數計算,可能得到比用 float 更精確的結果。

使用 32 位無符號整型數運算雖然最大定時時間只有 4294.9s 。但是我們也看到了,第一種方法有可能出現計算誤差的,當誤差超過 1ms 我們用 rt_thread_mdelay 或者 rt-thread 的軟/硬定時器,可能結果比硬件定時器更精確了,反而失去了精確定時器的意義。在這個前提下,使用 32 位無符號整型數已經足夠了。


算法及測試源碼見: https://gitee.com/thewon/rt_thread_repo/tree/master/user

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 算法
    +關注

    關注

    23

    文章

    4608

    瀏覽量

    92844
  • 定時器
    +關注

    關注

    23

    文章

    3246

    瀏覽量

    114739
  • RT-Thread
    +關注

    關注

    31

    文章

    1285

    瀏覽量

    40093
收藏 人收藏

    評論

    相關推薦

    RT-Thread記錄(一、版本開發環境及配合CubeMX)

    RT-Thread 學習記錄的第一文章,RT-Thread記錄(一、RT-Thread 版本、RT-Thread Studio開發環境 及
    的頭像 發表于 06-20 00:28 ?5230次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(一、版本開發環境及配合CubeMX)

    RT-Thread NUC97x 移植 LVGL

    不涉及 rt-thread 驅動,但是它是 LVGL 和 rt-thread 的接口。LVGL 在 rt-thread 上運行的基石。
    發表于 07-08 09:37 ?1480次閱讀

    RT-Thread ssd1306驅動

    RT-Thread 驅動ssd1306
    的頭像 發表于 04-21 10:08 ?26.5w次閱讀
    <b class='flag-5'>RT-Thread</b> ssd1306<b class='flag-5'>驅動</b>

    RT-Thread使用未默認啟用的timer作為硬件定時器HWTIMER的步驟

    初學 RT-Thread,在 RT-Thread studio 環境下,使用手里的 nucleo_L476 開發板來學習 HWTimer 的使用,運行官方 HWTimer 例程。
    的頭像 發表于 07-19 15:17 ?1794次閱讀
    <b class='flag-5'>RT-Thread</b>使用未默認啟用的timer作為硬件定時器<b class='flag-5'>HWTIMER</b>的步驟

    RT-Thread設備驅動開發指南基礎—以先楫bsp的hwtimer設備為例

    RT-Thread設備驅動開發指南》書籍是RT-thread官方出品撰寫,系統講解RT-thread IO設備驅動開發方法,從三方面進行講解
    的頭像 發表于 02-20 16:01 ?1686次閱讀
    <b class='flag-5'>RT-Thread</b>設備<b class='flag-5'>驅動</b>開發指南基礎<b class='flag-5'>篇</b>—以先楫bsp的<b class='flag-5'>hwtimer</b>設備為例

    RT-Thread驅動開發指南進階-動手驅動先楫未適配的外設LCD

    經過上一的《《RT-Thread設備驅動開發指南》基礎--以先楫bsp的hwtimer設備為例》闡述,可以大致了解到
    的頭像 發表于 02-25 11:04 ?2518次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>驅動</b>開發指南進階<b class='flag-5'>篇</b>-動手<b class='flag-5'>驅動</b>先楫未適配的外設LCD

    rt-thread驅動資料下載

    1、rt-thread驅動hwtimer重載算法最大定時范圍兩種算法,最主要的差別在于前一種
    發表于 03-24 15:37

    【原創精選】RT-Thread征文精選技術文章合集

    rt-thread 驅動(六)serialX弊端及解決方法rt-thread 驅動(七)GP
    發表于 07-26 14:56

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開發組(2015-03-31)。RT-Thread做為國內有較大影響力的開源實時操作系統,本文是RT-Thread實時操作系統的編程指南
    發表于 11-26 16:06 ?0次下載

    RT-Thread Studio驅動SD卡

    RT-Thread Studio驅動SD卡前言一、創建基本工程1、創建Bootloader2、創建項目工程二、配置RT-Thread Settings三、代碼分析1.引入庫2.讀入數據四、效果驗證
    發表于 12-27 19:13 ?20次下載
    <b class='flag-5'>RT-Thread</b> Studio<b class='flag-5'>驅動</b>SD卡

    RT-Thread驅動hwtimer重載算法

    區別于 rt-thread 內核實現的兩種定時器,這種定時器依賴芯片內置的定時器外設,依靠穩定高速的晶振實現精確定時,可以實現 rt_timer 無法達到的定時精度。硬件定時器最重要的兩個參數是定時器時鐘和定時器重載值。
    的頭像 發表于 04-01 10:06 ?1771次閱讀

    RT-Thread文檔_RT-Thread 簡介

    RT-Thread文檔_RT-Thread 簡介
    發表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡介

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    RT-Thread文檔_HWTIMER 設備

    RT-Thread文檔_HWTIMER 設備
    發表于 02-22 18:34 ?0次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>HWTIMER</b> 設備

    RT-Thread設備驅動開發指南》基礎--以先楫bsp的hwtimer設備為例

    一、概述(一)RT-Thread設備驅動RT-Thread設備驅動開發指南》書籍是RT-thread官方出品撰寫,系統講解
    的頭像 發表于 02-24 08:16 ?1636次閱讀
    《<b class='flag-5'>RT-Thread</b>設備<b class='flag-5'>驅動</b>開發指南》基礎<b class='flag-5'>篇</b>--以先楫bsp的<b class='flag-5'>hwtimer</b>設備為例
    主站蜘蛛池模板: 伊人青青操| 亚洲精品在线免费| 少妇被阴内射XXXB少妇BB| 色戒无删减流畅完整版| 99亚洲精品| free俄罗斯性xxxxhd派对| 操中国老太太| 国产女人喷潮视频免费| 极品少妇高潮啪啪AV无码| 快播dvd吧| 人妻仑乱少妇88MAV| 无码AV免费精品一区二区三区| 亚洲haose在线观看| 夜夜骑夜夜欢| bbwxxxx交女警| 国产精品久AAAAA片| 国产在线观看黄| 玖玖爱在线播放| 日本伦理片 中文字幕| 无码AV熟妇素人内射V在线| 亚洲中久无码永久在线| 最近中文字幕MV免费看| 波多野结衣教师系列6| 沟沟人体一区二区| 精品视频在线一区| 欧美怡红院视频一区二区三区| 全球真实小U女视频合集| 午夜男人免费福利视频| 一级毛片视频免费| 别插我B嗯啊视频免费| 国产在线精品亚洲第一区| 美女图片131亚洲午夜| 同时被两个男人轮流舔| 中文字幕无线手机在线| 国产第81页| 迈开腿让我看下你的小草莓声音| 日日夜夜天天操| 在线观看亚洲 日韩 国产| 国产 交换 丝雨 巅峰| 久久笫一福利免费导航| 婷婷精品国产亚洲AV在线观看|