我很难理解我在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以每秒无法确定的速度闪烁。我希望它每秒闪一次。但是,我不了解整个比较和重新加载。
有人可以更好地解释这段代码吗?
答案 0 :(得分:1)
由于定时器是供应商和部件特定的功能(不是ARM体系结构的一部分),除非您提及要处理的CPU或微控制器,否则我只能提供一般性指导。
计时器有几个功能:
在您的情况下,我可以看到您正在使用计时器的比较功能。通过确定定时器时钟输入,并计算预分频器和比较寄存器的新值,您应该能够实现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,您可以在其中配置是要向上计数还是向下计数,计数下降/上升/两个边沿,仅计数一次/连续,计数到比较值然后复位或保持计数直到它的限制。有关每个位字段的详细信息,请参阅微控制器手册。