日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NRF51822 Timer

發布時間:2024/3/24 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NRF51822 Timer 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先熟悉一下NRF51822,這一篇文章講得不錯,鏈接如下:
http://wenku.baidu.com/link?url=JNSJuhxNtMn3HJg6q5rETABXbejF_dallu8CkGzQCb1azNtVv5MJeYbrI26KCl4RrPaq0C41wqkeDihF9RnG577vEhHY993ZksVlSV6FHV_

定時器簡介

定時器可謂是熟悉一個芯片主頻之后第二個要熟悉的模塊。
51822的Timer/Counter結構如下圖所示:

時鐘源

  • 51822的定時器的時鐘源默認是是HFCLK,也就是16MHz。
  • 可以通過預分頻PRESCALER來降低時鐘頻率,公式是:timer時鐘頻率=16M/2^PRESCALER;
    • 這里可能有個疑問,上面的圖解中不是有兩個時鐘源 16M和1M嗎,怎么這個公式只能通過16M來分頻獲得timer時鐘。 這是因為51822為了降低功耗內部自動 做了時鐘源切換,當 Ftimer <= 1M時會自動切換成1M時鐘源
  • 舉兩個例子解釋下

    • 如果需要timer的時鐘為 4M,那么4 = Ftimer = 16M/2^2
      即我們只需設置分頻寄存器 PRESCALER為2,就能或得4M的時鐘給timer了
    • 當需要timer的時鐘為500Khz時,根據公式 我們設置PRESCALER寄存器的值為5, 500kHZ = Ftimer = 16M/2^5。 這個時候Ftimer<=1M,所以51882內部會自動切換成1M的時鐘源然后分頻后獲得500K的timer時鐘。 不過這些都是51822自動切換的了
  • 也就是說設置timer時鐘只要根據上面的公式設置就可以了,時鐘源的切換是51822自動完成的

模式(MODE)

TIMER可以處于兩種模式:
- 0 定時模式:TIMER_MODE_MODE_Timer(默認)
- 1 計數模式:TIMER_MODE_MODE_Counter

它們的區別在于決定定時器里的計數器增加的時鐘源不一樣。如果我們設置了compare[n]事件產生時觸發中斷(關于事件與中斷看前一篇GPIOTE),那么就可以在counter計數到與 cc[n]寄存器中的值相等時觸發中斷,也就能實現我們需要的定時器功能了

定時模式

  • Timer模塊從PCLK16M/PCLK1M 處獲得時鐘源,然后經分頻PRESCALER后得到的時鐘作為timer模塊的時鐘( 上圖Ftimer )。
  • -

計數模式

  • Timer模塊以外部引腳輸入的波動作為timer模塊的時鐘 。

位寬(BITMODE)

定時器位寬,決定用來存儲計數的寄存器有多少位,最大是32bit

寄存器cc[n]

定時就是通過這個值來設置的。

寄存器INTENSET

這個寄存器可以設置compare事件產生時觸發中斷。第16、17、18位分別對應compare[0]、compare[1]、compare[2]。

寄存器SHORTS

可以決定timer模塊中的counter計數到cc[0]的時候值會不會清零,以達到可以重新計數的目的。

就是說當定時器內部的計數累加值和這個寄存器的值相等的時候就會觸發compare事件

下面的例子會做一個一秒定時亮燈/滅燈的程序, 我們設置timer時鐘為1M,即分頻寄存器PRESCALER寫值為4。 1M的時鐘源則一個tick為1us,所以要定時1s,則cc[0]的值我們填入 1000000就行了。(這里也可以選擇cc[1],cc[2],或cc[3],只要下面對應的compare事件產生中斷設置成對應的就可以了)

定時器中斷工作

  • 根據上面的模塊結構圖和說明想要實現定時器,定時器的工作氛圍幾個步驟。

    • 選擇Timer/Countermo模塊為timer模式,并設置bitmode(8,16,24,32位)。
    • 通過設置分頻來設置timer的時鐘。
    • 設置cc[n] (后面我們的例子選擇使用cc0),來設置計數到多少產生compares[n]事件(當計數值技術到cc[n]的值時對應產生compare[n]事件)
    • 設置compare事件產生時觸發中斷。
    • 通過NVIC函數NVIC_EnableIRQ來使能MCU 的timer中斷
    • 最后通過Timer/Counter模塊的 START 啟動timer
  • 代碼示例

void timer2_init(void) {// 時鐘 = 16 MhzNRF_TIMER2->BITMODE = 0;//(TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos); // 設置16bit模式NRF_TIMER2->PRESCALER = 9; // 2^9=512,得到31.25kHz的timer時鐘NRF_TIMER2->SHORTS = 1<<18;//(TIMER_SHORTS_COMPARE2_CLEAR_Enabled << TIMER_SHORTS_COMPARE2_CLEAR_Pos); //設置compare[2]事件產生時觸發中斷,在中斷函數中清楚對應的compare// 2比較中斷NRF_TIMER2->MODE = 0;//TIMER_MODE_MODE_Timer; // 計時模式(默認)NRF_TIMER2->CC[2] = 31250U; //0x7A12UL//中斷設置NRF_TIMER2->INTENSET = 1<<18;//(TIMER_INTENSET_COMPARE2_Enabled << TIMER_INTENSET_COMPARE2_Pos);//開啟中斷NVIC_ClearPendingIRQ(TIMER2_IRQn);NVIC_SetPriority(TIMER2_IRQn, 3);NVIC_ClearPendingIRQ(TIMER2_IRQn);NVIC_EnableIRQ(TIMER2_IRQn);//啟動timerNRF_TIMER2->TASKS_START = 1; }void TIMER2_IRQHandler(void) //定時器中斷模式 {if ((NRF_TIMER2->EVENTS_COMPARE[2] == 1)&& (NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE2_Msk)){NRF_TIMER2->EVENTS_COMPARE[2] = 0;LED1_Toggle();//電平翻轉void LED2_Toggle(void)//NRF_TIMER2->TASKS_CLEAR = 1; //應該是1s秒中斷一次,如果沒有這一句就會兩秒才中斷一次}}
  • 代碼說明
    • mian需要初始化兩個函數
      • led_init();
      • timer2_init();
    • 需要注意替換的地方
      • NRF_TIMER0、CC[0]、TIMER0_IRQn、EVENTS_COMPARE[0]、COMPARE0_Enabled
      • NRF_TIMER1、CC[1]、TIMER1_IRQn、EVENTS_COMPARE[1]、COMPARE1_Enabled
      • NRF_TIMER2、CC[2]、TIMER2_IRQn、EVENTS_COMPARE[2]、COMPARE2_Enabled
    • 調試過程中出現了一點BUG,本來設置的是1s中斷一次,但是實驗結果是2s,后面才發現是在中斷結束后沒有及時清除,剛好設置的CC[2]是31250,設置的Bit位寬又是16位,剛好65535差不錯是31250的兩倍,所以每次compare[2]都是從0一直計數累計到65535才從零開始,也就是說,每次與CC[2]比較相等的時候,已經過了差不多2s。
    • 但是好像在有上面那個BUG的情況下把位寬修改為32位也還是一樣的2秒中斷一次!一開始很疑惑,后面想了想,如果沒有在中斷結束后及時把compare寄存器的值清零的話,不管CC寄存器的值為多少,中斷周期都是一整個大周期也就是大約2秒。設置位寬只是能讓compare進位的步數顆粒度更小一點而已。

其他

建議定時器中斷采用time1或者是time2,因為如果跑了協議棧就不能用timer0。

總結

以上是生活随笔為你收集整理的NRF51822 Timer的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。