nrf51822裸机教程-PPI
Programmable Peripheral Interconnect即可编程外设互联 系统,该模块是51822 提供的一个特性。 目的是为了让51822 的外围模块可以不通过处理器而自动相互作用。 工作原理很简单。 可以将PPI看做是一通道。 该通道有两个端点,一个叫event end-point,另一个为task end-point. 通过将具体的 event寄存器和 task寄存器 分别赋值到 ppi通道的event end-point和task end-point中。 那么当 event定义的事件发生时。 PPI另一端被赋值的对应的task就会自动被触发。
举个简单的例子。
按键翻转LED灯状态的实现。一般需要使用 I/O中断。在按键按下后cpu在中断处理函数中判断是否按键按下,然后再改变LED引脚状态。
这种实现就需要CPU参与其中才能工作。
而利用PPI, 则只需定义 按键按下后产生event,同时定义task为翻转引脚状态。然后分别将event和task寄存器绑定到PPI通道两端的event end-point和task end-point中。再使能PPI,之后按键按下和LED翻转状态就完全是自动进行。不需要CPU参与运算处理。 这样就在一定程度上释放了CPU,提高了工作效率。
综上,PPI的使用 就是配置下两端的event end-point和task end-point。然后使能PPI就可以了。
那么什么值可以赋值给 PPI的event end-point和task end-point呢? 这就要用到51822每个模块中定义的event和task寄存器。 只要将这些寄存器的地址赋值给PPI的两个端点就可以了。
比如GPIOTE模块中的
对于PPI模块的寄存器。简单介绍下。
CH[n].EEP和CH[n].TEP
这两个寄存器就是配置某个通道两个端点的。 将形如上面截图的GPIOTE中的模块的event和task寄存器地址对应赋值给CH[n].EEP和CH[n].TEP 就完成了通道的配置。
然后通过CHEN或者CHENSET寄存器使能自己使用的通道就可以了。
下面新建一个工程来通过PPI实现按键点灯功能。
新建工程选择自己板子使用的芯片型号:

教程中为了更直接的理解模块的使用。不使用sdk中提供的库函数,而直接操作寄存器来实现。
所以运行时环境勾选下必要的CMSIS下的CORE,Device下的Startup。因为用了gpio的函数 勾选一下nRF_Drivers下的nrf_gpio 就可以了。

然后配置jlink的设置(我的板子使用的是jlink的sw方式下载程序)。


创建main.c文件,然后添加到工程中

下面介绍main.c代码细节。
上面说过PPI的配置 就是配置 两端的event end-point和task end-point。
现在我们要实现按键点灯。
所以首先要配置 :按键 产生 一个event 和 一个翻转电平的task
这需要使用到 GPIOTE 部分。细节参考 GPIOTE教程。
配置BUTTON的按下事件。
NRF_GPIOTE->CONFIG[] = ( << ) //作为event
| ( BUTTON_PIN << ) //设置button引脚产生event
| ( << ); //button引脚高到低变化产生event
该配置使用 GPIOTE 通道1 作为event,并绑定BUTTON引脚,设置event触发事件为高到低电平的跳变。即按键按下触发event
配置 翻转电平的 task
NRF_GPIOTE->CONFIG[] = ( << ) //作为task
| ( LED_PIN << )
| ( << ) //task为翻转电平
| ( << ); //初始电平为高
改配置 使用 GPIOTE 通道0 作为task, 并绑定 led引脚,设task为toggle,即task被执行时led改变状态,引脚初始电平为高(led灭)
GPIOTE的Event和task配置好后。就需要将其绑定到PPI上。
在GPIOTE中:
因为event产生(按键按下时)时, 产生event[1]会被置位(BUTTON使用的是GPIOTE通道1)
而
而 OUT[0](LED使用的是GPIOTE通道0)被置位时,上面定义的task(led翻转)就会执行。
所以在PPI两端绑定的就是这两个寄存器地址的值。
NRF_PPI->CH[].EEP = (uint32_t)(&NRF_GPIOTE->EVENTS_IN[]);
NRF_PPI->CH[].TEP = (uint32_t)(&NRF_GPIOTE->TASKS_OUT[]);
最后使能一下PPI通道0 就可以了。
下面是完整代码
程序中都是直接使用NRF_GPIOTE和NRF_PPI来操作模块。这两个宏是在nrf51.h文件中定义的
#include "nrf51.h"
#include "nrf_gpio.h"
#define LED (22)
#define BUTTON (18)
int main(void){
nrf_gpio_cfg_input(BUTTON, NRF_GPIO_PIN_PULLUP);
NRF_GPIOTE->CONFIG[] = ( << )
| ( LED << )
| ( << )
| ( << );
NRF_GPIOTE->CONFIG[] = ( << )
| ( BUTTON << )
| ( << );
//将 GPIOTE通道 1 绑定到 PPI 通道 0 的event 输入端。
//将 GPIOTE通道 0 绑定到 PPI 通道 0 的task 端
//因为 GPIOTE通道 1和0 已经分别绑定到button和led,并且对应设置为了 event和task。
//所以当button被按下(产生下降沿)的时候,会产生event事件输入给 ppi通道0的 事件输入端,然后ppi 0的task端就会自动被触发,即led电平翻转
NRF_PPI->CH[].EEP = (uint32_t)(&NRF_GPIOTE->EVENTS_IN[]);
NRF_PPI->CH[].TEP = (uint32_t)(&NRF_GPIOTE->TASKS_OUT[]); //注意,这里赋值要取地址
//使能PPI通道 0
NRF_PPI->CHENSET = 0x01;
);
;
}
nrf51822裸机教程-PPI的更多相关文章
- nrf51822裸机教程-PWM
先简单介绍一下PWM的原理. 原理很简单. 假设COUNTER是个从0开始递增的计数器. 我们设置两个值 counter0 和counter1 在 COUNTER 计数到counter0的值时候翻转 ...
- nrf51822裸机教程-GPIOTE
GPIO通常都会具有中断功能,上一讲的GPIO中并没有涉及到中断的相关寄存器. 51822将GPIO的中断相关做成了一个单独的模块GPIOTE,这个模块不仅提供了GPIO的中断功能,同时提供了 通过t ...
- nrf51822裸机教程-IIC
关于IIC总线的核心有以下几点: :时钟线高电平期间必须保持数据线不变. :时钟线低电平期间可以改变数据. :时钟线和数据线上都要接上拉电阻,以使总线不工作时,两根线的电平都处于高电平状态. :每个传 ...
- nrf51822裸机教程-UART
art硬件模块通常都有内置的硬件接收buff,比如51822的硬件uart模块图如下 因为通常接收到uart数据时都会做一些处理.比如保存到数据,或者对数据做一些判断之类的. 如果uart的波特率设置 ...
- nrf51822裸机教程-RTC
RTC0被协议栈使用了.所以在跑蓝牙程序的情况下.RTC0不能使用. RTC相关寄存器如下: EVTEN,EVTENSET,EVTENCLR. 这三个寄存器用来设置是否使能某个事件.(TICK,OVR ...
- nrf51822裸机教程-SPI(主)
关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...
- nrf51822裸机教程-硬件timer
该讲介绍51822的Timer/Counter模块工作在timer模式下(定时器模式,还可以工作为计数器模式) 如何操作 51822的Timer/Counter结构如下图所示 Timer模块从PCLK ...
- nrf51822裸机教程-GPIO
首先看看一下相关的寄存器说明 Out寄存器 输出设置寄存器 每个比特按顺序对应每个引脚,bit0对应的就是 引脚0 该寄存器用来设置 引脚作为输出的时候的 输出电平为高还是低. 与输出设置相关的 还有 ...
- [nRF51822] 9、基础实验代码解析大全 · 实验12 - ADC
一.本实验ADC 配置 分辨率:10 位. 输入通道:5,即使用输入通道AIN5 检测电位器的电压. ADC 基准电压:1.2V. 二.NRF51822 ADC 管脚分布 NRF51822 的ADC ...
随机推荐
- 几种php 删除数组元素方法
几种php教程 删除数组元素方法在很多情况下我们的数组会出现重复情况,那我们删除数组中一些重复的内容怎么办,这些元素我必须保持他唯一,所以就想办法来删除它们,下面利用了遍历查询来删除重复数组元素的几种 ...
- Hark的数据结构与算法练习之珠排序
---恢复内容开始--- 算法说明 珠排序是分布排序的一种. 说实在的,这个排序看起来特别的巧妙,同时也特别好理解,不过不太容易写成代码,哈哈. 这里其实分析的特别好了,我就不画蛇添足啦. 大家看一 ...
- Oracle创建表空间和表
创建表空间和表ORACLE物理上是由磁盘上的以下几种文件:数据文件和控制文件和LOGFILE构成的oracle中的表就是一张存储数据的表.表空间是逻辑上的划分.方便管理的.数据表空间 (Tablesp ...
- Codeforces Round #293 (Div. 2)
A. Vitaly and Strings 题意:两个字符串s,t,是否存在满足:s < r < t 的r字符串 字符转处理:字典序排序 很巧妙的方法,因为s < t,只要找比t字典 ...
- java多次替换(replace不行)
import java.util.regex.Matcher; import java.util.regex.Pattern; public class test { public static vo ...
- BZOJ2610 : [Poi2003]Monkeys
考虑离线,将删边操作倒过来变成加边,等价于询问每个点什么时候与1连通 使用并查集维护,每次合并时如果有一边是1所在连通块,就把另一边的所有点的答案更新 #include<cstdio> # ...
- clumsy 0.1 测试工具(延迟\掉包\节流\重发\乱序\篡改)
clumsy : http://jagt.github.io/clumsy/可以模拟以下几种场景: 延迟(Lag),把数据包缓存一段时间后再发出,这样能够模拟网络延迟的状况. 掉包(Drop),随机丢 ...
- TYVJ P1053 字符串的展开 Label:字符 水
背景 NOIP2007年提高组第2道 描述 在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或“4-8”的子串,我们就把它当作一种简 ...
- 【POJ】1151 Atlantis(线段树)
http://poj.org/problem?id=1151 经典矩形面积并吧.....很简单我就不说了... 有个很神的地方,我脑残没想到: 将线段变成点啊QAQ这样方便计算了啊 还有个很坑的地方, ...
- hiho#1145 : 幻想乡的日常
描述 幻想乡一共有n处居所,编号从1到n.这些居所被n-1条边连起来,形成了一个树形的结构. 每处居所都居住着一个小精灵.每天小精灵们都会选出一个区间[l,r],居所编号在这个区间内的小精灵一起来完成 ...