nordic—RTC+PPI定时驱动某外设做非单次触发(本次测试为驱动GPIO口做电平翻转)
简介:在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口做电平翻转)的更多相关文章
- 《ServerSuperIO Designer IDE使用教程》-1.标准Modbus和非标准协议的使用、测试以及驱动开发。附:v4.2发布
ServerSuperIO Designer IDE v4.2版本更新内容: 增加ServerSuperIO.Host运行程序,可以使用IDE进行测试,Host为运行环境. 针对设备驱动增加导入监测点 ...
- linux驱动学习(八) i2c驱动架构(史上最全) davinc dm368 i2c驱动分析【转】
转自:http://blog.csdn.net/ghostyu/article/details/8094049 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 预备知识 lin ...
- linux测试 scullpipe 驱动
我们已经见到了 scullpipe 驱动如何实现阻塞 I/O. 如果你想试一试, 这个驱动的源码 可在剩下的本书例子中找到. 阻塞 I/O 的动作可通过打开 2 个窗口见到. 第一个可运行 一个命令诸 ...
- 使用“纯”Servlet做一个单表的CRUD操作
使用"纯"Servlet做一个单表的CRUD操作 每博一文案 庄子说:"独往独来,是谓独有.独有之人,是谓至贵".热闹是别人的狂欢,而孤独是自己的自由. 相聚总 ...
- 【nginx配置】nginx做非80端口转发
一个场景 最近在使用PHP重写一个使用JAVA写的项目,因为需要查看之前的项目,所以要在本地搭建一个Tomcat来跑JAVA的项目.搭建成功后,因为Tomcat监听的端口是8080,因此,访问的URL ...
- linux驱动初探之杂项设备(控制两个GPIO口)
关键字:linux驱动.杂项设备.GPIO 此驱动程序控制了外接的两个二极管,二极管是低电平有效. 上一篇博客中已经介绍了linux驱动程序的编写流程,这篇博客算是前一篇的提高篇,也是下一篇博客(JN ...
- windows下给用非exe格式的文件安装网卡驱动
之前我只知道用驱动精灵来给新机器装网卡驱动,或者用下载好的exe格式文件给非新机器装网卡驱动. 今天下载了一个非exe格式的文件,就不知道怎么装了,百度了一下才知道,可以通过:”设备管理器“-> ...
- Linux设备驱动之IIO子系统——Triggered buffer support触发缓冲支持
Triggered buffer support触发缓冲支持 在许多数据分析应用中,能够基于某些外部信号(触发器)捕获数据是比较有用的. 这些触发器可能是: 数据就绪信号 连接到某个外部系统的IRQ线 ...
- 把www.domain.com均衡到本机不同的端口 反向代理 隐藏端口 Nginx做非80端口转发 搭建nginx反向代理用做内网域名转发 location 规则
负载均衡-Nginx中文文档 http://www.nginx.cn/doc/example/loadbanlance.html 负载均衡 一个简单的负载均衡的示例,把www.domain.com均衡 ...
- 不用写代码也能做表单 —— 加载meta即可
做增删改查要写多少代码? 一个表单一套代码,十个表单十套代码吗? 我这么懒,怎么会写这么多代码? 我想做到:即使一百个表单也只需要一套代码(而且不需要复制粘贴).实现多个表单,只需要加载不同的meta ...
随机推荐
- K8s 网关选型初判:Nginx 还是 Envoy?
简介: 本文将从性能和成本.可靠性.安全性 3 方面,对两大开源实现进行比对,希望对正在做 K8s 网关选型的企业有所借鉴. 作者:张添翼(澄潭) 为了避免混淆,我们先对一些关键定义做一些厘清: 传统 ...
- 性能提升3倍、时延降低70%,阿里云企业级存储ESSD云盘再升级!
9月22日,阿里云存储年度新品发布会上,阿里云基础产品资深产品总监陈起鲲发布了其全球领先的旗舰级块存储产品ESSD的两款新规格(ESSD Auto PL.ESSD PL-X),并宣布了新增的多项企业级 ...
- 大模型 RAG 是什么
大模型 RAG(Retrieval-Augmented Generation)是一种结合了检索(Retrieval)与生成(Generation)能力的先进人工智能技术,主要用于增强大型语言模型(LL ...
- 开源相机管理库Aravis例程学习(五)——camera-api
目录 简介 例程代码 函数说明 arv_camera_get_region arv_camera_get_pixel_format_as_string arv_camera_get_pixel_for ...
- ansible系列(1)--ansible基础
目录 1. ansible概述 1.1 ansible的功能 1.2 ansible的特性 1.3 ansible的架构 1.4 ansible注意事项 1. ansible概述 Ansible 是一 ...
- 对于Docker和Podman的一点使用经验
前言:本文会以多个实际的线上例子,分享自己对于Docker和Podman的一点使用经验及踩过的坑,希望对读者有一点帮助. 本文bash脚本初步加工后可直接使用(兼容mac和linux系统),对于关键点 ...
- PostgreSQL世界上最先进的开源关系型数据库
PostgreSQL 的 Slogan 是 "世界上最先进的开源关系型数据库". PostgreSQL是一个功能非常强大.源代码开放的对象关系数据库系统(ORDBMS),在灵活的B ...
- Teamviewer 再次涨价,太贵了,有没有平替软件?
今天打开 Teamviewer 网站,吓一跳,商业版基础款价格直接翻倍. 作为行业龙头,又是德国产品,Teamviewer 一直保持着高价格的特色.这两年 Teamviewer 的价格还逐年上涨,从每 ...
- AIRIOT答疑第6期|如何使用二次开发引擎?
灵活扩展,满足客户定制化需求 AIRIOT物联网低代码平台提供丰富的前端.后台服务二次开发接口,具备灵活的组件服务部署与管理能力,对任何功能模块进行二次开发,满足客户各类二次开发需求.支持多种 ...
- sass变量的详细使用
sass变量同javascript变量,可以用来存储一些信息,并且可以重复使用. 先来对比一下css中的变量 同css变量对比 CSS 变量是由 CSS 作者定义的,它包含的值可以在整个文档或指定的范 ...