当前位置: 首页 > 编程日记 > 正文

[nRF51822] 8、基础实验代码解析大全 · 实验11 - PPI


前一篇分析了前十个基础实验的代码,从这里开始分析后十个~

一、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 }


相关文章:

【组队学习】【第30期】青少年编程(Scratch 三级)

小朋友们大家好,我是本次组队学习的领航员-马燕鹏,欢迎大家参加《青少年编程(Scratch 三级)》航海活动。 今天的开营有两大环节: 1、「活动介绍」介绍我们这个活动的整体设计框架。2、「规则介绍」介绍我们本次活动要…

linux resin mysql_Linux下Resin JSP MySQL的安装和配置-2

如果有,陆续(2)编辑httpd.conf# vi /usr/local/apache2/conf/httpd.conf找到ResinConfigServer localhost 6802确信其内容为:LoadModule caucho_module /usr/local/apache2/modules/mod_caucho.soResinConfigServer 192.168.1.109 6802 //即改localhost为你的计算机的实际IPCa…

胡锐锋:组队学习分享(队长)

组队学习分享(队长) 自我介绍 胡锐锋,现为Datawhale成员,目前担任《统计学习方法习题解答》开源项目的负责人,已工作近8年,由大数据平台研发工程师转变成一位项目管理人。我的人生目标是让未来的孩子们少…

[转]解析字符串的方法

解析字符串的方法 char st[]”123.45ab”; 解析这一段字符串,有很多种方法。这里介绍一个在”stdio.h”里面的函数: sscanf(…); 如果你看了如下代码,应该会有所感悟: 1 # include "stdio.h"2 3 int main() {4 char st[]"…

SpringBoot之@EnableConfigurationProperties分析

我们在用SpringBoot进行项目开发的时候,基本上都使用过ConfigurationProperties这个注解,我们在之前的文章中也说过ConfigurationPropertiesBindingPostProcessor会对标注ConfigurationProperties注解的Bean进行属性值的配置,但是我们之前没有…

mysql 自动管理内存_MySQL内存管理,内存分配器和操作系统

导读作者:Sveta Smirnova翻译:郑志江校对:徐晨亮原文 :MySQL Memory Management, Memory Allocators and Operating System本文涉及链接在文末展示当用户使用任何软件(包括MySQL)碰到内存问题时,我们第一反应就是内存泄…

采集音频和摄像头视频并实时H264编码及AAC编码

0. 前言 我在前两篇文章中写了DirectShow捕获音视频然后生成avi,再进行264编码的方法。那种方法有一些局限性,不适合实时性质的应用,如:视频会议、视频聊天、视频监控等。本文所使用的技术,适用于这种实时性的应用&…

【算法练习】校招研发工程师笔试题

请留言,说出你的解题思路和答案。稍后,我会把参考答案发到留言区。不定期整理相关的问题答案分享。 01、下面对于线性表的叙述中,不正确的是()。 (A)线性表采用顺序存储时,必须占用…

Ubuntu安装tomcat

1.从官网中下载apache-tomcat-**.tar.gz文件 2.在本地文件新建一个文件夹(tomcat),在文件夹中解压压缩包, 不需要使用root: tar -zxvf /home/xcx/下载/apache-tomcat-8.5.11.tar.gz 3.进入解压文件中使用命令,将tomcat中的文件全部设置添加读…

mysql 绑定参数_MySQL 使用 Perl 绑定参数和列

SQL 语句通常是动态构建的,用户提供一些输入,并将其内置到语句中。 程序员每次处理用户的输入时都必须谨慎。 它具有一些严重的安全隐患。 动态构建 SQL 语句的推荐方法是使用参数绑定。绑定参数可以防止 SQL 注入程序。 它会自动转义一些特殊字符并允许…

java入门(p1)进入java的世界

浅谈java世界(连载中P1) Java是一门语言,它并不是很难理解的东西,语言是来进行交流的工具,那么它用来跟谁来交互呢,所有的语言都有与其交流的对象,中文也好英文也罢,交流基本的对象应…

python __setattr__ , __getattr__

Python Class 对象或类型通过内置成员 __dict__ 来存储成员信息。 我们还可以通过重载 __getattr__ 和 __setattr__ 来拦截对成员的访问,需要注意的是 __getattr__ 只有在访问不存在的成员时才会被调用。转载于:https://www.cnblogs.com/Huayuan/archive/2013/05/17…

第01章 PyTorch简介和安装 的学习笔记

由于第一章,主要介绍Pytorch的安装,而自己的笔记本已经安装了CPU版本的Pytorch,所以第一章主要是复习了Conda的基本命令并做了5个选择题供大家练习。 课程来源:https://github.com/datawhalechina/thorough-pytorch 1、在Window…

python socket tcp客户端_python网络编程socketserver模块(实现TCP客户端/服务器)

摘录python核心编程socketserver(python3.x版本重新命名)是标准库中的网络编程的高级模块。通过将创建网络客户端和服务器所必须的代码封装起来,简化了模板,为你提供了各种各样的类。除了隐藏了实现细节之外,它督促我们使用类(面向对象的思维…

template.process(root, out)的用法(shiro项目中来的九)

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请…

java中最常用jar包的用途说明,适合初学者

jar包用途axis.jarSOAP引擎包commons-discovery-0.2.jar用来发现、查找和实现可插入式接口,提供一些一般类实例化、单件的生命周期管理的常用方法.jaxrpc.jarAxis运行所需要的组件包saaj.jar创建到端点的点到点连接的方法、创建并处理SOAP消息和附件的方法&#xff…

【青少年编程(第33周)】Scratch(三级)公益活动开营了!

2021年10月10日(周日)晚20:00我们在青少年编程竞赛交流群开展了第三十三期直播活动。我们直播活动的主要内容如下: 首先,我们奖励了上周测试超过40分的小朋友。 其次,我们讲解了上次测试中小朋友们做错的题目Scratch青…

python函数图像绘制、函数不固定_无法在函数中绘制tkinter图像

我正在制作一个垄断游戏,我试图在画布上绘制图像,但它只有在功能不起作用的情况下才会起作用:def make_image(root, location, canvas):photo PhotoImage(file root)canvas.create_image(location["X"],location["Y"],…

一些与算法有关的网站

//转自:http://www.cnblogs.com/a180285/archive/2012/01/15/2290290.html //------------------------------------------------------------------------------------------------------------------------------------------------------------ 我在网上到处找了…

【工程基础】校招研发工程师笔试题

请留言,说出你的解题思路和答案。稍后,我会把参考答案发到留言区。不定期整理相关的问题答案分享。 1、以下代码违反了什么设计原则() public class Student {public int Id;public string StudentName; }public class MClass {…

情人节学写html5微信游戏

情人节都在干什么??? 当然是写代码!!! 看某书正好以一个html5微信游戏,很适合今天的日子 附上demo:demo 请在手机上查看,pc端请切换手机调试模式,目前没弄完后…

python和idl_有前辈对比过IDL和Python的速度吗,哪个会快点?

看到这个问题,发现国外还真有人做过对比,主要在于语言特点方面,并没有详细的定量对比,贴过来大家一起乐呵乐呵。其实大体上就是之前几位答主所说的那样,主要区别在于:1.资料的多少。python资料较多2.现成的…

测试用例经验谈

1.需要测试的那个类是new出来的实例; 2.被测试的类实例的对象所需要调用的接口或者对象都是mock出来的(无论是否已经有实现)。 3.所有的接口都是根据被测试的类的需要产生的,即接口属于客户(被测试的类)。 …

中国电子学会图形化四级编程题:加减法混合运算器

「青少年编程竞赛交流群」已成立(适合6至18周岁的青少年),公众号后台回复【Scratch】或【Python】,即可进入。如果加入了之前的社群不需要重复加入。 我们将有关编程题目的教学视频已经发布到抖音号21252972100,小马老…

Bzoj4566:[HAOI2016]找相同字符

题面 Bzoj Sol 两个串拼在一起后求出后缀数组 然后显然的\(n^2\)暴力&#xff0c;就是直接枚举求\(LCP\) 又由于扫的时候是对\(height\)取\(min\) 那么可以用单调栈维护每一段的贡献相同的 # include <bits/stdc.h> # define RG register # define IL inline # define Fi…

python字符照片_python图片转字符图片

python图片转字符图片代码话不多说&#xff0c;直接上代码。***************************#-*- coding:utf-8 -*-from PIL import ImageIMG#文件路径WIDTH60HEIGHT45ascii_char list("$B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_~<>i!lI;:,\"^…

三大基本排序专题

//以下依次是冒泡、选择、插入排序 var n,i:longint;a:array[0..20] of longint;procedure BUB;var i,j,t:longint;beginfor i:1 to n-1 dofor j:1 to n-i doif a[j]>a[j1] then begin t:a[j]; a[j]:a[j1]; a[j1]:t; end;end;procedure SEL;var i,j,k,t:longint;beginfor i:…

Linux内核中锁机制之完成量、互斥量

在上一篇博文中笔者分析了关于信号量、读写信号量的使用及源码实现&#xff0c;接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题。 八、完成量 下面讨论完成量的内容&#xff0c;首先需明确完成量表示为一个执行单元需要等待另一个执行单元完成某事后方可执行&…

中国电子学会图形化四级编程题:绳子算法

「青少年编程竞赛交流群」已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 我们将有关编程题目的教学视频已经发布到抖音号21252972100&#xff0c;小马老…

域名登陆出现400_域名解析错误怎么办?

可能有些人在进行域名解析时会遇到解析错误的问题&#xff0c;遇到这样的问题该怎么办呢&#xff1f;今天小编给大家整理了一些思路&#xff0c;希望能够提供一些帮助给大家。网站域名设置目前域名解析服务很多都是由域名供应商来设置&#xff0c;也有用户在网站运营期间需要更…