简介:在nordic的开发中使用到RTC时,对于比较通道0/1/2/3的中断来说,如果不进行相关配置(如SDK中例子,使用的RTC比较通道就只能触发一次,不能多次触发),会导致比较中断只进入一次,如果说是使用RTC+PPI+ADC进行采样或者RTC+PPI+GPIOTE做IO口翻转等,都会只采样一次或者翻转一次就停止了,不能做的无限触发,接下来我就进行一下相关配置,让其可以无限循环起来。

测试环境:

硬件:nrf52840DK

软件路径:nordic的SDK\examples\ble_peripheral\ble_app_uart\pca10056 (在官方的SDK中的ble_app_uart例子中加入相关测试代码)

环境:keil5

一、RTC和PPI加入

1、源文件加入

加入三个文件分别是RTC和PPI的驱动文件,如果你选择ADC,作为RTC触发后要执行的任务的外设,在选择的工程没有ADC的源文件时,需要你自己加入,因为我本次测试使用的是RTC+PPI+GPIOTE去做IO口输出控制,ble_app_uart中已经有GPIOTE相关的代码了,我就不在加入了。

sdk_config.h修改,由于RTC需要低速时钟,默认是外部低速晶振,且协议栈使用了RTC0,然后app timer使用了RTC1,所以我就只能使用RTC2来进行配置,实际中你也可以使用RTC1的其余通道(app timer没有用到的通道进行,这就不改了,有需要自己看源码进行配置就行),因此有以下截图的配置

以上宏定义启动完成对于RTC和PPI来说就够了GPIOTE的我使用的例子中已经启用好了,如果你驱动的是其他外设,参考SDK中和外设相关的例子进行宏定义启动就可以了,所有外设的基础例子都在如下截图的SDK路径下:

头文件加入:

#include "nrf_drv_rtc.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_gpiote.h"

二、RTC带中断的无限循环模式

初始化RTC:

const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2);  //2就是初始化RTC2的意思
#define handle_tirgg_timer 1             //RTC通道0的中断时间
#define GPIO_pin 16          //需要翻转的GPIO口

在main中调用的代码

        uint32_t err_code;
/*############### 时钟使能 ###############*/
//ble中时钟已经初始化,不用再次初始化,否则会报错 ERROR 133 [NRF_ERROR_MODULE_ALREADY_INITIALIZED]
// err_code = nrf_drv_clock_init();
// APP_ERROR_CHECK(err_code); nrf_drv_clock_lfclk_request(NULL); /*################ RTC 初始化 #######################################*/ //Initialize RTC instance
nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
config.prescaler = 4095;
err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
APP_ERROR_CHECK(err_code);
/*禁用tick和溢出,你也可以根据需要启用*/
nrfx_rtc_tick_disable(&rtc);
nrfx_rtc_overflow_disable(&rtc);
/* 启用CC通道使能 */
err_code = nrf_drv_rtc_cc_set(&rtc,0,handle_tirgg_timer * 8,true);
APP_ERROR_CHECK(err_code);

  nrf_drv_rtc_enable(&rtc);

回调:

static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
if (int_type == NRF_DRV_RTC_INT_COMPARE0)
{
uint32_t err_code;
printf("NRF_DRV_RTC_INT_COMPARE0 \n");
/* 再次设置溢出值 */
err_code = nrf_drv_rtc_cc_set(&rtc,0,handle_tirgg_timer * 8,true);
APP_ERROR_CHECK(err_code);
/* 清除 */
nrf_drv_rtc_counter_clear(&rtc);
}
}

测试结果如下:

注意如何你需要的是tick就不需要清除,tick配置如下:

nrfx_rtc_tick_enable(&rtc);

三、RTC+PPI+GPIOTE

注意:

在这里配置的时候需要注意几个点:

  • GPIO要配置为GPIOTE的out功能,否则无法用PPI去触发输出
  • RTC初始化时,需要禁用回调功能,否则也只能执行一次
  • 需要启用PPI的fork机制,用于RTC的清除,否则无法触发循环,只能执行一次。

头文件和相关变量定义:

#include "nrf_drv_rtc.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_gpiote.h" const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2); //2就是初始化RTC2的意思
#define handle_tirgg_timer 1 //RTC通道0的中断时间
#define GPIO_pin 16 //需要翻转的GPIO口

1、RTC配置

RTC要工作需要启动低频时钟,代码如下

uint32_t err_code;
/*############### 时钟使能 ###############*/
//ble中时钟已经初始化,不用再次初始化,否则会报错 ERROR 133 [NRF_ERROR_MODULE_ALREADY_INITIALIZED]
// err_code = nrf_drv_clock_init();
// APP_ERROR_CHECK(err_code); nrf_drv_clock_lfclk_request(NULL);
/*################ RTC 初始化 #######################################*/
//Initialize RTC instance
nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
config.prescaler = 4095;
err_code = nrf_drv_rtc_init(&rtc, &config, NULL);
APP_ERROR_CHECK(err_code);
/*禁用tick和overflow降低功耗 */
nrfx_rtc_tick_disable(&rtc);
nrfx_rtc_overflow_disable(&rtc);
/* 启用CC通道使能 32768/(4095+1)=0.125ms,那么1s定时为0.125*8,所以设置定时器值是乘以8了,可以自由设置 */
err_code = nrf_drv_rtc_cc_set(&rtc,0,handle_tirgg_timer * 8,false);
APP_ERROR_CHECK(err_code);

2、GPIO口配置为GPIOTE的OUT模式

代码如下:

uint32_t err_code;
/*################ GPIO 口初始化 ############################*/
/* 前面已经有初始化了,不用再次初始化 */
// err_code = nrf_drv_gpiote_init();
// APP_ERROR_CHECK(err_code); nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true); //绑定输出端口
err_code = nrf_drv_gpiote_out_init(GPIO_pin, &out_config);
APP_ERROR_CHECK(err_code); nrf_drv_gpiote_out_task_enable(GPIO_pin);

3、PPI的配置(需要PPI的fork机制)

代码如下:

  uint32_t err_code;  
/* ############### PPI 初始化 ####################*/
err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code); /* 触发的事件地址*/
uint32_t rtc_event_addr = nrf_drv_rtc_event_address_get(&rtc,NRF_RTC_EVENT_COMPARE_0);
/* 执行的任务地址 */
uint32_t gpio_tick_addr = nrfx_gpiote_out_task_addr_get(GPIO_pin);
/* 执行二次任务的地址 */
uint32_t rtc_clear_tick_addr = nrf_drv_rtc_task_address_get(&rtc,NRF_RTC_TASK_CLEAR); err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
APP_ERROR_CHECK(err_code); /* 关联事件和任务*/
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
rtc_event_addr,
gpio_tick_addr);
APP_ERROR_CHECK(err_code); /* 关联二次任务 */
err_code = nrf_drv_ppi_channel_fork_assign( m_ppi_channel,
rtc_clear_tick_addr);
APP_ERROR_CHECK(err_code); /* 启动PPI*/
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
APP_ERROR_CHECK(err_code);

4、使能RTC

最后使能RTC:

//Power on RTC instance
nrf_drv_rtc_enable(&rtc);

结果:你会看到GPIO口16以1s的频率进行翻转,由于这是个ble例子添加的例子,一定时间后,默认是3分钟后(如果你没有修改过原始的ble代码的时间设置宏),这个ble例子将会进入sleep模式,将不会在有输出,唤醒引脚唤醒后会继续输出。

nordic—RTC+PPI定时驱动某外设做非单次触发(本次测试为驱动GPIO口做电平翻转)的更多相关文章

  1. 《ServerSuperIO Designer IDE使用教程》-1.标准Modbus和非标准协议的使用、测试以及驱动开发。附:v4.2发布

    ServerSuperIO Designer IDE v4.2版本更新内容: 增加ServerSuperIO.Host运行程序,可以使用IDE进行测试,Host为运行环境. 针对设备驱动增加导入监测点 ...

  2. linux驱动学习(八) i2c驱动架构(史上最全) davinc dm368 i2c驱动分析【转】

    转自:http://blog.csdn.net/ghostyu/article/details/8094049 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 预备知识 lin ...

  3. linux测试 scullpipe 驱动

    我们已经见到了 scullpipe 驱动如何实现阻塞 I/O. 如果你想试一试, 这个驱动的源码 可在剩下的本书例子中找到. 阻塞 I/O 的动作可通过打开 2 个窗口见到. 第一个可运行 一个命令诸 ...

  4. 使用“纯”Servlet做一个单表的CRUD操作

    使用"纯"Servlet做一个单表的CRUD操作 每博一文案 庄子说:"独往独来,是谓独有.独有之人,是谓至贵".热闹是别人的狂欢,而孤独是自己的自由. 相聚总 ...

  5. 【nginx配置】nginx做非80端口转发

    一个场景 最近在使用PHP重写一个使用JAVA写的项目,因为需要查看之前的项目,所以要在本地搭建一个Tomcat来跑JAVA的项目.搭建成功后,因为Tomcat监听的端口是8080,因此,访问的URL ...

  6. linux驱动初探之杂项设备(控制两个GPIO口)

    关键字:linux驱动.杂项设备.GPIO 此驱动程序控制了外接的两个二极管,二极管是低电平有效. 上一篇博客中已经介绍了linux驱动程序的编写流程,这篇博客算是前一篇的提高篇,也是下一篇博客(JN ...

  7. windows下给用非exe格式的文件安装网卡驱动

    之前我只知道用驱动精灵来给新机器装网卡驱动,或者用下载好的exe格式文件给非新机器装网卡驱动. 今天下载了一个非exe格式的文件,就不知道怎么装了,百度了一下才知道,可以通过:”设备管理器“-> ...

  8. Linux设备驱动之IIO子系统——Triggered buffer support触发缓冲支持

    Triggered buffer support触发缓冲支持 在许多数据分析应用中,能够基于某些外部信号(触发器)捕获数据是比较有用的. 这些触发器可能是: 数据就绪信号 连接到某个外部系统的IRQ线 ...

  9. 把www.domain.com均衡到本机不同的端口 反向代理 隐藏端口 Nginx做非80端口转发 搭建nginx反向代理用做内网域名转发 location 规则

    负载均衡-Nginx中文文档 http://www.nginx.cn/doc/example/loadbanlance.html 负载均衡 一个简单的负载均衡的示例,把www.domain.com均衡 ...

  10. 不用写代码也能做表单 —— 加载meta即可

    做增删改查要写多少代码? 一个表单一套代码,十个表单十套代码吗? 我这么懒,怎么会写这么多代码? 我想做到:即使一百个表单也只需要一套代码(而且不需要复制粘贴).实现多个表单,只需要加载不同的meta ...

随机推荐

  1. WPF 已知问题 某些设备上的应用在 WindowChromeWorker 抛出 System.OverflowException 异常

    准确来说,这个不算是 WPF 的问题,而是系统等的问题.在某些设备上的使用了 WindowChrome 功能的 WPF 应用,将在运行过程,在 WindowChromeWorker 类里面抛出 Sys ...

  2. dotnet 使用 ConfigureAwait.Fody 库设置默认的 await 同步上下文切换配置

    在 dotnet 里面,使用 await 进行异步逻辑,默认是会尝试切换回调用 await 的线程同步上下文.这个机制对于大多数的上层应用来说都是符合逻辑且方便的逻辑,例如对于带 UI 线程的 WPF ...

  3. 2019-11-29-如何入门-C++-AMP-教程

    title author date CreateTime categories 如何入门 C++ AMP 教程 lindexi 2019-11-29 08:20:37 +0800 2018-2-13 ...

  4. python01-03作业

    # 小球落地,一共运动了多少米 hight = 100 # 原始高度 distance = 0 # 和 for i in range(10): # 将 下落 高度加入到 和 中 distance += ...

  5. STM32 ADC使用问题

    基本信息 MCU:STM32F105R8T6 库:HAL 平台:MDK 精度:12位 问题一 现象: 在测量的时候,发现采样值在 1023 ~ 1042 和 1279 ~ 1290 两个区间之间无法测 ...

  6. LabView之MQTT协议使用

    一.MQTT概述 MQTT协议是一种消息列队传输协议,采用订阅.发布机制,订阅者只接收自己已经订阅的数据,非订阅数据则不接收,既保证了必要的数据的交换,又避免了无效数据造成的储存与处理.因此在工业物联 ...

  7. C#开发的CPU使用率小应用 - 开源研究系列文章 - 个人小作品

    这次用C#编写一个CPU使用率的小应用.想了一下,大概需要两个内容:一个是获取CPU使用率:一个是托盘图标的动画效果.这两个内容在上次的博文中有介绍了,此博文为具体的应用的例子. 对于要实现的应用,首 ...

  8. LLaMA 3 源码解读-大语言模型5

    本来不是很想写这一篇,因为网上的文章真的烂大街了,我写的真的很有可能没别人写得好.但是想了想,创建这个博客就是想通过对外输出知识的方式来提高自身水平,而不是说我每篇都能写得有多好多好然后吸引别人来看. ...

  9. linux服务器配置查看

    查看linux服务器配置 查硬盘信息 sblk 看sda sdb sdc之类的 以下可以看出是500G sda第一块,sdb是第二块 以下可以看出是 1T+100G 查内存 free -h 查cpu ...

  10. C 语言编程 — 逻辑控制语句

    目录 文章目录 目录 前文列表 结构化程序设计 条件分支语句 if/else 语句 if 语句 if/else 语句 if/else-if/else 语句 嵌套 if 语句 switch 语句 swi ...