多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
>[success] **技术支持说明:** >**1**.一般以自主学习为主 > **2**.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/nb-iot) > **3**.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解! <br/> ## **定时器简介** 顾名思义,定时器的作用是用来计算一段时间,其应用非常广泛,例如: * 30min后关闭音乐 * 每隔1s闪烁一次LED灯 * 每隔1个小时上报一次数据 STM32F030内置了一个TIM3定时器,可提供定时服务。 <br/> ## **定时器 HAL API 设计** 为定时器设计HAL API前,需要先思考一下应用开发者需要对定时器进行什么操作。一般地,应用开发者需要设置定时时长、开启定时器和关闭定时器,因此HAL可以提供以下API供应用层调用: * 初始化定时器并设定定时时长 * 开启定时器 * 关闭定时器 与按键类似,如果定时时间到了可以产生中断,利用中断处理函数来处理。相关架构设计如图所示。 ![](https://img.kancloud.cn/80/99/80992a4dd5ced16d9f302cf1dc68ac5d_470x471.png =300x) <br/> **编写代码** 笔者在本节课配套的源代码中新建了 hal\_timer.h 和 hal\_timer.c文件,如图所示。 ![](https://img.kancloud.cn/a4/24/a4244bfe58a04ffdb26e1be66820a740_246x495.png =300x) ### 打开本节课配套的工程,笔者把hal\_timer.c以及必要的标准库文件添加进工程了,如图所示。 ![](https://img.kancloud.cn/49/7c/497ce4a1799feba5dffbbed0c731e7b9_375x594.png =350x) <br/> hal_timer.h文件的代码如下: ### ``` #ifndef __HAL_TIMER_H__ #define __HAL_TIMER_H__ /* * 初始化定时器 * period: 定时时长(毫秒),取值范围是1 ~ 65534 * onTick: 回调函数,定时结束后自动调用此函数 */ void halTimerInit(unsigned int period, void (*onTimerIRQ)(void)); /* * 开启定时器 */ void halTimerStart(void); /* * 关闭定时器 */ void halTimerStop(void); #endif /* #ifndef __HAL_TIMER_H__ */ ``` <br/> hal_timer.c文件代码如下: ### ``` #include "hal_timer.h" #include "stm32f0xx_tim.h" /* 回调函数,定时结束后自动执行此函数 */ static void (*halTimerOnIRQ)(void) = 0; /* * 初始化定时器 * period: 定时时长(毫秒),取值范围是1 ~ 65534 * onTick: 回调函数,定时结束后自动调用此函数 */ void halTimerInit(unsigned int period, void (*onTimerIRQ)(void)) { TIM_TimeBaseInitTypeDef timer3; NVIC_InitTypeDef timer3NVIC; /* 保存回调函数 */ halTimerOnIRQ = onTimerIRQ; /* * ((TIM_Period + 1) / Clock)*(TIM_Prescaler + 1) = N ms / 1000 * * So, when TIM_Prescaler is 47999, ((TIM_Period + 1) / 48MHz) * 48000 = N ms / 1000 * * TIM_Period + 1 = (N ms / 1000) / 48000 * 48MHz = (N ms * 48000000Hz) / (1000 * 48000) * * TIM_Prescaler = N ms - 1 * * Another solution: * Clock is 48MHz, * when TIM_Prescaler is 47999, number of pulses generated in 1 second: 48000000Hz / (47999 + 1) = 1000 * So, 10 pulses can be generated in 1 millisecond. */ timer3.TIM_Period = (period > 1) ? (period - 1) : 1;//设置定时器的计数次数,即定时时长(毫秒) timer3.TIM_Prescaler = 47999;//分频系数 timer3.TIM_ClockDivision = TIM_CKD_DIV1; timer3.TIM_CounterMode = TIM_CounterMode_Up; /* TIM3 NVIC */ timer3NVIC.NVIC_IRQChannel = TIM3_IRQn; timer3NVIC.NVIC_IRQChannelPriority = 1; timer3NVIC.NVIC_IRQChannelCmd = ENABLE; /* Enable TIM3 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* Initial TIM3 */ TIM_TimeBaseInit(TIM3, &timer3); /* Enable IRQ */ TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); /* Initial TIM3 NVIC */ NVIC_Init(&timer3NVIC); } /* * 开启定时器 */ void halTimerStart() { TIM_Cmd(TIM3, ENABLE); } /* * 开启定时器 */ void halTimerStop() { TIM_Cmd(TIM3, DISABLE); } /* * TIM3定时器中断处理函数 */ void TIM3_IRQHandler() { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET && halTimerOnIRQ != 0) halTimerOnIRQ();//回调函数 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);//清空中断标志位 } ``` ### 上述代码涉及到定时器的计数原理,这里简单地讲解一下。 * **系统时钟频率** CPU的时钟发生器会以恒定的时间间隔产生脉冲,这个间歇性的脉冲可以形象理解为芯片的心跳,时钟频率则是用来描述这个心跳的速率。大家通常用1s内时钟发生器产生的脉冲数量来描述时钟频率,例如“时钟频率10 MHz”表示1s内的心跳次数为10 000 000次。 ### * **分频系数** 分频是指将时钟频率降低为原来的1/N,也称为N分频。比如当时钟频率是48MHz的时候,那么2分频是24MHz。 ### * **计数器** 是定时器的核心,用于记录时钟发生器产生的脉冲数量。通过这个脉冲数量,便可计算出时间 查阅STM32F030的技术参数可得知其系统时钟频率为48MHz,即每秒可产生48 000 000次脉冲。如果定时器的分频系统为48000(47999+1),那么定时器的时钟频率是48 000 000Hz / 48 000=1000Hz,即每秒钟产生1000次脉冲,也就是说每秒钟计数器计数1000次。于是可以得出,计数器每计算1次就是1毫秒了。 <br/> ## **使用 定时器 HAL API** 编写好按键 HAL API后,定时器的使用非常简单。在配套工程的main.c文件中添加如下代码: ``` /* * 按键回调函数,当按键被按下后即执行此函数 */ static void buttonOnClick() { halLedToggle();//反转LED灯的亮灭状态 } /* * 定时器回调函数,当定时结束后即执行此函数 */ static void timerOnIRQ() { halLedToggle();//反转LED灯的亮灭状态 } int main(void) { halSystemInit();//系统初始化 halLedInit();//LED初始化 halButtonInit(buttonOnClick);//按键初始化 halTimerInit(1000, timerOnIRQ);//定时器初始化,同时设定定时时间为1000ms halTimerStart();//启动定时器 while (1){} } ``` 上述代码同样实现了每隔1秒闪烁一次LED,与上节课不用的是,此处使用TIM3定时器。 <br/> <br/> ## **商务合作** 如有以下需求,可扫码添加管理员好友,注明“**商务合作**” * 项目定制开发,技术范围:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等; * 入驻平台,成为讲师; * 接项目赚外快; * 善学坊官网:[www.sxf-iot.com](https://www.sxf-iot.com/) ![](https://img.kancloud.cn/b7/5a/b75ac8c3da945f20568771f5935c388f_430x430.png =150x) (非商务合作**勿扰**,此处**非**技术支持)