简介:在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的频率进行翻转。
标签:err,code,RTC,rtc,PPI,nrf,drv,驱动 From: https://www.cnblogs.com/HW-liu/p/17926414.html