鄙人才疏学浅,如有看不入眼的代码,烦请各位指教。
既然已经配置了GPIO,那么不来一场有间隔的灯光闪烁,就不妥了。nrf有一些定时器的配置流程,也有具体的实例,坐标:nRF5_SDK_17.0.2_d674dde\examples\peripheral\timer。官方的演示可谓详细之极,一般来说按此配置即可。
/**
* @brief Handler for timer events.
*/
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
static uint32_t i;
uint32_t led_to_invert = ((i++) % LEDS_NUMBER);
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
bsp_board_led_invert(led_to_invert);
break;
default:
//Do nothing.
break;
}
}
/**
* @brief Function for main application entry.
*/
int main(void)
{
uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
uint32_t time_ticks;
uint32_t err_code = NRF_SUCCESS;
//Configure all leds on board.
bsp_board_init(BSP_INIT_LEDS);
//Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
APP_ERROR_CHECK(err_code);
time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
nrf_drv_timer_extended_compare(
&TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
nrf_drv_timer_enable(&TIMER_LED);
但是通过浏览驱动库,我们可以找到更简便的办法。坐标:nRF5_SDK_17.0.2_d674dde\components\libraries\timer。
于是,四大战神,出来!
sdk中的简单定时器配置
ret_code_t app_timer_create(app_timer_id_t const * p_timer_id,
app_timer_mode_t mode,
app_timer_timeout_handler_t timeout_handler)
{
// Check state and parameters
VERIFY_MODULE_INITIALIZED();
if (timeout_handler == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
if (p_timer_id == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
if (((timer_node_t*)*p_timer_id)->is_running)
{
return NRF_ERROR_INVALID_STATE;
}
timer_node_t * p_node = (timer_node_t *)*p_timer_id;
p_node->is_running = false;
p_node->mode = mode;
p_node->p_timeout_handler = timeout_handler;
return NRF_SUCCESS;
}
ret_code_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context)
{
uint32_t timeout_periodic;
timer_node_t * p_node = (timer_node_t*)timer_id;
// Check state and parameters
VERIFY_MODULE_INITIALIZED();
if (timer_id == 0)
{
return NRF_ERROR_INVALID_STATE;
}
if ((timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS) || (timeout_ticks > MAX_RTC_COUNTER_VAL))
{
return NRF_ERROR_INVALID_PARAM;
}
if (p_node->p_timeout_handler == NULL)
{
return NRF_ERROR_INVALID_STATE;
}
// Schedule timer start operation
timeout_periodic = (p_node->mode == APP_TIMER_MODE_REPEATED) ? timeout_ticks : 0;
return timer_start_op_schedule(p_node,
timeout_ticks,
timeout_periodic,
p_context);
}
ret_code_t app_timer_stop(app_timer_id_t timer_id)
{
timer_node_t * p_node = (timer_node_t*)timer_id;
// Check state and parameters
VERIFY_MODULE_INITIALIZED();
if ((timer_id == NULL) || (p_node->p_timeout_handler == NULL))
{
return NRF_ERROR_INVALID_STATE;
}
p_node->is_running = false;
// Schedule timer stop operation
return timer_stop_op_schedule(p_node, TIMER_USER_OP_TYPE_STOP);
}
ret_code_t app_timer_stop_all(void)
{
// Check state
VERIFY_MODULE_INITIALIZED();
return timer_stop_op_schedule(NULL, TIMER_USER_OP_TYPE_STOP_ALL);
}
来的这四位,究竟是什么高手了?原来是四个很简单的函数,只需要创建名称和定时,简单的调用,平平无奇的语句,已知他们是程序猿的福祉了。
用这四句定时器配置,基本可以满足嵌入式软件所需的内容,不需要繁琐的init和声明。
如果只需要简单的定时器配置,按此要求即可,省去较多繁琐操作。
配置流程
1.首先我们需要新建一个定时器ID,没有什么特殊的,取一个你认得请的名字即可。APP_TIMER_DEF(ID);
/**
* @brief Create a timer identifier and statically allocate memory for the timer.
*
* @param timer_id Name of the timer identifier variable that will be used to control the timer.
*/
#define APP_TIMER_DEF(timer_id) _APP_TIMER_DEF(timer_id)
2.接着,我们看模式如何选择:
/**@brief Timer modes. */
typedef enum
{
APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */
APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */
} app_timer_mode_t;
第一个的意思是,这个定时器只会定时一次,结束后需要重新开启,而第二个则是定时结束后继续定时。
3.最后则是定时结束后触发的事件了。这个就看个人需求了
配置结果
APP_TIMER_DEF(one_time);
app_timer_create(one_time,APP_TIMER_MODE_SINGLE_SHOT,vendor_one_time_func);
APP_TIMER_DEF(more);
app_timer_create(more,APP_TIMER_MODE_REPEATED,vendor_more_func);
既然配置完成了,那么我们就可以用下面两个函数开始或者停止他们了。
void vendor_one_time_func(void * p_context)
{
nrf_gpio_pin_toggle(10);
}
让这个定时器连接到按键事件中,按下按键后过300ms,将灯反转一次。
#define one_time_ms APP_TIMER_TICKS(300);
void vendor_onetime(void)
{
app_timer_stop(one_time);
app_timer_start(one_time,one_time_ms,vendor_one_time_func)
}
接下来就是烧录验证了。
另一种配置流程
#if 1
void Vendor_fgtimer_event_init(void)
{
#if 1
uint32_t time_ms = 1; //定时器比较时间
uint32_t time_ticks;
uint32_t err_code = NRF_SUCCESS;
//配置定时器
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
err_code = nrf_drv_timer_init(&TIMER_FG, &timer_cfg, timer_sysclock_event_handler);
APP_ERROR_CHECK(err_code);
time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_FG, time_ms);
//触发定时器比较
nrf_drv_timer_extended_compare(
&TIMER_FG, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
// nrf_drv_timer_extended_compare(
// &TIMER_LED, NRF_TIMER_CC_CHANNEL0, 31250, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
//使能定时器
// nrf_drv_timer_enable(&TIMER_FG);
// Enable timer
nrf_drv_timer_enable(&TIMER_FG);
#else
app_timer_create(&m_fg_1ms_cnt_timer_id, APP_TIMER_MODE_REPEATED, timer_sysclock_event_handler);
app_timer_start(m_fg_1ms_cnt_timer_id, APP_TIMER_TICKS(1), NULL);
#endif
}
#endif
sdk.config.h中的配置
GPIO和UART也需要配置,之前忘了,在此补上。
再次提醒
先打开SDK.CONFIG.H中的配置,再烧录代码,如果鄙人有缺漏,请指出或询问清风。有需要讨论的也可咨询本人。
研发类型的需求和讨论,如有需要请联系鄙人。公司邮箱:zhongweixiong@kyohoon.com,联系电话:15507589165 钟先生