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

來源:互聯網
上載者:User

標籤:

 

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

 

一、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 at31     // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads32     //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 seconds15  *           for example, events are created at 2,4,6 ... seconds. This event can be used to stop Timer 016  *           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 details21     // The overflow occurs every 0xFFFF/(SysClk/2^PRESCALER).22     // = 65535/31250 = 2.097 sec23     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 seconds31  *           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 033  *           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 details39     // 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 channels27     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 

 

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.