Day05.定时器

2025-04-02  本文已影响0人  xqiiitan

7.定时器

定时器作用:

1.用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作;
2.替代长时间的Delay,提高CPU运行效率和处理速度。
3.切换多任务。

定时器框图:

定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔‘1秒’,计数单元的数值就增加1,
当计数单元数值增加到‘设定的闹钟提醒时间’时,计数单元就会向中断系统发出中断申请,
产生“响铃提醒”,使程序跳转到中断服务函数中执行。

时钟:提供计数单元的时钟脉冲
系统时钟,即晶振周期,本开发板的晶振为12MHz.时钟12分频。

计数单元:时钟计数

中断系统:产生中断,执行定时任务。
中断系统是为使CPU具有 紧急事件的实时处理能力而设置的。
处理完以后,再回到原来被中断的地方,继续原来的主工作。

模式1: 16位定时器/计数器(最常用)
计数器到最大值,产生中断信号。

单片机通过寄存器值得修改,来实现内部不同的电路连接。
寄存器是连接软硬件的媒介。

7.1 按键控制led流水灯模式。

// 闹钟响了,执行中断任务。中断子程序。 在main里面实现。。
void Timer0_Routine() interrupt 1
{   
    static unsigned int T0Count; // 累加计数器。
    // 重新配置寄存器。
    TH0 = 64535/256; // 高位,最大能计数65535
    TL0 = 64535%256 +1;
    
    T0Count++;
    if(T0Count >= 1000) {
        T0Count = 0;
        P2_0 = ~P2_0; // 1s 亮灭
    }
}

void main(){
    // 配置寄存器。
    Timer0_init();  
    while(1) {
    }
}

模块化:

// Timer0.h
void Timer0_init();

// Timer0.c
void Timer0_init(){ // 定时器0 初始化。
    // TMOD =0x01; //配置寄存器:0000 0001
    TMOD = TMOD & 0xF0; // TMOD低4位清零,高4位保持不变
    TMOD = TMOD | 0x01; // TMOD最低位 置1, 高4位保持不变
    TF0 =0;
    TR0 =1; 
    // 设置起始值,64535离计数器溢出差值1000,所以计时单位是1ms。
    TH0 = 64535/256; // 高位,最大能计数65535. 0xFC
    TL0 = 64535%256 +1; // 0x18
    ET0 =1;
    EA  =1;
    PT0 =0;
}

7.2.按键控制

//Key.c 按键模块
// 获取独立按键的键码,范围0-4,无按键按下返回0.
unsigned char getKey(){
    unsigned char KeyNumber =0;
    // 消除抖动,按键抬起相应事件。按键检测。
    if(P3_1==0){Delay(20); while(P3_1==0);Delay(20); KeyNumber=1;}
    if(P3_0==0){Delay(20); while(P3_0==0);Delay(20); KeyNumber=2;}
    if(P3_2==0){Delay(20); while(P3_2==0);Delay(20); KeyNumber=3;}
    if(P3_3==0){Delay(20); while(P3_3==0);Delay(20); KeyNumber=4;}
    return KeyNumber;
}
// main.c
#include <INTRINS.H> // 循环移位函数,用于方便实现流水灯。
unsigned char KeyNum; // 记录按下了那个按键。
unsigned char LEDMode; // 实现流水灯模式控制。

void main() {
    Timer0_init();  
    P2 = 0xFE; // 初始亮灯。
    
    while(1) {
        KeyNum = Key();
        if(KeyNum==1){ // 控制向左,向右流水灯效果。
            LEDMode++;
            if(LEDMode>=2){LEDMode=0;}
        } 
        //if(KeyNum==2) P2_2 =~P2_2;
        //if(KeyNum==3) P2_3 =~P2_3;
        //if(KeyNum==4) P2_4 =~P2_4;
    }
}

// 闹钟响了,执行中断任务。中断子程序。 在main里面实现。。
void Timer0_Routine() interrupt 1
{   
    static unsigned int T0Count; // 累加计数器。
    // 重新配置寄存器。
    TH0 = 64535/256; // 高位,最大能计数65535
    TL0 = 64535%256 +1;
    
    T0Count++;
    if(T0Count >= 1000) {
        T0Count = 0;
        if(LEDMode==0){ // 左右循环移位函数,实现流水灯。
            P2_0 = _crol_(P2, 1);
        }
        if(LEDMode==1){
            P2_0 = _cror_(P2, 1);
        }
    }
}

7.3时钟实现。

// 需要依赖Delay.h, LCD1602.h, Timer0.h

unsigned char Sec,Min,Hour;

void main() {
    LCD_Init();
    LCD_ShowString(1,1, "Clock:");
    LCD_ShowString(2,1, "  :  :"); // 显示时间中间的冒号
    Timer0_init();
        
    while(1) {
        LCD_ShowNum(2,1, Hour, 2);
        LCD_ShowNum(2,4, Min, 2);
        LCD_ShowNum(2,7, Sec, 2);   
    }
}
// 中断函数
void Timer0_Routine() interrupt 1
{   
    static unsigned int T0Count; // 累加计数器。
    // 重新配置寄存器。
    TH0 = 64535/256; // 高位,最大能计数65535
    TL0 = 64535%256 +1;
    
    T0Count++;
    if(T0Count >= 1000) { //每隔1秒,处理。
        T0Count = 0;
        Sec++;
        if(Sec>=60){ // 秒到达60,分钟+1
            Sec=0;
            Min++;
            if(Min>=60){ // 分钟到达60,小时+1
                Min =0;
                Hour++;
                if(Hour>=24){ // 时到达24,清零
                    Hour =0;
                }
            }
        }
    }
}

上一篇 下一篇

猜你喜欢

热点阅读