一、定时器基础
sysclk-系统时钟(12MHz),通过AUXR来控制是否分频,然后是通过T2_C/-T来选择是内部还是外部晶振,当其值=0时,T2对内部系统时钟计数,T2工作在定时方式;当其值=1时,连接到外部脉冲输入,T2工作在计数方式;T2R是AUXR寄存器的控制位,T2R=1,打开控制开关。
二、定时器简单应用----用定时器来做任务调度‘
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"
#include "system.h"
HexToBin led_ctrl,buzzer_ctrl;
u8 cnt_buzzer;
//外设控制函数
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0); //关闭蜂鸣器、继电器
}
void Timer2Init(void) //1ms@12.000MHz
{
AUXR |= 0x04; //选择1T模式
T2L = 0x20; //设置定时器初值
T2H = 0xD1; //设置定时器初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //打开定时器2中断
EA = 1; //打开总开关
}
void main(void)
{
vSystem_Init();
Timer2Init();
while(1)
{
}
}
void Timer2_Rountine(void) interrupt 12
{
cnt_buzzer++;
if(cnt_buzzer<=200) //0~200ms蜂鸣器不响
{
buzzer_ctrl.b.b6 = 1;
vDevice_Ctrl(0xa0,buzzer_ctrl.hex);
}
else if(cnt_buzzer<=400) //200~400ms蜂鸣器响
{
buzzer_ctrl.b.b6 = 0;
vDevice_Ctrl(0xa0,buzzer_ctrl.hex);
}
else cnt_buzzer=0;
/*更简单的写法-根据时间点来调度*/
/*
cnt_buzzer++;
if(cnt_buzzer==200)
{
cnt_buzzer=0;
buzzer_ctrl.b.b6 = ~buzzer_ctrl.b.b6;
vDevice_Ctrl(0xa0,buzzer_ctrl.hex);
}
}
三、综合练习
编程实现如下所有任务:
1.L1以0.5s间隔闪烁(不使用delay)
2.当L1闪烁5次,继电器吸合;再闪烁五次,继电器关闭;
3.L4~L8以0.1s间隔流水灯
4.蜂鸣器一直处于关闭状态,且L2,L3一直处于熄灭状态;
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"
#include "system.h"
HexToBin led_ctrl,uln_ctrl;
void System_Init()
{
vDevice_Ctrl(0xa0,0); //关闭蜂鸣器、继电器
led_ctrl.hex=0xff;
vDevice_Ctrl(0x80,led_ctrl.hex); //关闭所有Led
}
void Timer2Init(void) //1ms@12.000MHz
{
AUXR &= 0xFB; //12T模式
T2L = 0x18; //设置初值
T2H = 0xFC; //设置初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //打开定时器2中断
EA = 1; //打开总中断
}
//led操作函数
u16 cnt_led_blink,cnt_led_running;
u8 led_blink_times;
u8 led_shift;
void vLED_Process()
{
//led以0.5s间隔闪烁
if(cnt_led_blink>=500)
{
cnt_led_blink=0;
led_ctrl.b.b0 = ~led_ctrl.b.b0;
vDevice_Ctrl(0x80,led_ctrl.hex);
led_blink_times++;
}
//L4~L8以0.1s间隔流水
if(cnt_led_running>=100)
{
cnt_led_running=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);
vDevice_Ctrl(0x80,led_ctrl.hex);
led_shift++;
if(led_shift==5) led_shift=0;
}
}
//继电器操作函数
void vULN_Process()
{
if(led_blink_times==10)
{
uln_ctrl.b.b4=1; //继电器打开
vDevice_Ctrl(0xa0,uln_ctrl.hex);
}
if(led_blink_times==20)
{
led_blink_times=0;
uln_ctrl.b.b4=0; //继电器关闭
vDevice_Ctrl(0xa0,uln_ctrl.hex);
}
}
void main()
{
System_Init();
Timer2Init();
while(1)
{
}
}
void Timer2_Routine(void) interrupt 12
{
cnt_led_blink++;
cnt_led_running++;
vLED_Process();
vULN_Process();
}
实际现象: