[nRF51822] 8、基礎實驗代碼解析大全 · 實驗11 - PPI

来源:http://www.cnblogs.com/zjutlitao/archive/2016/08/09/5752520.html
-Advertisement-
Play Games

前一篇分析了前十個基礎實驗的代碼,從這裡開始分析後十個~ 一、PPI原理: PPI(Programmable Peripheral Interconnect),中文翻譯為可編程外設互連。 在nRF51822 內部設置了PPI 方式,可以通過任務和事件讓不同外設之間進行互連,而不需要CPU 進行參與。 ...


 

前一篇分析了前十個基礎實驗的代碼,從這裡開始分析後十個~

 

一、PPI原理:

PPI(Programmable Peripheral Interconnect),中文翻譯為可編程外設互連。

在nRF51822 內部設置了PPI 方式,可以通過任務和事件讓不同外設之間進行互連,而不需要CPU 進行參與。

PPI 通過通道讓任務和事件連接在一起。PPI 通道由兩個端點組成:

  • 任務端點:Task End-Point (TEP)。
  • 事件端點:Event End-Point (EEP)。

所謂的互聯就是將任務端點寫入需要連接的任務寄存器地址,事件端點寫入需要連接事件寄存器地址,之後,使能該PPI 通道,即實現了任務和事件的互聯。

可以通過如下兩種方式使能和關閉PPI 通道:

  • 1) 通過獨立設置CHEN,CHENSET 和CHENCLR 寄存器。
  • 2) 通過PPI 通道組的使能和關閉任務。使用這種方式,在觸發任務之前,需要先配置好哪些PPI 通道屬於哪個組。

 

二、運行邏輯:

實驗中,用到了3 個定時器:Timer 0、Timer 1 和Timer 2。

1) Timer 0 配置為計數器,在主迴圈中每100ms 被觸發一次,並通過串口列印出計數值。
2) Timer 1 每個偶數秒(2、4、6、8……)產生一次比較匹配事件,該事件通過PPI通道0 和Timer 0 的STOP Task 互聯,互聯後通過該事件觸發Timer 0 的STOP Task。
3) Timer 2 每個奇數秒(1、3、5、7……)產生一次比較匹配事件,該事件通過PPI通道1 和Timer 0 的START Task 互聯,互聯後通過該事件觸發Timer 0 的START Task。

實驗原理框圖如圖1 所示:

 

三、核心代碼分析

系統運行後,在迴圈中Timer 0 計數器的計數值每100ms 增加一次,在偶數秒時,Timer2 產生比較匹配事件,通過PPI 觸發Timer 0 的STOP Task,Timer 0 停止計數。此時,儘管主迴圈中每隔100ms 觸發一次Timer 0 計數,但是由於Timer 0 已經停止,所以,計數值不會增加。每個奇數秒,Timer2 產生比較匹配事件,通過PPI 觸發Timer 0 的START Task,Timer 0 恢復計數。

main函數部分:

 1 int main(void)
 2 {
 3     timer0_init(); // Timer used to blink the LEDs.
 4     timer1_init(); // Timer to generate events on even number of seconds.
 5     timer2_init(); // Timer to generate events on odd number of seconds.
 6     ppi_init();    // PPI to redirect the event to timer start/stop tasks.
 7 
       串口初始化(略)
28 
29     // Enabling constant latency as indicated by PAN 11 "HFCLK: Base current with HFCLK 
30     // running is too high" found at Product Anomaly document found at
31     // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
32     //
33     // @note This example does not go to low power mode therefore constant latency is not needed.
34     //       However this setting will ensure correct behaviour when routing TIMER events through 
35     //       PPI (shown in this example) and low power mode simultaneously.
36     NRF_POWER->TASKS_CONSTLAT = 1;
37     
38     // Start clock.
39     nrf_drv_timer_enable(&timer0);
40     nrf_drv_timer_enable(&timer1);
41     nrf_drv_timer_enable(&timer2);
42 
43     // Loop and increment the timer count value and capture value into LEDs. @note counter is only incremented between TASK_START and TASK_STOP.
44     while (true)
45     {
46 
47         printf("Current cout: %d\r\n", (int)nrf_drv_timer_capture(&timer0,NRF_TIMER_CC_CHANNEL0));
48 
49         /* increment the counter */
50         nrf_drv_timer_increment(&timer0);
51 
52         nrf_delay_ms(100);
53     }
54 }

 

定時器初始化部分:

 1 // Timer even handler. Not used since timer is used only for PPI.
 2 void timer_event_handler(nrf_timer_event_t event_type, void * p_context){}
 3 
 4 /** @brief Function for Timer 0 initialization, which will be started and stopped by timer1 and timer2 using PPI.
 5 */
 6 static void timer0_init(void)
 7 {
 8     ret_code_t err_code = nrf_drv_timer_init(&timer0, NULL, timer_event_handler);
 9     APP_ERROR_CHECK(err_code);
10 }
11 
12 /** @brief Function for Timer 1 initialization.
13  *  @details Initializes Timer 1 peripheral, creates event and interrupt every 2 seconds,
14  *           by configuring CC[0] to timer overflow value, we create events at even number of seconds
15  *           for example, events are created at 2,4,6 ... seconds. This event can be used to stop Timer 0
16  *           with Timer1->Event_Compare[0] triggering Timer 0 TASK_STOP through PPI.
17 */
18 static void timer1_init(void)
19 {
20     // Configure Timer 1 to overflow every 2 seconds. Check TIMER1 configuration for details
21     // The overflow occurs every 0xFFFF/(SysClk/2^PRESCALER).
22     // = 65535/31250 = 2.097 sec
23     ret_code_t err_code = nrf_drv_timer_init(&timer1, NULL, timer_event_handler);
24     APP_ERROR_CHECK(err_code);
25 
26     nrf_drv_timer_extended_compare(&timer1, NRF_TIMER_CC_CHANNEL0, 0xFFFFUL, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);//比較模式,Timer 1 每個偶數秒(2、4、6、8……)產生一次比較匹配事件,該事件通過PPI通道0 和Timer 0 的STOP Task 互聯,互聯後通過該事件觸發Timer 0 的STOP Task。
27 }
28 
29 /** @brief Function for Timer 2 initialization.
30  *  @details Initializes Timer 2 peripheral, creates event and interrupt every 2 seconds
31  *           by configuring CC[0] to half of timer overflow value. Events are created at odd number of seconds.
32  *           For example, events are created at 1,3,5,... seconds. This event can be used to start Timer 0
33  *           with Timer2->Event_Compare[0] triggering Timer 0 TASK_START through PPI.
34 */
35 static void timer2_init(void)
36 {
37     // Generate interrupt/event when half of time before the timer overflows has past, that is at 1,3,5,7... seconds from start.
38     // Check TIMER1 configuration for details
39     // now the overflow occurs every 0xFFFF/(SysClk/2^PRESCALER)
40     // = 65535/31250 = 2.097 sec */
41     ret_code_t err_code = nrf_drv_timer_init(&timer2, NULL, timer_event_handler);
42     APP_ERROR_CHECK(err_code);
43 
44     nrf_drv_timer_extended_compare(&timer2, NRF_TIMER_CC_CHANNEL0, 0x7FFFUL, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);//Timer 2 每個奇數秒(1、3、5、7……)產生一次比較匹配事件,該事件通過PPI通道1 和Timer 0 的START Task 互聯,互聯後通過該事件觸發Timer 0 的START Task。
45 }

 

PPI連接事件部分:

 1 /** @brief Function for initializing the PPI peripheral.
 2 */
 3 static void ppi_init(void)
 4 {
 5     uint32_t err_code = NRF_SUCCESS;
 6 
 7     err_code = nrf_drv_ppi_init();
 8     APP_ERROR_CHECK(err_code);
 9 
10     // Configure 1st available PPI channel to stop TIMER0 counter on TIMER1 COMPARE[0] match, which is every even number of seconds.
11     err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
12     APP_ERROR_CHECK(err_code);
13     err_code = nrf_drv_ppi_channel_assign(ppi_channel1,//PPI連接事件
14                                           nrf_drv_timer_event_address_get(&timer1, NRF_TIMER_EVENT_COMPARE0),
15                                           nrf_drv_timer_task_address_get(&timer0, NRF_TIMER_TASK_STOP));
16     APP_ERROR_CHECK(err_code);
17 
18     // Configure 2nd available PPI channel to start timer0 counter at TIMER2 COMPARE[0] match, which is every odd number of seconds.
19     err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
20     APP_ERROR_CHECK(err_code);
21     err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
22                                           nrf_drv_timer_event_address_get(&timer2, NRF_TIMER_EVENT_COMPARE0),
23                                           nrf_drv_timer_task_address_get(&timer0, NRF_TIMER_TASK_START));
24     APP_ERROR_CHECK(err_code);
25 
26     // Enable both configured PPI channels
27     err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
28     APP_ERROR_CHECK(err_code);
29     err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
30     APP_ERROR_CHECK(err_code);
31 }

 

 

 

@beautifulzzzz - 物聯網&普適計算實踐者
e-mail:[email protected] 
i-blog:blog.beautifulzzzz.com 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 虛擬機中的Linux系統克隆後,網卡配置eth0中的UUID可被克隆的系統是一樣的,這樣UUID就失去了唯一性。 我參考了該篇博客: 有時我們不小心將/etc/sysconfig/network-scripts /ifcfg-eth0(可以通過此文件進行查看UUID)刪除或者損壞,要重新編輯ifcf ...
  • 創建條件 第一種:源文件複製,目標文件不存在 可以複製,複製的目標文件的目錄必須存在(不然會報錯),複製後文件相同,表示覆制到目錄後將文件重命名 當目標文件的目錄(/dir)不存在時,會報錯 第二種:源文件複製,目標文件存在 可以複製,當有文件名相同表明覆蓋,會提示,查看文件內容,表明確實會覆蓋原文 ...
  • PIDSTAT NAME pidstat對linux任務的統計 語法 pidstat [ -C comm ] [ -d ] [ -h ] [ -I ] [ -l ] [ -p { pid [,...] | SELF | ALL } ] [ -r ] [ -t ] [ -T { TASK | CHIL ...
  • 說“血案”有寫誇張了,其實是也就熬了一夜的通宵,做運維的傷不起啊,作為一名運維工程師,像這種伺服器突發故障半夜起床的情況屬於家常便飯,見怪不怪了,開始說正事: 前幾天半夜12點左右,收到伺服器宕機的消息,然後用dell idrac 卡遠程,結果無法通過它正常開機,直接發郵件給機房,讓他們重置下idr ...
  • 文件壓縮、解壓 網路、進程 磁碟、文件使用情況 記憶體使用 1、文件壓縮、解壓 1)tar.gz文件解壓: 2)zip 文件解壓: 2、網路、進程 1)netstat 在Linux上通常使用的是: netstat –apn | grep pid 在Windows上,對應的命令是:netstat –an ...
  • 一、本實驗ADC 配置 解析度:10 位。 輸入通道:5,即使用輸入通道AIN5 檢測電位器的電壓。 ADC 基準電壓:1.2V。 二、NRF51822 ADC 管腳分佈 NRF51822 的ADC 共有8 個輸入通道,對應的管腳分佈入下圖: 三、NRF51822 ADC 原理 NRF51822 的 ...
  • (1)當vim打開一個文件的時候,可以使用 (2)對當前文件寫入: 按鍵i ,左下角會顯示insert單詞,代表可以進行文本的插入; (3)滑鼠上下左右的移動: 上:K ↑ 下:j ↓ 左:H ← 右:L → (4)換行及刪除 換行寫入: o 刪除一行 : dd 返回 u (5)保存及退出 ESC ...
  • 附帶東野圭吾小說集(txt文件)http://pan.baidu.com/s/1slMSFxj 類模塊有多種用途,主要用於以下幾個方面: 1.封裝相似功能到單個對象中 2.建立帶有屬性、方法和事件的對象 3.特為自定義集合建立類模塊 封裝相似功能: 以一個名為clsUStationDialog的類開 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...