了解计时器和中断周期

时间:2011-08-10 06:21:04

标签: c timer embedded arm interrupt

我很难理解我在ARM板上使用定时器和中断时发现的一些代码。定时器基本上在每次打开和关闭之间切换一个LED,使其闪烁。

void main(void) {

    /* Pin direction */
    led_init();

    /* timer setup */
    /* CTRL */

    #define COUNT_MODE 1      /* Use rising edge of primary source */
    #define PRIME_SRC  0xf    /* Peripheral clock with 128 prescale (for 24 MHz = 187500 Hz)*/
    #define SEC_SRC    0      /* Don't need this */
    #define ONCE       0      /* Keep counting */
    #define LEN        1      /* Count until compare then reload with value in LOAD */
    #define DIR        0      /* Count up */
    #define CO_INIT    0      /* Other counters cannot force a re-initialization of this counter */
    #define OUT_MODE   0      /* OFLAG is asserted while counter is active */

    *TMR_ENBL     = 0;                    /* TMRS reset to enabled */
    *TMR0_SCTRL   = 0;
    *TMR0_CSCTRL  = 0x0040;
    *TMR0_LOAD    = 0;                    /* Reload to zero */
    *TMR0_COMP_UP = 18750;                /* Trigger a reload at the end */
    *TMR0_CMPLD1  = 18750;                /* Compare one triggered reload level, 10 Hz maybe? */
    *TMR0_CNTR    = 0;                    /* Reset count register */
    *TMR0_CTRL    = (COUNT_MODE<<13) | 
                    (PRIME_SRC<<9)   | 
                    (SEC_SRC<<7)     | 
                    (ONCE<<6)        | 
                    (LEN<<5)         | 
                    (DIR<<4)         | 
                    (CO_INIT<<3)     |
                    (OUT_MODE);
    *TMR_ENBL     = 0xf;                  /* Enable all the timers --- why not? */

    led_on();

    enable_irq(TMR);

    while(1) {
        /* Sit here and let the interrupts do the work */
        continue;
    };
}

现在,LED以每秒无法确定的速度闪烁。我希望它每秒闪一次。但是,我不了解整个比较和重新加载。

有人可以更好地解释这段代码吗?

2 个答案:

答案 0 :(得分:1)

由于定时器是供应商和部件特定的功能(不是ARM体系结构的一部分),除非您提及要处理的CPU或微控制器,否则我只能提供一般性指导。

计时器有几个功能:

  1. 大小,例如16位,这意味着它们可以向上或向下计数65535。
  2. 时钟输入,以时钟频率(可能来自CPU时钟或外部晶振),以及将此时钟频率除以另一个值(或除以1)的预分频器。
  3. 溢出中断 - 当定时器回退到0时,通常会有一个触发中断的选项。
  4. 比较中断 - 当定时器满足设定值时,它将发出中断。
  5. 在您的情况下,我可以看到您正在使用计时器的比较功能。通过确定定时器时钟输入,并计算预分频器和比较寄存器的新值,您应该能够实现1 Hz的速率。

答案 1 :(得分:1)

在尝试理解您找到的代码之前,请先了解定时器外设单元的工作原理,然后了解如何配置它的寄存器以获得所需的输出。

定时器外围设备如何工作? 这是与CPU和其他外围设备一起嵌入微控制器的硬件模块。微控制器内的每个外围模块都与公共时钟源同步。参考代码,定时器外设时钟为24 MHz,然后预先缩放128,这意味着它将工作在187500 Hz。现在这个频率将取决于时钟配置和振荡器。

现在,定时器单元有一个计数器寄存器,可以计数到它的位大小,一般可以是8,16或32。启用计数后,此计数器将开始向上计数或向下计数上升沿或下降沿或两个边沿。现在您可以选择是否要向上计数(从0到255,对于8位)或向下计数(从255到0),并且您想要指望哪个时钟边沿。

现在,在187500 Hz,1个周期= 5.333333 us,如果您在1个周期内在上升沿或下降沿计数一次,例如,如果计数器值= 100(向上计数),则经过的总时间为5.33333 * 100 = 533us。现在,您必须为计数器设置比较值以设置此期间,这取决于您的闪存速率。这个比较值将通过Timer的比较器与你的计数器值进行比较,一旦匹配它就会发送一个中断信号,如果你在比较匹配时启用了中断,你可以在那里切换LED。

我希望您已了解定时器的工作原理。 在示例代码中,Timer配置为以10Hz的速率获得比较匹配事件。所以比较值是187500/10 = 18750.,1秒你可以保持187500/1。 您有定时器控制寄存器TMR0_CTRL,您可以在其中配置是要向上计数还是向下计数,计数下降/上升/两个边沿,仅计数一次/连续,计数到比较值然后复位或保持计数直到它的限制。有关每个位字段的详细信息,请参阅微控制器手册。