The previous article analyzed the code of the first 10 basic experiments, starting from here to analyze the next 10 ~
First, the PPI principle:
PPI (Programmable peripheral interconnect), Chinese translation is a programmable peripheral interconnect.
The PPI approach is set up inside nRF51822, allowing interconnection between different peripherals through tasks and events, without the need for CPU involvement.
The PPI allows tasks and events to be connected together through channels. The PPI channel consists of two endpoints:
- Task endpoint: Task end-point (TEP).
- Incident Endpoint: Event end-point (EEP).
The so-called interconnection is to write the task endpoint to the task register address that needs to be connected, the event endpoint writes need to connect the event register address, and then enable the PPI channel, that is, the realization of the task and event interconnection.
There are two ways to enable and close the PPI channel:
- 1) Set the Chen,chenset and CHENCLR registers independently.
- 2) Enable and close tasks through the PPI Channel group. In this way, before triggering a task, you need to configure which PPI channels belong to which group.
Second, the Operation logic:
In the experiment, 3 timers were used: Timer 0, Timer 1, and timer 2.
1) Timer 0 is configured as a counter, which is triggered once per 100ms in the main loop, and the count value is printed through the serial port.
2) Timer 1 per even seconds (2, 4, 6, 8 ...) Generates a comparison match event that is connected through the stop task of PPI channel 0 and timer 0, which triggers a stop task for timer 0 through the event.
3) Timer 2 each odd second (1, 3, 5, 7 ...) Generates a comparison match event that is connected through the start task of PPI Channel 1 and timer 0, which triggers the start task of timer 0 through the event.
The experimental principle is shown in diagram 1:
Third, core code analysis
After the system runs, in the cycle Timer 0 counter count value increases every 100ms, in even seconds, Timer2 produces a comparison match event, through the PPI trigger Timer 0 stop Task,timer 0 stops counting. At this point, although the timer 0 count is triggered every 100ms in the main loop, the count value does not increase because timer 0 has stopped. Each odd second, Timer2 produces a comparison match event that triggers a Timer 0 start Task,timer 0 recovery count through the PPI.
Main function Section:
1 intMainvoid)2 {3Timer0_init ();//Timer used to blink the LEDs.4Timer1_init ();//Timer to generate events on even number of seconds.5Timer2_init ();//Timer to generate events on odd number of seconds.6Ppi_init ();//PPI to redirect the event to the timer start/stop tasks.7 Serial Port Initialization (abbreviated) - in //enabling constant latency as indicated by PAN one "Hfclk:base current with HFCLK - //running is too high "found at Product Anomaly document found at to // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads + // - //@note This example does not go to low power mode therefore constant latency are not needed. the //however this setting would ensure correct behaviour when routing TIMER events through * //PPI (shown in this example) and low power mode simultaneously. $Nrf_power->tasks_constlat =1;Panax Notoginseng - //Start clock. theNrf_drv_timer_enable (&Timer0); +Nrf_drv_timer_enable (&timer1); ANrf_drv_timer_enable (&timer2); the + //Loop and increment the timer count value and capture value into LEDs. @note counter are only incremented between task_ START and Task_stop. - while(true) $ { $ -printf"Current cout:%d\r\n", (int) Nrf_drv_timer_capture (&timer0,nrf_timer_cc_channel0)); - the /*Increment the counter*/ -Nrf_drv_timer_increment (&Timer0);Wuyi theNrf_delay_ms ( -); - } Wu}
Timer Initialization section:
1 //Timer even handler. Not used since timer was used only for PPI.2 voidTimer_event_handler (nrf_timer_event_t event_type,void*P_context) {}3 4 /** @brief Function for Timer 0 initialization, which would be is started and stopped by Timer1 and Timer2 using PPI.5 */6 Static voidTimer0_init (void)7 {8ret_code_t Err_code = Nrf_drv_timer_init (&Timer0, NULL, Timer_event_handler);9 App_error_check (err_code);Ten } One A /** @brief Function for Timer 1 initialization. - * @details Initializes Timer 1 peripheral, creates event and interrupt every 2 seconds, - * by configuring CC[0] to Timer overflow value, we create events at even number of seconds the * For example, events is created at 2,4,6 ... seconds. This event can is used to stop Timer 0 - * with timer1->event_compare[0] triggering Timer 0 task_stop through PPI. - */ - Static voidTimer1_init (void) + { - //Configure Timer 1 to overflow every 2 seconds. Check TIMER1 configuration for details + //The overflow occurs every 0xffff/(Sysclk/2^prescaler). A //= 65535/31250 = 2.097 sec atret_code_t Err_code = Nrf_drv_timer_init (&timer1, NULL, Timer_event_handler); - App_error_check (err_code); - - Nrf_drv_timer_extended_compare (&timer1, nrf_timer_cc_channel0, 0xFFFFUL, Nrf_timer_short_ Compare0_clear_mask, false);//comparison mode, Timer 1 per even seconds (2, 4, 6, 8 ...) Generates a comparison match event that is connected through the stop task of PPI channel 0 and timer 0, which triggers a stop task for timer 0 through the event. - } - in /** @brief Function for Timer 2 initialization. - * @details Initializes Timer 2 peripheral, creates event and interrupt every 2 seconds to * by configuring cc[0] to half of timer overflow value. Events is created at odd number of seconds. + * For example, events is created at 1,3,5,... seconds. This event can is used to start Timer 0 - * with timer2->event_compare[0] triggering Timer 0 task_start through PPI. the */ * Static voidTimer2_init (void) $ {Panax Notoginseng //Generate interrupt/event When half of time before the timer overflows have past, that's at 1,3,5,7 ... seconds from S Tart. - //Check TIMER1 configuration for details the //Now the overflow occurs every 0xffff/(Sysclk/2^prescaler) + //= 65535/31250 = 2.097 sec * / Aret_code_t Err_code = Nrf_drv_timer_init (&Timer2, NULL, Timer_event_handler); the App_error_check (err_code); + - Nrf_drv_timer_extended_compare (&timer2, Nrf_timer_cc_channel0, 0x7ffful, Nrf_timer_short_compare0_clear_ MASK, False);//timer 2 each odd second (1, 3, 5, 7 ...). Generates a comparison match event that is connected through the start task of PPI Channel 1 and timer 0, which triggers the start task of timer 0 through the event. $}
PPI Connection Events section:
1 /** @brief Function for initializing the PPI peripheral.2 */3 Static voidPpi_init (void)4 {5uint32_t Err_code =nrf_success;6 7Err_code =nrf_drv_ppi_init ();8 App_error_check (err_code);9 Ten //Configure 1st available PPI Channel to stop TIMER0 counter on TIMER1 compare[0] match, which is every even number of seconds. OneErr_code = Nrf_drv_ppi_channel_alloc (&ppi_channel1); A App_error_check (err_code);Err_code = nrf_drv_ppi_channel_assign (Ppi_channel1,//ppi connection Event NRF_DR V_timer_event_address_get (&timer1, nrf_timer_event_compare0), Nrf_drv_time R_task_address_get (&timer0, Nrf_timer_task_stop)); - App_error_check (err_code); - - //Configure 2nd available PPI Channel to start Timer0 counter in TIMER2 compare[0] match, which is every odd number of seconds. +Err_code = Nrf_drv_ppi_channel_alloc (&Ppi_channel2); - App_error_check (err_code);Err_code = nrf_drv_ppi_channel_assign (ppi_channel2,22 nrf_drv_timer_e Vent_address_get (&timer2, nrf_timer_event_compare0), Nrf_drv_timer_task_ad Dress_get (&timer0, Nrf_timer_task_start)); - App_error_check (err_code); - - //Enable both configured PPI channels -Err_code =nrf_drv_ppi_channel_enable (PPI_CHANNEL1); - App_error_check (err_code); inErr_code =nrf_drv_ppi_channel_enable (PPI_CHANNEL2); - App_error_check (err_code); to}
@beautifulzzzz -The Internet of Things & ubiquitous computing practitioners
e-mail: [Email protected]
I-blog:blog.beautifulzzzz.com
[nRF51822] 8, basic experimental code Analysis Daquan · Experimental 11-ppi