九齐单片机(如NY8B062D)以其低成本、高性能和高性价比在家电、量测等I/O应用中广受欢迎。本文将通过一个具体的定时器例程代码,详细解析九齐单片机定时器的工作原理及实现方法。
一、例程背景
假设我们有一个项目,需要使用九齐单片机NY8B062D的定时器功能来控制三个LED灯(分别连接在PB0、PB1、PB2引脚)的闪烁频率,以实现不同的视觉效果。具体需求如下:
- Timer0:每2048微秒(us)翻转PB0引脚的状态,即LED灯闪烁。
- Timer1:每1024微秒翻转PB1引脚的状态,LED灯闪烁频率是Timer0的两倍。
- WDT(看门狗定时器):每3.5毫秒(ms)翻转PB2引脚的状态,用于监控程序是否正常运行。
二、定时器初始化与配置
首先,我们需要对定时器进行初始化和配置。以下是定时器初始化的关键代码段:
c复制代码
// 初始化GPIO | |
void init_gpio(void) { | |
IOSTB = C_PB5_Input | C_PB4_Input | C_PB3_Input; // PB0, PB1, PB2设为输出 | |
PORTB = 0x07; // PB0, PB1, PB2输出高电平 | |
} | |
// 初始化Timer0 | |
void init_timer0(void) { | |
PCON1 = C_TMR0_Dis; // 禁用Timer0 | |
TMR0 = 0; // 加载初始值 | |
T0MD = C_PS0_TMR0 | C_PS0_Div8; // Timer0预分频器设为1:8,时钟源为指令时钟 | |
PCON1 = C_TMR0_En; // 启用Timer0 | |
} | |
// 初始化Timer1 | |
void init_timer1(void) { | |
TMR1 = 0xFF; // 加载初始值 | |
T1CR1 = C_TMR1_Reload | C_TMR1_En; // 启用Timer1,自动重载 | |
T1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Div4; // Timer1时钟源为指令时钟,预分频器设为1:4 | |
} | |
// 初始化WDT | |
void init_wdt(void) { | |
// WDT的配置通常在系统启动时通过配置字节(Configuration Word)设置 | |
// 这里假设WDT时间基准已设为3.5ms | |
} | |
// 设置中断 | |
void init_interrupt(void) { | |
INTE = C_INT_WDT | C_INT_TMR1 | C_INT_TMR0; // 启用WDT、Timer0、Timer1中断 | |
ENI(); // 启用所有未屏蔽的中断 | |
} | |
// 主函数 | |
void main(void) { | |
init_gpio(); | |
init_timer0(); | |
init_timer1(); | |
init_wdt(); | |
init_interrupt(); | |
while (1); // 主循环 | |
} |
三、中断服务例程
当定时器达到设定时间时,会触发中断,中断服务例程(ISR)将执行相应的操作。以下是ISR的实现:
c复制代码
void isr(void) __interrupt(0) { | |
if (INTFbits.T0IF) { | |
PORTB ^= 1; // 翻转PB0引脚状态 | |
INTF = (unsigned char)~(C_INT_TMR0); // 清除Timer0中断标志 | |
} | |
if (INTFbits.T1IF) { | |
PORTB ^= (1 << 1); // 翻转PB1引脚状态 | |
INTF = (unsigned char)~(C_INT_TMR1); // 清除Timer1中断标志 | |
} | |
if (INTFbits.WDTIF) { | |
PORTB ^= (1 << 2); // 翻转PB2引脚状态 | |
INTF = (unsigned char)~(C_INT_WDT); // 清除WDT中断标志 | |
} | |
} |
四、工作原理
- Timer0:通过配置预分频器和初始值,Timer0每2048us溢出一次,触发中断,翻转PB0引脚状态。
- Timer1:类似地,Timer1每1024us下溢一次,触发中断,翻转PB1引脚状态。
- WDT:WDT