嵌入式Linux之定时器中断

定时器(timer0)中断步骤:

  • 设置timer0时钟
    Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
    =50000000/(99+1)/16=31500
    在这里插入图片描述
    在这里插入图片描述
  • 设置timer0初值
    在这里插入图片描述
  • 加载初值,启动timer0
  • 设置为自动加载并启动
    在这里插入图片描述
  • 设置中断
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

定时器代码:

void timer0_init(void)
{
	//设置timer0的时钟
	//Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
	//							  =50000000/(99+1)/16
	//							  =31250
	TCFG0 = 99;
	TCFG1 &=~0xf;
	TCFG1 = 0x3;
	
	//设置timer0的初值
	TCNTB0= 15625;   //0.5s中断一次
	
	//加载初值,启动timer0
	TCON |= (1<<1);  //Update from TCNTB0 & TCMPB0

	//设置为自动加载并启动
	TCON &=~(1<<1);
	TCON |= (1<<0)|(1<<3);
	
	//设置中断
}

设置中断代码:

//初始化中断控制器
void interrupt_init(void)
{
		INTMSK &= ~((1<<0) | (1<<2) | (1<<5));
		INTMSK &= ~(1<<10);     //enable timer0

}

调用中断代码:

void handle_irq_c(void)
{
	//分辨中断源
	int bit = INTOFFSET;

	//调用对应的处理函数
	if(bit==0||bit==2||bit==5)  //eint0 or eint2 or eint 8-23
	{
		key_eint_irq(bit);//处理中断,清中断源EINTPEND
	}
	else if (bit == 10)
	{
		timer_irq();
	}
	//清中断:从源头开始清
	SRCPND=(1<<bit);
	INTPND=(1<<bit);
	
}

中断处理函数代码:

void timer_irq(void)
{
	static int cnt=0;
	int tmp;
	cnt++;
	
	tmp=~cnt;
	tmp &= 7;
	GPFDAT &= ~(7<<4);
	GPFDAT |= (tmp<<4);
}

代码改进:为了不用每次产生中断都设置中断控制器和调用中断函数,可以使用typedef函数指针进行简化。

typedef char (*PTRFUN)(int); 
PTRFUN pFun;

改进代码如下:
interrupt:

#include "s3c2440_soc.h"

typedef void (*irq_func)(int); 
irq_func irq_array[32];

//SRCPND用来显示哪个中断产生了,需要清清除对应位 bit0-eint0 bit2-eint2 bit5-eint8-23

//INTMSK用来屏蔽中断,1-masked bit0-eint0 bit2-eint2 bit5-eint8-23

//INTPND用来显示当前优先级最高,正在发生的中断,需要清除对应位 bit0-eint0 bit2-eint2 bit5-eint8-23

//INTOFFSET用来显示INTPND哪一位被设置为1

//初始化中断控制器
void interrupt_init(void)
{
		INTMSK &= ~((1<<0) | (1<<2) | (1<<5));
		INTMSK &= ~(1<<10);//enable timer0

}
//初始化按键,设为中断源

void key_eint_irq(int irq)
{
	unsigned int val =EINTPEND;
	unsigned int val1=GPFDAT;
	unsigned int val2=GPGDAT;
	 if (irq==0)//eint0 :s2
 	{
 		if (val1 & (1<<0)) /* s2 --> gpf6 */
		{
			/* 松开 */
			GPFDAT |= (1<<6);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<6);
		}
 	}
	 else if (irq==2)//eint2 :s3
 	{
 		if (val1 & (1<<2)) /* s3 --> gpf5 */
		{
			/* 松开 */
			GPFDAT |= (1<<5);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<5);
		}
 	}
	 else if (irq==5)//eint8-23,eint11--s4 eint19--s5 
 	{
 		if (val & (1<<11)) /* eint11 */
		{
			if (val2 & (1<<3)) /* s4 --> gpf4 */
			{
				/* 松开 */
				GPFDAT |= (1<<4);
			}
			else
			{
				/* 按下 */
				GPFDAT &= ~(1<<4);
			}
		}
		else if (val & (1<<19)) /* eint19 */
		{
			if (val2 & (1<<11))
			{
				/* 松开 */
				/* 熄灭所有LED */
				GPFDAT |= ((1<<4) | (1<<5) | (1<<6));
			}
			else
			{
				/* 按下: 点亮所有LED */
				GPFDAT &= ~((1<<4) | (1<<5) | (1<<6));
			}
		}
 	}

	EINTPEND=val;
}

void handle_irq_c(void)
{
	//分辨中断源
	int bit = INTOFFSET;

	//调用对应的处理函数
	irq_array[bit](bit);
	INTMSK &= ~(1<<bit);
	
	//清中断:从源头开始清
	SRCPND=(1<<bit);
	INTPND=(1<<bit);
	
}

int led_init(void)
{
	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));
}

void register_irq(int irq,irq_func fp)
{
	irq_array[irq]=fp;
	INTMSK &= ~(1<<irq);
}

void key_enit_init(void)
{
	//配置GPIO为中断引脚
	GPFCON &=~((3<<0)|(3<<4));
	GPFCON |= ((2<<0)|(2<<4));  //s2,s3被设置为中断引脚

	GPGCON &=~((3<<6)|(3<<22));
	GPGCON |= ((2<<6)|(2<<22));  //s4,s5被设置为中断引脚

	//设置中断触发方式:双边沿触发
	EXTINT0 |= ((7<<0)|(7<<8));  //s2,s3
	EXTINT1 |=(7<<12);           //s4
	EXTINT2 |=(7<<12); 			 //s5

	//设置EINTMASK使能eint11,19
	EINTMASK &=~((1<<11)|(1<<19));

	register_irq(0,key_eint_irq);
	register_irq(2,key_eint_irq);
	register_irq(5,key_eint_irq);
}

timer.c:

#include "s3c2440_soc.h"

void timer_irq(void)
{
	static int cnt=0;
	int tmp;
	cnt++;
	
	tmp=~cnt;
	tmp &= 7;
	GPFDAT &= ~(7<<4);
	GPFDAT |= (tmp<<4);
}

void timer0_init(void)
{
	//设置timer0的时钟
	//Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
	//							  =50000000/(99+1)/16
	//							  =31250
	TCFG0 = 99;
	TCFG1 &=~0xf;
	TCFG1 = 0x3;
	
	//设置timer0的初值
	TCNTB0= 15625;   //0.5s中断一次
	
	//加载初值,启动timer0
	TCON |= (1<<1);  //Update from TCNTB0 & TCMPB0

	//设置为自动加载并启动
	TCON &=~(1<<1);
	TCON |= (1<<0)|(1<<3);
	
	//设置中断
	register_irq(10,timer_irq);
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值