linuxARM裸机学习笔记(5)----定时机按键消抖和高精度延时实验

定时机按键消抖

之前的延时消抖,是直接借助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);
	}
}
相关推荐
hopetomorrow17 分钟前
学习路之压力测试--jmeter安装教程
学习·jmeter·压力测试
hopetomorrow18 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
/**书香门第*/1 小时前
Cocos creator 3.8 支持的动画 7
学习·游戏·游戏引擎·游戏程序·cocos2d
美式小田1 小时前
单片机学习笔记 9. 8×8LED点阵屏
笔记·单片机·嵌入式硬件·学习
猫爪笔记1 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html
_不会dp不改名_1 小时前
HCIA笔记3--TCP-UDP-交换机工作原理
笔记·tcp/ip·udp
-一杯为品-2 小时前
【51单片机】程序实验5&6.独立按键-矩阵按键
c语言·笔记·学习·51单片机·硬件工程
风尚云网3 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
熙曦Sakura3 小时前
完全竞争市场
笔记
EterNity_TiMe_4 小时前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip