>[success] **技术支持说明**
> 1.**客服**提供简单的技术支持,一般自主学习为主
> 2.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/nb-iot)
> 3.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解!
<br/>
## **定时器简介**
顾名思义,定时器的作用是用来计算一段时间,其应用非常广泛,例如:
* 30min后关闭音乐
* 每隔1s闪烁一次LED灯
* 每隔1个小时上报一次数据
STM32F030F4P6内置了一个TIM3定时器,可提供定时服务。
<br/>
## **定时器 HAL API 设计**
为定时器设计HAL API前,需要先思考一下应用开发者需要对定时器进行什么操作。一般地,应用开发者需要设置定时时长、开启定时器和关闭定时器,因此HAL可以提供以下API供应用层调用:
* 初始化定时器并设定定时时长
* 开启定时器
* 关闭定时器
与按键类似,如果定时时间到了可以产生中断,利用中断处理函数来处理。相关架构设计如图所示。
![](https://img.kancloud.cn/b2/4e/b24e46ab309ef9bd46c3dfc14dfa01da_470x471.png =300x)
<br/>
**编写代码**
笔者在本节课配套的源代码中新建了 hal\_timer.h 和 hal\_timer.c文件,如图所示。
![](https://img.kancloud.cn/c8/7d/c87debbb628aad03c46d2e406e6e1a0a_246x495.png =250x)
###
打开本节课配套的工程,笔者把hal\_timer.c以及必要的标准库文件添加进工程了,如图所示。
![](https://img.kancloud.cn/4a/63/4a63c7cb1af4fddce720ce5d692c13d2_375x594.png =250x)
<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。
###
* **计数器**
是定时器的核心,用于记录时钟发生器产生的脉冲数量。通过这个脉冲数量,便可计算出时间
查阅STM32F030F4P6的技术参数可得知其系统时钟频率为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。
<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/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =150x)
(非商务合作**勿扰**,此处**非**技术支持)
- 课程介绍
- 配套资源下载
- 配套开发套件简介
- 简介
- 硬件组成 & 技术参数
- 电路原理图 & PCB图
- 拨码开关使用说明
- 第一部分:无线通信 开发指南
- 1.1.1 NB-IoT:技术简介
- 1.1.2 NB:CH34x USB转串口驱动安装
- 1.1.3 NB:AT 指令开发与测试
- 1.1.4 NB:基础指令集简介
- 1.1.5 NB:云端服务器
- 1.1.5.1 PuTTY 简介与安装
- 1.1.5.2 登录云端服务器
- 1.1.6 NB:移远官方工具简介
- 1.1.7 NB:使用UDP协议与云端服务器通信
- 1.1.8 NB:使用TCP协议与云端服务器通信
- 1.1.9 NB:使用MQTT协议与云端服务器通信
- 进阶课程
- 第二部分:STM32 开发指南
- 2.1 搭建开发环境
- 2.1.1 Keil MDK 简介与安装
- 2.1.2 STM32 Pack 简介与安装
- 2.1.3 CH34x 驱动简介与安装
- 2.1.4 其他开发工具
- 2.2 STM32 开发基础
- 2.2.1 新建工程
- 2.2.2 实现第1个程序
- 2.2.3 Hex 文件烧录详解
- 2.3 移植官方标准工程模板
- 2.4 GPIO实验——LED灯
- 2.5 系统延时应用
- 2.6 GPIO实验——按键
- 2.7 GPIO中断实验——按键触发
- 2.8 使用定时器TIM3
- 2.9 串口通信实验
- 2.10 ADC 实验
- 2.11 OLED显示器实验
- 2.12 SDK 设计思想
- 2.13 SDK 架构解析
- 2.14 多任务应用
- 2.15 输入型任务:按键输入
- 2.16 输入型任务:串口接收
- 课外篇:项目实战
- 基于STM32+NB-IoT的温湿度采集
- 系统简介
- 系统搭建
- 系统详解
- 1.代码编译与架构说明
- 2.DHT11温湿度传感器
- 3. 数据通信任务说明
- 版权声明与免责声明