PPI
1.PPI的作用:提供一个硬件通道,连接事件和任务。当事件触发时,不需要cpu的参与,硬件自行完成任务的驱动。
2.PPI通道:
1.EEP:事件端点(1个)
2.TEP:任务端点(2个,主任务+从任务)
3.PPI共有32个PPI通道(0~31),其中有12已经被预编译(20~31),其他由用户自主编程。预编译的通道也可进行分组,使用和禁止。
4.每一个PPI通道的信号都被同步到16M的时钟上。
5.nrf52832共有6个PPI分组(CHG(0)~CHG(5))
PPI常用函数
1.PPI初始阿化函数:nrf_drv_ppi_init(void)
2.PPI通道申请函数:nrfx_ppi_channel_alloc(nrf_ppi_channel* channel)
3.PPI通道配置函数:nrfx_ppi_channel_assign(channel,eep,tep)
4.PPI通道次级任务配置函数:nrfx_ppi_channel_fork_assgin(channel,ftep)
5.PPI通道使能函数:nrfx_ppi_channel_enable(channel)
6.PPI组申请函数:nrfx_ppi_group_alloc(p_group)
7.PPI组通道使能函数:nrfx_ppi_group_enable(group)
8.PPI加入通道组函数:nrfx_ppi_channel_include_in_group(channel,group)
9.多个PPI通道加入组函数:nrfx_ppi_channels_include_in_group(mask,group)
PPI示例程序
通道组只是提供一种方式管理控制多个ppi通道的方式而已(去除不影响)
#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"
#include "boards.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_ppi.h"
//定义ppi通道
nrf_ppi_channel_t ppi_channel_1;
nrf_ppi_channel_t ppi_channel_2;
//定义ppi通道组
nrf_ppi_channel_group_t ppi_group;
static void log_init(void)
{
ret_code_t err = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
/**
* ppi通道初始化函数
*/
void ppi_config(void)
{
uint32_t err = NRF_SUCCESS;
err = nrf_drv_ppi_init(); //ppi通道初始化配置
APP_ERROR_CHECK(err);
/* ppi通道1 */
err = nrf_drv_ppi_channel_alloc(&ppi_channel_1); //申请ppi通道,系统自动配置
APP_ERROR_CHECK(err);
/* 主任务 */
err = nrfx_ppi_channel_assign(ppi_channel_1,nrfx_gpiote_in_event_addr_get(13),nrfx_gpiote_out_task_addr_get(17));
APP_ERROR_CHECK(err); //使用ppi通道连接事件和任务
/* 次级任务 */
err = nrfx_ppi_channel_fork_assign(ppi_channel_1,nrfx_gpiote_out_task_addr_get(18));
APP_ERROR_CHECK(err); //使用ppi通道连接次级任务
err = nrfx_ppi_channel_enable(ppi_channel_1); //使能ppi通道
APP_ERROR_CHECK(err);
/* ppi通道2 */
err = nrf_drv_ppi_channel_alloc(&ppi_channel_2); //申请ppi通道,系统自动配置
APP_ERROR_CHECK(err);
err = nrfx_ppi_channel_assign(ppi_channel_2,nrfx_gpiote_in_event_addr_get(14),nrfx_gpiote_out_task_addr_get(17));
APP_ERROR_CHECK(err); //使用ppi通道连接事件和任务
err = nrfx_ppi_channel_enable(ppi_channel_2); //使能ppi通道
APP_ERROR_CHECK(err);
/* ppi通道组 */
err = nrfx_ppi_group_alloc(&ppi_group); //申请ppi通道组
APP_ERROR_CHECK(err);
err = nrfx_ppi_channel_include_in_group(ppi_channel_1,ppi_group); //将通道1加入通道组中
//nrfx_ppi_channels_include_in_group()这个函数是多个ppi通道加入PPI组,注意区分(channel有无带s)
APP_ERROR_CHECK(err);
err = nrfx_ppi_channel_include_in_group(ppi_channel_2,ppi_group); //将通道2加入通道组中
APP_ERROR_CHECK(err);
err = nrfx_ppi_group_enable(ppi_group); //使能ppi通道组
APP_ERROR_CHECK(err);
}
int main(void)
{
log_init();
//gpiote初始化
ret_code_t err;
err = nrf_drv_gpiote_init(); //只能初始化一次(共享资源)
//输出任务
APP_ERROR_CHECK(err);
nrf_drv_gpiote_out_config_t task_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true); //定义gpiote电平翻转任务结构体
/* 主任务 */
err = nrf_drv_gpiote_out_init(17,&task_config); //配置gpiote引脚17
APP_ERROR_CHECK(err);
nrf_drv_gpiote_out_task_enable(17); //gpiote任务使能
/* 次级任务 */
err = nrf_drv_gpiote_out_init(18,&task_config); //配置gpiote引脚18
APP_ERROR_CHECK(err);
nrf_drv_gpiote_out_task_enable(18); //gpiote任务使能
//输入事件
nrf_drv_gpiote_in_config_t event_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true); //设置为下降沿模式触发,配置为port事件时为false
event_config.pull = NRF_GPIO_PIN_PULLUP; //设置gpio为上拉模式
/* 事件1 */
err = nrf_drv_gpiote_in_init(13,&event_config,NULL); //使用ppi通道连接事件和任务,不需要创建事件回调函数
APP_ERROR_CHECK(err);
nrf_drv_gpiote_in_event_enable(13,true); //gpiote事件使能
/* 事件2 */
err = nrf_drv_gpiote_in_init(14,&event_config,NULL); //使用ppi通道连接事件和任务,不需要创建事件回调函数
APP_ERROR_CHECK(err);
nrf_drv_gpiote_in_event_enable(14,true); //gpiote事件使能
ppi_config(); //ppi通道初始化
nrf_gpio_cfg_input(15,NRF_GPIO_PIN_PULLUP); //设置gpio输入模式,作为ppi组的开关
nrf_gpio_cfg_input(16,NRF_GPIO_PIN_PULLUP);
NRF_LOG_INFO("GPIOTE example started");
NRF_LOG_FLUSH();
while(1)
{
if(nrf_gpio_pin_read(15) == 0)
{
nrf_delay_ms(10);
if(nrf_gpio_pin_read(15) == 0)
nrfx_ppi_group_enable(ppi_group);
}
else if(nrf_gpio_pin_read(16) == 0)
{
nrf_delay_ms(10);
if(nrf_gpio_pin_read(16) == 0)
nrfx_ppi_group_disable(ppi_group);
}
}
}