浏览量: 258 次浏览

STM32 定时器介绍以及应用

2019年4月20日 0 作者 Nie Hen

本篇文章介绍定时器的使用方法,并应用
流水灯,以及秒表
应用展示:

定时器的作用

定时器(Timer)最基本的功能就是定时,定时功能与外设结合,可
定时发送 USART 数据
定时采集 AD数据。
将定时器与 GPIO结合起来使用,可以实现非常丰富的功能:
可以产生输出波形
可以测量输入信号的脉冲宽度
用定时器产生PWM 控制电机状态是工业控制的普遍方法

STM32中定时器

STM32中一共有11个定时器:
所有定时器都是彼此独立的,不共享任何资源
1. 内核中的SysTick
SysTick是简易的周期定时器,存在于控制器内核,其使用涉及的寄存器少,相同内核的器件间移植不需要修改程序。
2. 常规定时器,共8个,分为三类:
高级定时器2个:TIM1、TIM8 (能够产生三对PWM互补输出)
通用定时器4个:TIM2,TIM3, TIM4,TIM5,
基本定时器2个:TIM6、TIM7 (DAC触发信号 )
TIM1、TIM8的时钟由APB2的输出产生,其他6个定时器的时钟由APB1的输出产生。

通用定时器可以用来 输入捕获 输出比较 PWM输出 脉冲计数等等

SysTick 系统滴答

SysTick 位于Cortex-M3核内的NVIC中,使用SysTick编写的程序代码在相同内核的器件间移植不需要修改。
enter description here
简单 好用。
使用该功能实现LED灯的亮1s,灭1s。
通过CubeMX实现硬件资源配置。
1. 使用led灯 PA4 设为output
2. RCC 时钟源 选择外部高速时钟
enter description here
3. 时钟配置 使用外部高速时钟,内部进行9倍频作为系统时钟
enter description here
到这里系统滴答就算是配置好了
编写代码
1. 编写中断服务函数
在 stm32f1xx_hal_cotex.c 添加一个函数HAL_SYSTICK_IRQHandler
void HAL_SYSTICK_IRQHandler(void)
{
HAL_SYSTICK_Callback();
}
enter description here
2. 将中断服务函数添加
在stm32f1xx_it.c 中 SysTick_Handler函数添加一行代码
HAL_SYSTICK_IRQHandler();
enter description here
3. 编写中断函数

/* USER CODE BEGIN 4 */
void HAL_SYSTICK_Callback(void)
{
    Tick_ms++;
    if(Tick_ms%1000==0) 
    {
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);
        Tick_ms=0;
    }
}
/* USER CODE END 4 */

Tick_ms 是一个int型的,初始值为0的变量,每一ms调用一次callback,变量加一,直到1000ms即是1s的时候 GPIO电位反转(高电位变成低电位,低电位的变成高电位)。led灯亮灭变换。变量重新置零

通用定时器

通用定时器的功能是通过操作相应寄存器实现的
每个通用定时器有四类可编程的控制器:
※ 预分频器寄存器:TIMx_PSC
※ 自动重装载寄存器, TIMx_ARR
※ 当前值寄存器, TIMx_CNT
※ 比较/捕获寄存器(4个):TIMx_SR
计算定时器的工作频率
TIMx_PSC 表示分频系数
CK_CNT 表示定时器工作频率
则定时器的工作频率计算公式为:

CK_CNT=CK_PSC/ (TIMx_PSC +1)

每一个CK_CNT脉冲,TIMx_CNT值就加1,从CNT=0计数到ARR时产生中断,这时共经历ARR个时钟周期,中断频率

F_INT=CK_CNT/ (ARR+1)

enter description here
普通定时器模块的时钟为72MHz,分频比(PSC)为7199,那么我们想要得到一个1秒钟的定时,定时计数器ARR的值需要设定为 10000 分频比设置为7199
因为72 000 000 / (7199+1) = 10KHz
时钟周期T=1/10KHz=100us
100us × 10 000 = 1s

技术模式分为向上计数模式,向下计数模式,和中央对齐计数模式 。(通过控制寄存器来设置)
enter description here

应用
同样是使LED灯 亮一秒 灭一秒 循环

CubeMx配置
1. 设置LED灯的引脚 output 初始化高电平(灭)
enter description here

  1. 配置时钟
    RCC 使能外部高速时钟
    enter description here
    使用外部时钟9倍频,对APB1 进行2分频,Timer2—5的时钟频率为72MHz
    enter description here

  2. 设置定时器
    时钟源 : 使用内部定时器,预分频:7200-1 ,计数模式:向上,ARR:10000,预装载值自动重装载:使能
    enter description here
    打开中断 在NVIC Setting中 选中Enable

软件编程部分
开启定时中断:写在初始化完成之后,while(1) 之前

HAL_TIM_Base_Start_IT(&htim2);

定时中断回调函数

/* USER CODE BEGIN 4 /
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim2.Instance)
{
/
Toggle LED /
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);
}
}
/
USER CODE END 4 */

达到1s的时候 判断条件成立,对LED灯的电位进行翻转,实现一秒的亮与灭
程序下载到开发板上可以看到一个led灯一会亮 一会灭
也可以通过示波器来看PA4的输出情况
enter description here

应用

使用SysTick(我感觉很好用 )或者普通计时器
实现 流水灯 (多个led灯循环显示)
实现计时器 (将板子运行时间的秒数显示到数码管上)
两个功能来回切换 (使用按键进行切换 )

思路
在CubeMx上的配置其实都一样,主要是代码上的设计。
1. 第一个功能 将LED灯的引脚信息写入数组 ,使用遍历 在callback中 时间达到1s就对遍历到的led灯和上一个led灯进行电位反转。(这里就需要注意 第一个led灯和最后一个led灯的时候特殊处理)
2. 第二个功能 需要一个变量一直计时,然后将获取到的值使用数码管的函数进行显示。
3. 第三个功能 需要对扫描键盘进行处理,设置两个键当获取到其中一个键的时候做响应处理,而按到其他键不处理。

代码链接