QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3121|回复: 2

Learn lumit Step 16 : 定时器实验

[复制链接]
发表于 2005-6-14 00:19:41 | 显示全部楼层 |阅读模式
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;
}

    可以看出,这一节和上一节无论是代码,或者是结构上都是非常类似的,我们做的
仅仅就是把几个细节方面的代码重新实现了,从主程序框架上看基本没有变化。这也从
另一个方面说明了:一个结构良好的程序框架就会具有良好的可移植性和可扩充性。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2006-3-29 10:52:56 | 显示全部楼层
// Clear pending interrupts
INTPND = 0x00000000;

悬挂位清零不是应该写1的么,和后面的
case TIMER_CLEAR_INTERRUPT:
INTPND |= 1 << 10;

冲突啊,究竟这句话是什么意思啊?
回复

使用道具 举报

发表于 2006-4-1 22:14:08 | 显示全部楼层
第一个清零是保证在定时器开启之前悬挂位为0
当定时器中断后,悬挂位会自动置1,要清此位的话,需要写1清零,写1是触发硬件清零,而不是往此寄存器写1。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-24 07:12 , Processed in 0.117579 second(s), 17 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表