type
status
date
slug
summary
tags
category
icon
password
使用外设时钟TIM2让LD2闪烁
关于流程
执行流程大概可以分成个部分
- 使能GPIOA_5
- 操作GPIOA_5相关的寄存器
- 使能TIM2(通过结构图可知TIM2挂载在APB1外设总线上)
- 操作TIM2相关的寄存器
- 配置中断
下面这张图可以帮助理解
我们只需要打通箭头的那一路即可
关于寄存器
使能和操作TIM2时钟时使用到的寄存器主要有如下几个:
- RCC_APB1ENR
TIM2EN:用于使能TIM2
- TIMxCNT、TIMxPSC、TIMx_ARR(这三个寄存器用于设置TIM2的时基单元)
- TIMx_CNT是TIM2的计数器
- TIMx_PSC用于设置TIM2分频器的值
- TIMx_ARR用于设置TIM2计数器的自动重装值
- RCC_CFGR
- PPRE1:用于设置APB1时钟对AHB时钟的分频
- TIMx_CR1
ARPE:用于使能预重装
CMS:用于设置中央对齐计数模式
DIR:用于设置向上计数和向下计数模式
CEN:用于使能TIM2的计数器,或者说启动时钟
设置定时中断时使用到的时钟主要有如下几个:
- TIMx_DIER
UIE:用于使能更新中断(使能之后可以向NVIC申请中断了)
- NVIC_ISER0
关于NVIC的寄存器位于编程手册内核外设那里。这里为了设置NVIC通道需要查一下TIM2中断的编号。在参考手册EXIT那找到了TIM2外设的编号为28,所以我们应该操作NVIC_ISER0寄存器,将28位置1,这样就可以让NVIC接收中断信号了
- TIMx_SR
UIF:这是TIM2更新中断的标志位。若发生了更新事件(计数器溢出等),该位就会被置为1。
这里就可以有另一种使灯闪烁的方法,只要监视UIF位是否被置1,若置为1就将LED灯的状态取反且重置该位即可,这样就不需要用到中断了。
TIM2设置代码如下:
中断寄存器设置如下:
关于中断函数的书写
查阅启动文件可以发现TIM2的中断函数名为TIM2_IRQHandler
余下的工作就是在中断函数中书写LED状态翻转的代码了
中断函数代码如下:
这里有必要说一说IT指令
IT指令是IF-THEN的缩写,可以用于条件判断和分支跳转
值得注意的是IT语句块中的指令必须带上后缀
基本书写格式如下:
IT语句还可以进行扩展,可以在IT之后加上1到3个T或者E(E代表ELSE)
如:
一定要注意指令的后缀必须与其对应的T或者E进行对应,如NE对应E,EQ对应T
关于杂项&BUG
BUG
时间变为三倍左右?
默认外部时钟的频率是8MHz,不是25MHz,解决方案见子为博客
使能了NVIC通道但是产生不了中断?
这实际上是因为编程手册写错了....
这里可以看见NVIC_ISER0的偏移地址为0x100
而在编程手册的第四章开头说道NVIC的基地址应该是0xE000E100
所以理所当然NVIC_ISER0的地址就变为0xE000E200了
但是实际操作的时候确发现TIM2的中断函数并没有被执行
随后翻阅再次翻阅编程手册发现:
这里写到NVICISER0-NVICISER7的起始地址为0xE000E100,所以将NVIC_ISER0的偏移地址改为0后TIM2的中断函数就可以正常运行了
这说明编程手册上NVIC_ISERx处的偏移地址应该为0而不是0x100
或者说偏移地址应该是相对0xE000E000的
杂项
TIM2的时钟源是什么?
TIM2的时钟源默认是APB1的时钟
可以通过修改相关寄存器来将TIM2的时钟源设置为外部时钟(ETR)和其他的定时器(ITRx)。如果将时钟源修改为其他定时器还可以做到定时器的级联(套娃)
TIMx_CR1中的预重装有什么用?
预重装实际上就是一个影子寄存器。
当使能预重装时,如果修改了ARR的值,这个ARR的值并不会立即生效,而是等待下一次重装时再生效,这样可以避免一些BUG,比如说如果没有设置预重装,修改了ARR的值,此时ARR值立即生效,但若ARR的值小于当前计数器的值(假设计数器采用向上计数模式),此时计数器的值就将不会到达ARR值,导致计数器一直计数。
附上源代码
- 作者:Noah
- 链接:https://imnoah.top/article/AssLightUp
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。