[NCS] nrf5340 rtc使用
1.1 API介绍
-
NRFX_TIMER_INSTANCE
/** @brief 创建定时器结构体指针. */
#define NRFX_TIMER_INSTANCE(id) \
{ \
.p_reg = NRFX_CONCAT_2(NRF_TIMER, id), \
.instance_id = NRFX_CONCAT_3(NRFX_TIMER, id, _INST_IDX), \
.cc_channel_count = NRF_TIMER_CC_CHANNEL_COUNT(id), \
}
-
nrfx_timer_init
/**
* @brief 初始化定时器
*
* @param[in] p_instance 为定时器结构体指针.
* @param[in] p_config 定时器配置参数.
* @param[in] timer_event_handler 定时器处理程序.
*
* @retval NRFX_SUCCESS 成功初始化.
* @retval NRFX_ERROR_INVALID_STATE 已经初始化.
*/
nrfx_err_t nrfx_timer_init(nrfx_timer_t const * p_instance,
nrfx_timer_config_t const * p_config,
nrfx_timer_event_handler_t timer_event_handler);
-
nrfx_timer_uninit
/**
* @brief 取消定时器初始化.
*
* @param[in] p_instance 为定时器结构体指针.
*/
void nrfx_timer_uninit(nrfx_timer_t const * p_instance);
-
nrfx_timer_enable
/**
* @brief 使能定时器.
*
* @param[in] p_instance 为定时器结构体指针.
*/
void nrfx_timer_enable(nrfx_timer_t const * p_instance);
-
nrfx_timer_disable
/**
* @brief 关闭定时器.
*
* The timer will allow to enter the lowest possible SYSTEM_ON state
* only after this function is called.
*
* @param[in] p_instance 为定时器结构体指针.
*/
void nrfx_timer_disable(nrfx_timer_t const * p_instance);
-
nrfx_timer_pause
/**
* @brief 终止定时器.
*
* @param[in] p_instance 为定时器结构体指针.
*/
void nrfx_timer_pause(nrfx_timer_t const * p_instance);
-
nrfx_timer_resume
/**
* @brief 恢复定时器.
*
* @param[in] p_instance 为定时器结构体指针.
*/
void nrfx_timer_resume(nrfx_timer_t const * p_instance);
-
nrfx_timer_clear
/**
* @brief 清除定时器。
*
* @param[in] p_instance 为定时器结构体指针.
*/
void nrfx_timer_clear(nrfx_timer_t const * p_instance);
1.2 移植
1.2.1 bsp_timer.h
#ifndef __BSP_TIMER_H
#define __BSP_TIMER_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <zephyr/kernel.h>
/*
在此定义若干个软件定时器全局变量
注意,必须增加__IO 即 volatile,因为这个变量在中断和主程序中同时被访问,有可能造成编译器错误优化。
*/
#define TMR_COUNT 2 /* 软件定时器的个数 (定时器ID范围 0 - 3) */
/* 定时器结构体,成员变量必须是 volatile, 否则C编译器优化时可能有问题 */
typedef enum
{
TMR_ONCE_MODE = 0, /* 一次工作模式 */
TMR_AUTO_MODE = 1 /* 自动定时工作模式 */
} tmr_mode_t;
/* 定时器结构体,成员变量必须是 volatile, 否则C编译器优化时可能有问题 */
typedef struct
{
volatile uint8_t Mode; /* 计数器模式,1次性 */
volatile uint8_t Flag; /* 定时到达标志 */
volatile uint32_t Count; /* 计数器 */
volatile uint32_t PreLoad; /* 计数器预装值 */
} soft_tmr_t;
/* 提供给其他C文件调用的函数 */
void bsp_StartTimer(uint8_t _id, tmr_mode_t n_timer_mode);
void bsp_StopTimer(uint8_t _id);
void bsp_InitTimer(void);
#ifdef __cplusplus
}
#endif
#endif //__BSP_TIMER_H
1.2.2 bsp_timer.c
#include "bsp_timer.h"
#include <nrfx_log.h>
#include <nrfx_timer.h>
/** @brief Symbol specifying timer instance to be used. */
#define TIMER_INST_IDX_0 0
#define TIMER_INST_IDX_1 1
/** @brief Symbol specifying time in milliseconds to wait for handler execution. */
#define TIME_TO_WAIT_10_MS 10UL
#define TIME_TO_WAIT_50_MS 50UL
/* 定于软件定时器结构体变量 */
static soft_tmr_t s_tTmr[TMR_COUNT] = {0};
uint32_t desired_ticks;
static void
timer0_handler(nrf_timer_event_t event_type, void *p_context)
{
if (event_type == NRF_TIMER_EVENT_COMPARE0)
{
// NRFX_LOG_INFO("timer0");
printf("timer0\r\n");
if (s_tTmr[0].Mode == TMR_AUTO_MODE)
{
nrfx_timer_t timer_inst_0 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_0);
nrfx_timer_clear(&timer_inst_0);
nrfx_timer_resume(&timer_inst_0);
}
}
}
static void
timer1_handler(nrf_timer_event_t event_type, void *p_context)
{
if (event_type == NRF_TIMER_EVENT_COMPARE0)
{
NRFX_LOG_INFO("timer1");
printf("timer1\r\n");
if (s_tTmr[1].Mode == TMR_AUTO_MODE)
{
nrfx_timer_t timer_inst_1 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_1);
nrfx_timer_clear(&timer_inst_1);
nrfx_timer_resume(&timer_inst_1);
}
}
}
void bsp_StartTimer(uint8_t _id, tmr_mode_t n_timer_mode)
{
if (_id == 0)
{
s_tTmr[0].Mode = n_timer_mode;
nrfx_timer_t timer_inst_0 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_0);
nrfx_timer_enable(&timer_inst_0);
NRFX_LOG_INFO("Timer0 status: %s", nrfx_timer_is_enabled(&timer_inst_0) ? "enabled" : "disabled");
}
else if (_id == 1)
{
s_tTmr[1].Mode = n_timer_mode;
nrfx_timer_t timer_inst_1 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_1);
nrfx_timer_enable(&timer_inst_1);
NRFX_LOG_INFO("Timer1 status: %s", nrfx_timer_is_enabled(&timer_inst_1) ? "enabled" : "disabled");
}
}
void bsp_StopTimer(uint8_t _id)
{
if (_id == 0)
{
nrfx_timer_t timer_inst_0 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_0);
nrfx_timer_pause(&timer_inst_0);
NRFX_LOG_INFO("Timer0 stop");
}
else if (_id == 1)
{
nrfx_timer_t timer_inst_1 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_1);
nrfx_timer_pause(&timer_inst_1);
NRFX_LOG_INFO("Timer1 stop");
}
}
void bsp_InitTimer(void)
{
nrfx_err_t status;
/* timer 0 */
nrfx_timer_t timer_inst_0 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_0);
uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer_inst_0.p_reg);
nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
config.bit_width = NRF_TIMER_BIT_WIDTH_32;
config.p_context = "Timer0";
status = nrfx_timer_init(&timer_inst_0, &config, timer0_handler);
NRFX_ASSERT(status == NRFX_SUCCESS);
#if defined(__ZEPHYR__)
IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER_INST_IDX_0)), IRQ_PRIO_LOWEST,
NRFX_TIMER_INST_HANDLER_GET(TIMER_INST_IDX_0), 0);
#endif
nrfx_timer_clear(&timer_inst_0);
/* Creating variable desired_ticks to store the output of nrfx_timer_ms_to_ticks function */
desired_ticks = nrfx_timer_ms_to_ticks(&timer_inst_0, TIME_TO_WAIT_10_MS);
NRFX_LOG_INFO("Time to wait: %lu ms", TIME_TO_WAIT_10_MS);
/*
* Setting the timer channel NRF_TIMER_CC_CHANNEL0 in the extended compare mode to stop the timer and
* trigger an interrupt if internal counter register is equal to desired_ticks.
*/
nrfx_timer_extended_compare(&timer_inst_0, NRF_TIMER_CC_CHANNEL0, desired_ticks,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK, true);
/* timer 1 */
nrfx_timer_t timer_inst_1 = NRFX_TIMER_INSTANCE(TIMER_INST_IDX_1);
base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer_inst_1.p_reg);
nrfx_timer_config_t config1 = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
config1.bit_width = NRF_TIMER_BIT_WIDTH_32;
config1.p_context = "Timer1";
status = nrfx_timer_init(&timer_inst_1, &config1, timer1_handler);
NRFX_ASSERT(status == NRFX_SUCCESS);
#if defined(__ZEPHYR__)
IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER_INST_IDX_1)), IRQ_PRIO_LOWEST,
NRFX_TIMER_INST_HANDLER_GET(TIMER_INST_IDX_1), 0);
#endif
nrfx_timer_clear(&timer_inst_1);
/* 转滴答计数 */
desired_ticks = nrfx_timer_ms_to_ticks(&timer_inst_1, TIME_TO_WAIT_50_MS);
NRFX_LOG_INFO("Time to wait: %lu ms", TIME_TO_WAIT_50_MS);
/*
* Setting the timer channel NRF_TIMER_CC_CHANNEL0 in the extended compare mode to stop the timer and
* trigger an interrupt if internal counter register is equal to desired_ticks.
*/
nrfx_timer_extended_compare(&timer_inst_1, NRF_TIMER_CC_CHANNEL0, desired_ticks,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK, true);
}
1.2.3 main()添加
bsp_InitTimer();
bsp_StartTimer(0, TMR_AUTO_MODE);
bsp_StartTimer(1, TMR_AUTO_MODE);
在进入while()之前添加此函数即可。
1.3 测试
程序中设置的时间是timer0——10ms,timer1——50ms.可以看出是有效的运行5个timer0和1个timer1的。

2 基于zephyr实现
此例程基于LED的例程修改,不懂的可以翻看之前的GPIO设置博客。
2.1 prj.comf文件使能RTC
CONFIG_LOG=y #开启log打印
CONFIG_NRF53_SYNC_RTC=y #使能rtc
2.2 main修改
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include "bsp_led.h"
#include <zephyr/device.h>
#include <zephyr/sys/printk.h>
#include <zephyr/logging/log.h>/* log头文件 */
LOG_MODULE_REGISTER(main);
/* 定时器延迟 */
#define TIME0_MS 50
#define TIME1_MS 200
/* 定时器处理函数 */
static void timeout_handler0(struct k_timer *timer);
static void timeout_handler1(struct k_timer *timer);
/* 初始化定时器 */
K_TIMER_DEFINE(timer, timeout_handler0, NULL);
K_TIMER_DEFINE(timer1, timeout_handler1, NULL);
static void timeout_handler0(struct k_timer *timer)
{
uint32_t now = sys_clock_tick_get_32();
bsp_LedToggle(0);
LOG_INF("timer 0 at %d ticks", now);
}
static void timeout_handler1(struct k_timer *timer)
{
uint32_t now = sys_clock_tick_get_32();
bsp_LedToggle(1);
LOG_INF("timer 1 at %d ticks", now);
}
int main(void)
{
int ret;
bsp_InitLed(); /* LED初始化 */
LOG_INF("zephyr using rtc");
k_timer_start(&timer, K_MSEC(TIME0_MS), K_MSEC(TIME0_MS)); /* 启动定时器 */
k_timer_start(&timer1, K_MSEC(TIME1_MS), K_MSEC(TIME1_MS));
return 0;
}
2.3 测试



浙公网安备 33010602011771号