蓝桥杯定时器2

定时器基础知识

定时器相当于单片机的心脏,有了它才能让单片机知道外部的时间。

前面都是使用延时来进行LED间隔点亮等等功能,这时单片机就在傻傻的数数,就像一个大傻der。有了定时器,单片机就可以摇身一变,成为时间管理大师💪,在空闲的时间可以去干别的事情了~~~~~

定时器2中断

在前面的程序中都是顺序执行程序的,中断系统就是为使CPU具有对外界紧急时间处理能力而设置的。当CPU正在处理某件事情的时候,外界发生了紧急事件请求,要求CPU暂停当前工作,转而去处理这个紧急事件 ,处理完成以后,再回到原来被中断的地方,继续原来的工作,这种过程就称为中断。实现这种功能的不见称为中断系统,请示CPU中断请求的请求源称为中断源。微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题,通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。CPU总市先响应优先级别最高的中断请求。比赛中不太需要管优先级其实

中断要求“快进快出”,快进中断请求快速响应,快出就是中断处理完成之后,立刻返回原事件

什么时候触发中断?

当计数器溢出时触发中断,即16位计数器计数超出65535,触发中断(当T2L=0xff T2H=0xff,再来一个脉冲,就溢出,触发中断)

声明中断函数,每一个中断函数都有一个中断编号,只有这个编号,单片机才能识别该函数是一个中断处理函数,识别它是什么中断。相应的中断编号也不需要去背,只需要在STC-ISP中就可以查找就可以。

在范例程序中选择15系列芯片的定时器2的16位自动重载模式就可以看到中断编号以及开中断等等示例程序了。

中断初始化函数以及中断处理函数

中断的原理在这里也不进行过多介绍,中断的初始化函数也可以不用自己背自己写,可以直接在STC-ISP中生成。

选择定时器计数器选项卡,再选择相应的定时器,以及技术方式等等选项,就可以直接生成相应的定时器初始化函数。但是需要注意的是系统频率,以及IRC频率要选择好,需要与题目要求一致,近几年蓝桥杯要求的都是 12MHZ。定时器时钟也要注意选择12T模式。(1T模式最多(65536/12)us;12T模式最多65536us!)

//用定时器2产生1ms的中断,并用定时器的方法来实现蜂鸣器以200ms间隔响
//(优化掉while(1)里面的Delay()延时,提高CPU效率)


#include <STC15F2K60S2.H>
#include <intrins.h>

unsigned char buzzer_ctrl;
unsigned char relay_ctrl;

unsigned int buzzer_cnt=0;//必须要定义为unsigned int型的变量
                          //因为unsigned char是0~255ms,unsigned int是0~65535MS
       
void device_Ctrl(unsigned char  P2data,unsigned char  P0data)
{
    P0=P0data;
    P2=P2data;
    P2=0;
}    


void dvice_Init()
{
    buzzer_ctrl=0;
    relay_ctrl=0;
    device_Ctrl(0xa0,((buzzer_ctrl<<6)|(relay_ctrl<<4)));
}

/*
使用计时器定时1ms,当需要200ms时就可以定义一个变量,每计时1ms,就将变量+1,当变量计数到200时
说明已经即使200ms,就进行相应的事件处理
*/
void Timer2Init(void)        //1毫秒@12.000MHz
{
    AUXR &= 0xFB;      //定时器时钟12T模式
    T2L = 0x18;        //设置定时初始值
    T2H = 0xFC;       //设置定时初始值
    AUXR |= 0x10;     //定时器2开始计时
    IE2 |= 0x04;      //开定时器2中断
    EA = 1;          //开启总中断
}

void main()
{
    dvice_Init();
    Timer2Init();
    while(1)
    {
    
    }
}


//中断服务程序
void t2int() interrupt 12           //中断入口
{
    buzzer_cnt++;
    if(buzzer_cnt==200)
    {
        buzzer_cnt=0;//将计数变量清0,为下一次计数做准备
        buzzer_ctrl=~buzzer_ctrl;
        device_Ctrl(0xa0,((buzzer_ctrl<<6)|(relay_ctrl<<4)));
    }
}

定时器正确的锁存操作

有时候可能代码正确但是会发生LED微亮,蜂鸣器可能会突然响一下,数码管可能会突然乱码一下等等情况。就是因为锁存器进行锁存时出现了干扰。

中断可能在任何时刻发生,可能发生在操作译码器、锁存器的位置,那么此时转去执行中断服务程序,就可能干扰锁存器里面存入的数据,并且while(1)里面也不要进行一些耗时的操作,可能会造成定时器定时不准确的情况。尽量将外设、耗时的操作都放在定时器中断中进行处理。

下面的代码就是一种典型的错误形式

#include <STC15F2K60S2.H>
#include <intrins.h>

unsigned char buzzer_ctrl;
unsigned char relay_ctrl;

unsigned int buzzer_cnt=0;//必须要定义为unsigned int型的变量
                          //因为unsigned char是0~255ms,unsigned int是0~65535MS
       
void device_Ctrl(unsigned char  P2data,unsigned char  P0data)
{
    P0=P0data;
    P2=P2data;
    P2=0;
}    


void dvice_Init()
{
    buzzer_ctrl=0;
    relay_ctrl=0;
    device_Ctrl(0xa0,((buzzer_ctrl<<6)|(relay_ctrl<<4)));
}

/*
使用计时器定时1ms,当需要200ms时就可以定义一个变量,每计时1ms,就将变量+1,当变量计数到200时
说明已经即使200ms,就进行相应的事件处理
*/
void Timer2Init(void)        //1毫秒@12.000MHz
{
    AUXR &= 0xFB;      //定时器时钟12T模式
    T2L = 0x18;        //设置定时初始值
    T2H = 0xFC;       //设置定时初始值
    AUXR |= 0x10;     //定时器2开始计时
    IE2 |= 0x04;      //开定时器2中断
    EA = 1;          //开启总中断
}

void main()
{
    dvice_Init();
    Timer2Init();
    while(1)
    {
            if(buzzer_cnt==200)
            {
                buzzer_cnt=0;//将计数变量清0,为下一次计数做准备
                buzzer_ctrl=~buzzer_ctrl;
                device_Ctrl(0xa0,((buzzer_ctrl<<6)|(relay_ctrl<<4)));
            }
    }
}


//中断服务程序
void t2int() interrupt 12           //中断入口
{
    buzzer_cnt++;
}

定时器综合练习

//1.L1以0.5s间隔闪烁
//2.当L1闪烁5次后,继电器吸合;再次闪烁5次后继电器关闭
//3.L4~L8以0.1s间隔流水灯
//4.蜂鸣器一直处于关闭状态,且L2、L3一直处于熄灭状态


#include <STC15F2K60S2.H>

typedef unsigned char u8;
typedef unsigned int u16;

u16 led_link;//LED间隔闪烁控制变量
u16 led_flash;//LED流水灯控制变量
u8 led_shift;//LED流水灯移位控制变量 
u16 relay_ctrl;//继电器控制变量

typedef struct
{
    u8 b0:1;
    u8 b1:1;
    u8 b2:1;
    u8 b3:1;
    u8 b4:1;
    u8 b5:1;
    u8 b6:1;
    u8 b7:1;
}bits;

typedef union
{
    u8 hex;
    bits b;
}HexToBin;


HexToBin led_ctrl,buzzer_ctrl;

void divice_ctrl(unsigned char P2data,unsigned char P0data)
{
    P0=P0data;
    P2=P2data;
    P2=0;
}

void system_init()
{
    divice_ctrl(0xa0,0);
    led_ctrl.hex=0xff;
    divice_ctrl(0x80,led_ctrl.hex);     /* 关闭LED*/
}


void LED_process()
{
    //L1以0.5s间隔闪烁
    if(led_link==500)
    {
        led_link=0;
        led_ctrl.b.b0=~led_ctrl.b.b0;
        divice_ctrl(0x80,led_ctrl.hex);
        relay_ctrl++;
    }
    
    //L4~L8以0.1s间隔流水灯
    if(led_flash==100)
    {
        led_flash=0;
        led_ctrl.b.b3=~(0x01>>led_shift);
        led_ctrl.b.b4=~(0x02>>led_shift);
        led_ctrl.b.b5=~(0x04>>led_shift);
        led_ctrl.b.b6=~(0x08>>led_shift);
        led_ctrl.b.b7=~(0x10>>led_shift);
        divice_ctrl(0x80,led_ctrl.hex);
          
        led_shift++;
        if(led_shift==5)
        {led_shift=0;}
    
    }
}


void relay_process()
{
    if(relay_ctrl==10)
    {
        buzzer_ctrl.b.b4=1;
        divice_ctrl(0xa0,buzzer_ctrl.hex);
    }
    if(relay_ctrl==20)
    {
        relay_ctrl==0;
        buzzer_ctrl.b.b4=0;
        divice_ctrl(0xa0,buzzer_ctrl.hex);
    }


}
void Timer2Init(void)        //1毫秒@12.000MHz
{
    AUXR &= 0xFB;        //定时器时钟12T模式
    T2L = 0x18;        //设置定时初始值
    T2H = 0xFC;        //设置定时初始值
    AUXR |= 0x10;        //定时器2开始计时
    IE2 |= 0x04;                    //开定时器2中断
    EA = 1;
}



void main()
{
    system_init();
    Timer2Init();
    while(1)
    {
    
    }

}

void t2int() interrupt 12    
{
    led_link++;
    led_flash++;
    LED_process();
    relay_process();
}
  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
蓝桥杯单片机定时器小蜜蜂是一个用于学习和实践单片机编程的教学项目。根据引用,在这个项目中,按键等待是一个关键操作,需要将显示时间的模块放在循环中,并且通过定时器中断来控制操作的时间。同时,引用提到LED和数码管的P0口端口被复用,用来记录串口发送的数据和判断按键是否按下。关于蓝桥杯单片机定时器小蜜蜂的具体内容,引用提供了一份目录,其中包括了一些进阶的案例和底层驱动代码的移植与应用。 总结来说,蓝桥杯单片机定时器小蜜蜂是一个教学项目,通过学习它可以了解和练习单片机编程的一些基础和高级操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [蓝桥杯单片机-小蜜蜂老师-工厂灯光控制系统(P15代码)](https://blog.csdn.net/m0_61804419/article/details/129488234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [备战蓝桥杯单片机倒数第四天 小蜜蜂老师公众号更新内容](https://blog.csdn.net/silver321/article/details/123969400)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值