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

定时器按键消抖

之前的延时消抖,是直接借助delay函数进行的,但是这样会浪费CPU的性能。我们采用延时函数的方式实现,可以实现快进快出。

linuxARM裸机学习笔记(5)----定时器按键消抖和高精度延时实验_第1张图片

 定时器消抖,必须是在t3的时间点才可以,当在t1,t2的时间点每次进入中断函数都要重新开启定时器的计时

linuxARM裸机学习笔记(5)----定时器按键消抖和高精度延时实验_第2张图片

但是,这两个时间点的时间小于定时器设定的10ms,所以不会产生定时器中断,也会避免这种情况的发生。只有在t3的时刻开启,才会产生定时器中断【时间够长】,这便是定时器的消抖原理。

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
linuxARM裸机学习笔记(5)----定时器按键消抖和高精度延时实验_第3张图片

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 定时器

 linuxARM裸机学习笔记(5)----定时器按键消抖和高精度延时实验_第4张图片

PRESCALER(bit11:0) 这就是 12 位分频值, 可设置 0~4095 ,分别对应 1~4096 分频

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

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】。
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

你可能感兴趣的:(Linux,学习,笔记)