定时机按键消抖
之前的延时消抖,是直接借助delay函数进行的,但是这样会浪费CPU的性能。我们采用延时函数的方式实现,可以实现快进快出。
定时器消抖,必须是在t3的时间点才可以,当在t1,t2的时间点每次进入中断函数都要重新开启定时器的计时
但是,这两个时间点的时间小于定时器设定的10ms,所以不会产生定时器中断,也会避免这种情况的发生。只有在t3的时刻开启,才会产生定时器中断【时间够长】,这便是定时器的消抖原理。
cpp
void filtertimer_init(unsigned int value)
{
EPIT1->CR = 0; //先清零
/*
* CR寄存器:
* bit25:24 01 时钟源选择Peripheral clock=66MHz
* bit15:4 0 1分频
* bit3: 1 当计数器到0的话从LR重新加载数值
* bit2: 1 比较中断使能
* bit1: 1 初始计数值来源于LR寄存器值
* bit0: 0 先关闭EPIT1
*/
EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);
/* 计数值 */
EPIT1->LR = value;
/* 比较寄存器,当计数器值和此寄存器值相等的话就会产生中断 */
EPIT1->CMPR = 0;
GIC_EnableIRQ(EPIT1_IRQn); /* 使能GIC中对应的中断 */
/* 注册中断服务函数 */
system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)filtertimer_irqhandler, NULL);
}
对定时器进行设置,上一章节已经详细说明了,不多赘述。核心其实计时定时器设定了10ms开启定时器中断。因为选择时钟主频是66MHZ【计一个数=1/66000000s】,所以倒计时的时间是time = (66000000/100/66000000 = 10ms)。
高精度延时实验
GPT定时器
GPT是一个32位的向上定时器【0X00000000】,也可以和一个数值进行比较,当计数值和这个数值相等的话就会发生比较事件,产生比较中断,也存在一个12位的分频器【1-4096】。
存在三个输出比较寄存器,三个是输出比较中断
两种模式:
重新启动(restart)模式:
当 GPTx_CR(x=1 , 2) 寄存器的 FRR 位清零的时候 GPT 工作在此
模式。在此模式下,当计数值和比较寄存器中的值相等的话计数值就会清零,然后重新从
0X00000000 开始向上计数,只有比较通道 1 才有此模式!向比较通道 1 的比较寄存器写入任何
数据都会复位 GPT 计数器。对于其他两路比较通道(通道 2 和 3 ),当发生比较事件以后不会
复位计数器
自由运行(free-run)模式:
当 GPTx_CR(x=1 , 2) 寄存器的 FRR 位置 1 时候 GPT 工作在此模
式下,此模式适用于所有三个比较通道,当比较事件发生以后并不会复位计数器,而是继续计
数,直到计数值为 0XFFFFFFFF ,然后重新回滚到 0X00000000 。
SWR(bit15):向此位写 1 就可以复位 GPT 定时器,当 GPT 复位完成以 后此为会自动清零
**FRR(bit9):**当此位为 0 的时候比较通道 1 工作在重新启动(restart)模式。当此位为 1 的时候所有的三个比较通道均工作在自由运行模式(free-run)
CLKSRC(bit8:6):
GPT 定时器时钟源选择位,为 0 的时候关闭时钟源;为 1 的时候选择 ipg_clk 作为时钟源;为 2 的时候选择 ipg_clk_highfreq 为时钟源;为 3 的时候选择外部时钟为 时钟源;为 4 的时候选择 ipg_clk_32k 为时钟源;为 5 的时候选择 ip_clk_24M 为时钟源。
ENMOD(bit1) : GPT 使能模式,此位为 0 的时候如果关闭 GPT 定时器,计数器寄存器保
存定时器关闭时候的计数值。此位为 1 的时候如果关闭 GPT 定时器,计数器寄存器就会清零。
EN(bit) : GPT 使能位,为 1 的时候使能 GPT 定时器,为 0 的时候关闭 GPT 定时器
PRESCALER(bit11:0): 这就是 12 位分频值, 可设置 0~4095 ,分别对应 1~4096 分频
ROV(bit5) : 回滚标志位,当计数值从 0XFFFFFFFF 回滚到 0X00000000 的时候此位置 1 。
IF2~IF1(bit4:3) : 输入捕获标志位,当输入捕获事件发生以后此位置 1 ,一共有两路输入捕
获通道。如果使用输入捕获中断的话需要在中断处理函数中清除此位。
OF3~OF1(bit2:0) :输出比较中断标志位,当输出比较事件发生以后此位置 1 ,一共有三路
输出比较通道。如果使用输出比较中断的话需要在中断处理函数中清除此位
高精度延时的原理:
才开始选择的是66MHZ的频率,然后66进行分频,所以时钟频率为1MHZ,也就是计一个数字为1us,这样我们就可以进行精确计时了,当GPTx_CNT为最大值的时候【0XFFFFFFFFus = 4294967296us = 4295s = 71.5min】。
cpp
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; /* 跳出 */
}
}
}
/*
* @description : 毫秒(ms)级延时
* @param - msdelay : 需要延时的ms数
* @return : 无
*/
void delayms(unsigned int msdelay)
{
int i = 0;
for(i=0; i<msdelay; i++)
{
delayus(1000);
}
}