完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本文摘录于本人博客:http://blog.csdn.net/chengdong1314/article/details/51594411
主程序调用的定时器初始化函数:timers_init(); 内容如下: static void timers_init(void) { // Initialize timer module, making it use the scheduler APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, true); /* YOUR_JOB: Create any timers to be used by the application. Below is an example of how to create a timer. For every new timer needed, increase the value of the macro APP_TIMER_MAX_TIMERS by one. err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler); APP_ERROR_CHECK(err_code); */ } 这个定时器初始化函数最终使用的是RTC时钟,作为整个程序的宏观脉搏,为调度器使用,当然用户也可以创建时钟。 static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE((MAX_TIMERS), (OP_QUEUES_SIZE) + 1), sizeof(uint32_t))]; 这是计算要分配的定时器内存区大小,说到底就是分配一个静态的数组,这个数组的类型是uint32_t,细看这个数组的项数,有下面这个函数: #define CEIL_DIV(A, B) /*lint -save -e573 */ ((((A) - 1) / (B)) + 1) /*lint -restore */ 可以看到,这个数组是以uint32_t就是4个字节为单位的,具体计算再看: APP_TIMER_BUF_SIZE((MAX_TIMERS), (OP_QUEUES_SIZE) + 1), 这里各个含义如下: #define APP_TIMER_BUF_SIZE(MAX_TIMERS, OP_QUEUE_SIZE) ( ((MAX_TIMERS) * APP_TIMER_NODE_SIZE) + ( APP_TIMER_INT_LEVELS * (APP_TIMER_USER_SIZE + ((OP_QUEUE_SIZE) + 1) * APP_TIMER_USER_OP_SIZE) ) ) 其中传入的变量: #define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */ #define APP_TIMER_MAX_TIMERS 2 /**< Maximum number of simultaneously created timers. */ #define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */ 也就是说 MAX_TIMERS=2 OP_QUEUE_SIZE)=4,再看其他的变量: #define APP_TIMER_NODE_SIZE 40 /**< Size of app_timer.timer_node_t (only for use inside APP_TIMER_BUF_SIZE()). */ #define APP_TIMER_USER_OP_SIZE 24 /**< Size of app_timer.timer_user_op_t (only for use inside APP_TIMER_BUF_SIZE()). */ #define APP_TIMER_USER_SIZE 8 /**< Size of app_timer.timer_user_t (only for use inside APP_TIMER_BUF_SIZE()). */ #define APP_TIMER_INT_LEVELS 3 /**< Number of interrupt levels from where timer operations may be initiated (only for use inside APP_TIMER_BUF_SIZE()). */ 从这里看APP_TIMER_BUF_SIZE函数的功能就是计算出time模块一共需要多少内存区域,然后经过CEIL_DIV函数对齐4字节的计算就知道了要分配多少个数组项给定时器模块 分配了内存区,然后下来的就是初始化rtc时钟了: uint32_t ERR_CODE = app_timer_init((PRESCALER), (MAX_TIMERS), (OP_QUEUES_SIZE) + 1, APP_TIMER_BUF, (USE_SCHEDULER) ? app_timer_evt_schedule : NULL); 该函数的源代码如下: uint32_t app_timer_init(uint32_t prescaler,//预分频器 uint8_t max_timers,//最大时间 uint8_t op_queues_size, void * p_buffer, app_timer_evt_schedule_func_t evt_schedule_func) { int i; // Check that buffer is correctly aligned检查缓冲区是否正确字对齐 if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM;//无效的参数 } // 检查空缓冲区 if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } // Stop RTC to prevent any running timers from expiring (in case of reinitialization)RTC停止 rtc1_stop(); m_evt_schedule_func = evt_schedule_func;//按键调度事件 // Initialize timer node array初始化定时器节点数组 m_node_array_size = max_timers; mp_nodes = p_buffer; for (i = 0; i < max_timers; i++) { mp_nodes[i].state = STATE_FREE; mp_nodes[i].is_running = false; } // Skip timer node array p_buffer = &((uint8_t *)p_buffer)[max_timers * sizeof(timer_node_t)]; // Initialize users array m_user_array_size = APP_TIMER_INT_LEVELS; mp_users = p_buffer; // Skip user array p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)]; // Initialize operation queues for (i = 0; i < APP_TIMER_INT_LEVELS; i++) { timer_user_t * p_user = &mp_users[i]; p_user->first = 0; p_user->last = 0; p_user->user_op_queue_size = op_queues_size; p_user->p_user_op_queue = p_buffer; // Skip operation queue p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)]; } m_timer_id_head = TIMER_NULL; m_ticks_elapsed_q_read_ind = 0; m_ticks_elapsed_q_write_ind = 0; NVIC_ClearPendingIRQ(SWI0_IRQn); NVIC_SetPriority(SWI0_IRQn, SWI0_IRQ_PRI); NVIC_EnableIRQ(SWI0_IRQn); rtc1_init(prescaler); m_ticks_latest = rtc1_counter_get(); return NRF_SUCCESS; } 首先要做的就是检查内存区是否是4字节对齐和是否存在 // Check that buffer is correctly aligned检查缓冲区是否正确字对齐 if (!is_word_aligned(p_buffer)) { return NRF_ERROR_INVALID_PARAM;//无效的参数 } // 检查空缓冲区 if (p_buffer == NULL) { return NRF_ERROR_INVALID_PARAM; } 然后停止rtc // Stop RTC to prevent any running timers from expiring (in case of reinitialization)RTC停止 rtc1_stop(); 源码如下: static void rtc1_stop(void) { NVIC_DisableIRQ(RTC1_IRQn); NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; //清除比较器 NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk; //停止比较器使能 NRF_RTC1->TASKS_STOP = 1; //停止RTC模块 nrf_delay_us(MAX_RTC_TASKS_DELAY); } 然后根据传入进来的参数给全局变量赋值: m_evt_schedule_func = evt_schedule_func;//按键调度事件 // Initialize timer node array初始化定时器节点数组 m_node_array_size = max_timers; mp_nodes = p_buffer; 主意这些全局变量,在后面才会使用,在本函数没有使用,只是赋值而已,下面给初始化定时器各个队列,比如设置定时器的使用标志和是否运行标志以及初始化操作队列 for (i = 0; i < max_timers; i++) { mp_nodes[i].state = STATE_FREE; mp_nodes[i].is_running = false; } // Skip timer node array p_buffer = &((uint8_t *)p_buffer)[max_timers * sizeof(timer_node_t)]; // Initialize users array m_user_array_size = APP_TIMER_INT_LEVELS; mp_users = p_buffer; // Skip user array p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)]; // Initialize operation queues for (i = 0; i < APP_TIMER_INT_LEVELS; i++) { timer_user_t * p_user = &mp_users[i]; p_user->first = 0; p_user->last = 0; p_user->user_op_queue_size = op_queues_size; p_user->p_user_op_queue = p_buffer; // Skip operation queue p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)]; } m_timer_id_head = TIMER_NULL; m_ticks_elapsed_q_read_ind = 0; m_ticks_elapsed_q_write_ind = 0; 然后初始化一个软件中断,这个也是给后面的定时各个函数使用的使用的 NVIC_ClearPendingIRQ(SWI0_IRQn); NVIC_SetPriority(SWI0_IRQn, SWI0_IRQ_PRI); NVIC_EnableIRQ(SWI0_IRQn); 然后是rtc时钟的初始化 rtc1_init(prescaler); 这里传入的参数是#define APP_TIMER_PRESCALER 0 下面细看这个函数 static void rtc1_init(uint32_t prescaler) { NRF_RTC1->PRESCALER = prescaler; NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI); } 主意这里只是设置rtc的分频和中断优先级,优先级不论,说说这个分频,也就是rtc的频率是32768 ,中断不可能以这个频率去跑,那只能够说明定时器模块的频率毕竟和RTC的比较器有关了,或许不同的定时器模块他的比较器的值是不一样的吧。 最后是获取一下计数值,以更新一个全局变量: m_ticks_latest = rtc1_counter_get(); 主意到这里并没有开始定时器 还有这里的定时器指的是RTC而不是51822的定时计数模块 到此初始化是分析完毕了 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
物联网工程师必备:怎么选择不同的无线连接技术,本指南帮你忙!
3262 浏览 1 评论
【DFRobot TinkerNode NB-IoT 物联网开发板试用连载】WIFI功能测试
3911 浏览 0 评论
【DFRobot TinkerNode NB-IoT 物联网开发板试用连载】Arduino的替代SublimeText3+STino
3420 浏览 0 评论
使用端口扩展器轻松高效地向IIoT端点添加具有成本效益的子节点
3969 浏览 1 评论
20611 浏览 11 评论
模组有时候复位重启后输出日志为“REBOOT_CAUSE_SECURITY_PMU_POWER_ON_RESET”的原因?
751浏览 2评论
943浏览 2评论
966浏览 1评论
1087浏览 1评论
362浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 14:17 , Processed in 1.822989 second(s), Total 75, Slave 55 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号