定时器
- [1. EPIT定时器](#1. EPIT定时器)
-
- [(1) 特征:](#(1) 特征:)
- [(2) 结构:](#(2) 结构:)
- [(3) 工作模式:](#(3) 工作模式:)
- [(4) 寄存器](#(4) 寄存器)
- [(5) 配置步骤](#(5) 配置步骤)
- [(6) 定时器消抖](#(6) 定时器消抖)
- [2. GPT 定时器](#2. GPT 定时器)
-
- [(1) 特征](#(1) 特征)
- [(2) 结构](#(2) 结构)
- [(3) 工作模式](#(3) 工作模式)
- [(4) 寄存器](#(4) 寄存器)
-
- [<1> GPTx_CR 配置](#<1> GPTx_CR 配置)
- [<2> GPTx_PR 分频](#<2> GPTx_PR 分频)
- [<3> GPTx_SR 状态](#<3> GPTx_SR 状态)
- [<4> GPTx_CNT 计数](#<4> GPTx_CNT 计数)
- [<5> GPTx_OCR 比较](#<5> GPTx_OCR 比较)
- [(5) 实现高精度延时](#(5) 实现高精度延时)
-
- [<1> 步骤](#<1> 步骤)
- [<2> 实现](#<2> 实现)
1. EPIT定时器
EPIT ( Enhanced Periodic Interrupt Timer):增强的周期中断定时器
(1) 特征:
- 时钟源可选的32位向下计数器
- 12位的分频值
- 计数器和比较值相等时,产生中断
(2) 结构:
- 选择EPIT定时器的时钟源:ipg_clk,ipg_clk_32k,ipg_clk_highfreq。
- 12位的分频器,对应 1~4096分频
- 三个寄存器:EPIT_CNR(计数器),EPIT_LR(加载寄存器),EPTI_CMPR(比较寄存器)。
- 比较器
- 引脚输出:可设置 EPIT1_OUT,EPIT2_OUT输出
- 定时中断
(3) 工作模式:
set-and-forget 模式:
只要计数器计数到 0,那么就会从加载寄存器 EPITx_LR 中重新加载数据到计数器中
free-running 模式:
当计数器计数到0以后会重新从0XFFFFFFFF开始计数
(4) 寄存器
配置寄存器 EPITx_CR
CLKSRC(bit25:24): EPIT 时钟源选择位(ipg_clk=66MHz)
PRESCALAR(bit15:4): EPIT 时钟源分频值(12位)
RLD(bit3):工作模式:set-and-forget,free-running
OCIEN(bit2):比较中断使能位,
ENMOD(bit1):为 1 的时候来源于加载寄存器
EN(bit0): EPIT 使能位
EPITx_SR
OCIF(bit0) :中断标志位,此位是写 1 清零的。
(5) 配置步骤
- 设置 EPIT1 的时钟源
- 设置分频值
- 设置工作模式
- 设置计数器的初始值来源
- 使能比较中断
- 设置加载值和比较值
- EPIT1 中断设置和中断服务函数编写
- 使能 EPIT1 定时器
Tout = ((frac +1 )* value) / Tclk;
Tclk: 输入时钟(66M)
frac: 分频值
value: 加载寄存器
Tout: 输出
(6) 定时器消抖
使用定时器来实现按键消抖,防止按键中断内部出现延时函数。
上图中 t1 - t3 时间之内是,按键抖动。
t1, t2, t3 会触发按键中断。按键中断处理函数内开 10ms 的定时器中断。
因t1-t2, t2-t3的时间小于10ms,不会触发定时器中断。
t3后10ms,触发定时器中断,内部做原来的按键中断处理。
按键中断函数:
c
void filtertimer_restart(unsigned int value)
{
EPIT1->CR &= ~(1<<0); /* 先关闭定时器 */
EPIT1->LR = value; /* 计数值 */
EPIT1->CR |= (1<<0); /* 打开定时器 */
}
void gpio1_16_31_irqhandler(void)
{
filtertimer_restart(66000000/100); /* 开启定时器 */
gpio_clearintflags(GPIO1, 18); /* 清除中断标志位 */
}
2. GPT 定时器
GPT(General Purpose Timer) 通用用途定时器。比EPIT更具有通用性。
可实现的功能:测量时间间隔、生成定时脉冲、执行时间相关的操作。
(1) 特征
- 可选时钟源的 32 位向上计数器
- 两个输入捕获通道,可以设置触发方式
- 三个输出比较通道,可以设置输出模式
- 可以生成捕获中断、比较中断和溢出中断
- 计数器可以运行在重新启动(restart)或(自由运行)free-run 模式
(2) 结构
时钟选择:ipg_clk_24M、 GPT_CLK(外部时钟)、ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq。
选择 ipg_clk=66MHz
- GPT 定时器的时钟源
- 12 位分频器
- GPT 定时器内部 32 位计数器
- GPT 的两路输入捕获通道
- GPT 的两路输入捕获通道
- 输出比较寄存器,三个输出比较寄存器
- 输出比较中断
(3) 工作模式
重新启动(restart)模式和自由运行(free-run)模式
重新启动(restart)模式
当计数值和比较寄存器中的值相等的话计数值就会清零,
比较通道 1 才有此模式
自由运行(free-run)模式
当比较事件发生以后并不会复位计数器,而是继续计数,直到计数值为 0XFFFFFFFF,然后重新回滚到 0X00000000。
(4) 寄存器
<1> GPTx_CR 配置
SWR(bit15):复位 GPT 定时器,写 1 复位 GPT 定时器
FRR(bit9):运行模式,restart / free-run
CLKSRC(bit8:6):钟源选择位 001(ipg_clk)
ENMOD(bit1): 关闭后是否计数清零
EN(bit): GPT 使能位
<2> GPTx_PR 分频
PRESCALER(bit11:0),这就是 12 位分频值,可设置 0~4095,分别对应 1~4096 分频
<3> GPTx_SR 状态
ROV(bit5): 回滚标志位,计数值从 0XFFFFFFFF 回滚到 0 的时候此位置 1
IF2~IF1(bit4:3):输入捕获标志位
OF3~OF1(bit2:0):输出比较中断标志位,比较事件发生以后此位置 1
<4> GPTx_CNT 计数
保存着 GPT 定时器的当前计数值
<5> GPTx_OCR 比较
三个比较寄存器,GPTx_OCR1-3,存放这三路比较值。可用于触发中断。
(5) 实现高精度延时
设置计数频率为1M,ipg_clk=66MHz,设置 66 分频
GPTx_CNT 计数周期为 1us。
<1> 步骤
- 设置 GPT1 定时器,GPTx_CR
- 设置 GPT1 的分频值
- 设置 GPT1 的比较值
- 使能 GPT1 定时器
- 编写延时函数
<2> 实现
c
void delayus(unsigned int usdelay)
{
unsigned long oldcnt,newcnt;
unsigned long tcntvalue = 0; /* 走过的总时间 */
oldcnt = GPT1->CNT;
while(1)
{
newcnt = GPT1->CNT;
if(newcnt != oldcnt)
{
if(newcnt > oldcnt) /* GPT 是向上计数器,并且没有溢出 */
tcntvalue += newcnt - oldcnt;
else /* 发生溢出 */
tcntvalue += 0XFFFFFFFF-oldcnt + newcnt;
oldcnt = newcnt;
if(tcntvalue >= usdelay) /* 延时时间到了 */
break; /* 跳出 */
}
}
}