先上代码
volatile unsigned long g_timer0_delay_conut = 0;
void main(void)
{
DISI(); //Disable all unmasked interrupts
Ny8b072a_Gpio_Init();
//Ny8b072a_Timer1_Init();
//Ny8b072a_Timer2_Init();
Ny8b072a_Timer3_Init();
ENI(); // Enable all unmasked interrupts
while(1)
{
//CLRWDT(); // Clear WatchDog
/*
LED1 = ~LED1;
LED2 = ~LED2;
LED3 = ~LED3;
LED4 = ~LED4;
*/
App_Delay_Ms(1000);
}
}
//10bit count down , max 0x3FF
void Ny8b072a_Timer1_Init(void)
{
//1MS
TMRH = 0x30; // TIMER1 higt 2bit in TMRH bit4~5 msb
TMR1 = 0xE8; // Load 0xFF to TMR1 (Initial Timer1 register) low 8bit
T1CR1 = C_TMR1_Reload | C_TMR1_En; // Enable Timer1, Initial value reloaded from TMR1, Non-stop mode
T1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Div2; // Enable Prescaler1, Prescaler1 dividing rate = 1:2
// Timer1 clock source is instruction clock
INTE |= C_INT_TMR1; // Enable Timer1 overflow interrupt
}
//10bit count down , max 0x3FF
void Ny8b072a_Timer2_Init(void)
{
//500us
TMRH = 0x40; //TIMER2 higt 2bit in TMRH bit6~7 msb
TMR2 = 0xF4; // Load 0xFF to TMR2 (Initial Timer2 register) low 8bit
T2CR1 = C_TMR2_Reload | C_TMR2_En; // Enable Timer2, Initial value reloaded from TMR2, Non-stop mode
T2CR2 = C_TMR2_ClkSrc_Inst | C_PS2_Div2; // Enable Prescaler2, Prescaler2 dividing rate = 1:2
// Timer2 clock source is instruction clock
INTE |= C_INT_TMR2; // Enable Timer2 overflow interrupt
}
//10bit count down , max 0x3FF
void Ny8b072a_Timer3_Init(void)
{
//50us
TM3RH = 0; //TIMER3 higt 2bit in TM3RH bit4~5 msb
TMR3 = 50; // Load 0xFF to TMR3 (Initial Timer3 register) low 8bit
T3CR1 = C_TMR3_Reload | C_TMR3_En; // Enable Timer3, Initial value reloaded from TMR3, Non-stop mode
T3CR2 = C_TMR3_ClkSrc_Inst | C_PS3_Div2; // Enable Prescaler3, Prescaler3 dividing rate = 1:2
// Timer3 clock source is instruction clock
//这里用 |= 会报错:如果其他中断讯号刚好在此时产生的话,使用 'BSR' 指令清除中断旗标有机会误清其他的中断旗标。 (201)
INTE2 = C_INE_TMR3; // Enable Timer3 overflow interrupt
}
//! interrupt service routine
void isr(void) __interrupt(0)
{
if(INTFbits.T1IF)
{
g_timer0_delay_conut ++;
if(500 == g_timer0_delay_conut ) //1MS * 500 = 500ms
{
LED1 ^= 1;
g_timer0_delay_conut= 0;
}
INTF= (unsigned char)~(C_INT_TMR1); // Clear T1IF flag bit
}
if(INTFbits.T2IF)
{
g_timer0_delay_conut ++;
if(1000 == g_timer0_delay_conut ) //500us * 1000 = 500ms
{
LED1 ^= 1;
g_timer0_delay_conut = 0;
}
INTF= (unsigned char)~(C_INT_TMR2); // Clear T2IF flag bit
}
if(INTE2bits.T3IF)
{
g_timer0_delay_conut ++;
if(10000 == g_timer0_delay_conut )//50us * 10000 = 500ms
{
LED1 ^= 1;
g_timer0_delay_conut = 0;
}
INTE2= (unsigned char)~(C_INF_TMR3); // Clear T3IF flag bit
}
}
时钟频率 | 指令周期 | 定时器分频 | TMRH | TMR1 | 中断计数 | IO翻转周期 |
---|---|---|---|---|---|---|
8M | 4T | C_PS1_Div2 | 0 | 50 | 10 000 | 500ms |
8M | 4T | C_PS1_Div4 | 0 | 50 | 10 000 | 1000ms |
表中第一行,定时器1的时间计算如下:
8 000 000 / 4 / 2 = 1 000 000,1 / 1 000 000 = 1us;
定时器1的初值计数50需要50us,这就是定时器1每次进中断的时间;
中断里10000 == g_time0_delay_conut需要的时间为 50 * 10 000 = 500 000us = 500ms。
表中第二行,定时器1的分频为4,验证时间为2分频的一倍,说明时间计算正确。
个人不建议把定时器初值设置过低(1us),太频繁的中断容易引起意想不到的BUG,根据自己实际使用需求来设置一个合理的值。