Learn lumit Step 16 : 定时器实验
Learn lumit Step 16 : 定时器实验++++++++++++++++++++++++++++++++++++++++++++++++++++++
这一节主要介绍定时器的驱动和中断处理。从程序框架上看,timer 基本就是上一节
int0 的一个 copy ,因为它们的机制和处理流程是非常接近的。唯一不同的就是 timer
是由内部定时触发的,不像 int0 那样需要人的参与才能触发中断。
和上一节同样的,我们也采用了 led 作为系统的辅助输出设备来显示主程序和中断的
执行状态。系统的主程序是通过 led 0, led 1, led 2 的交替闪烁来标识执行状态,其中
timer 会每隔一定长的时间(约1秒)触发一次中断,在中断处理中,我们安装了一个简单的
timer_irq_hooker 函数,对 led 3 做一次闪烁来标识中断程序的执行。
void timer_irq_hooker( void )
{
// we add a hooker of timer interrupt ( just let led_3 to blink one time )
led_one_light(3);
led_delay( 10 );
led_one_dark(3);
}
int main( void )
{
int i = 1;
install_irq_handler( irq_handler );
timer_install_irq_hooker( timer_irq_hooker );
led_init();
timer_init();
while(i++)
{
led_one_light(i%3);
led_delay( 200 );
led_one_dark(i%3);
}
return 0;
}
从底层的 timer_driver 实现来说,主要就是使能系统的 timer 0 和设置 interrupt
counter ,同样这些设置方面的工作基本还是采用了 timer_ioctl 来完成。
/* enable timer 0 */
int timer_open( void )
{
// disable timer_0
TMOD = 0;
// Clear pending interrupts
INTPND = 0x00000000;
// enable timer 0
TMOD = 1;
return 0;
}
int timer_ioctl( unsigned int cmd, unsigned long arg )
{
switch( cmd )
{
// set interrupt counter
case TIMER_SET_COUNTER:
TDATA0 = *(unsigned int *)arg;
break;
// Enable interrupt request and Unmask timer_0 interrupt
case TIMER_ENABLE_INTERRUPT:
INTMSK &= ~((1 << 21) | (1 <<10) );
break;
// clear timer 0 pending interrupts
case TIMER_CLEAR_INTERRUPT:
INTPND |= 1 << 10;
default:
break;
}
return 0;
}
可以看出,这一节和上一节无论是代码,或者是结构上都是非常类似的,我们做的
仅仅就是把几个细节方面的代码重新实现了,从主程序框架上看基本没有变化。这也从
另一个方面说明了:一个结构良好的程序框架就会具有良好的可移植性和可扩充性。 // Clear pending interrupts
INTPND = 0x00000000;
悬挂位清零不是应该写1的么,和后面的
case TIMER_CLEAR_INTERRUPT:
INTPND |= 1 << 10;
冲突啊,究竟这句话是什么意思啊? 第一个清零是保证在定时器开启之前悬挂位为0
当定时器中断后,悬挂位会自动置1,要清此位的话,需要写1清零,写1是触发硬件清零,而不是往此寄存器写1。
页:
[1]