定时器2中断的开启首先,我们需要借用ISP软件生成代码。此代码仅仅是开启定时器2的定时功能。
```c
void Timer2Init(void) //1毫秒@12.000MHz {
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初始值
T2H = 0xD1; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
}
```
接下来,我们需要打开定时器2中断。打开STC15系列单片机用户手册,可以看到IE(可位寻址)和IE2(不可位寻址)两个中断允许控制寄存器。可位寻址与不可位寻址的意思就是:是否可以按位进行赋值操作。这里需要打开定时器2的中断开关,因此IE2的ET2位赋值为1,又因为IE2寄存器不可位寻址,则IE2必须整个字节进行赋值,即IE2 |= 0x04;这样赋值。打开定时器2中断后,还必须开启CPU响应所有中断(总中断允许位),因此IE的EA位赋值为1,又因为IE寄存器可位寻址,则IE中的每一位可以单独赋值,即"EA = 1";这样赋值。
最终开启定时器2中断的代码如下:
```c
void Timer2Init(void) //1毫秒@12.000MHz {
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初始值
T2H = 0xD1; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时 //***************************从此往上 只是单纯的开定时器2 IE2 |= 0x04; //开定时器2的中断 EA = 1; //总中断
}
```
接下来,我们需要编写定时器2中断服务函数。查手册得到定时器2中断查询次序号(当然也有计算公式)。查手册得次序号为12。通过公式计算:中断地址向量=0003H+中断序号×8。所以:中断序号=(中断地址向量-0003H)/8。例如:定时器2中断(即中断序号为12),其中断地址向量为0063H,0063H-0003H=0060H=96,96/8=12,因此定时器2中断号就为12。
最后,编写中断服务函数:
```c
void Timer2Handler() interrupt 12 { //这里因为设置的是16位自动重载,不需要像传统51那样给定时器赋初值 }
```
结合之前学的点亮LED,现在我们来实现Led1闪烁的代码。首先,我们需要包含头文件`STC15F2K60S2.H`,然后定义两个无符号字符类型`u8`和`u16`。接下来,我们编写`DeviceCtrl`函数,用于控制P0和P2端口的数据。在这个函数中,我们将P0数据设置为`p0data`,将P2数据设置为`(P2&0x1f)|p2data`,并将P2数据清零。
接着,我们需要编写`Timer2Init`函数,用于初始化定时器2。在这个函数中,我们设置定时器的时钟模式、定时初始值,并开启定时器2的中断。
最后,在`main`函数中,我们调用`DeviceCtrl`函数,打开继电器和LED1。然后调用`Timer2Init`函数初始化定时器2。接下来,我们进入一个无限循环,等待定时器2中断发生。
在`Timer2Handler`中断服务程序中,我们定义一个静态变量`one_sec`,用于计算时间。当时间小于等于1000毫秒时,我们打开LED1;当时间小于等于2000毫秒时,我们关闭LED1;否则,我们将`one_sec`重置为0。
下面是完整的代码:
```c++
#include "STC15F2K60S2.H"
typedef unsigned char u8;
typedef unsigned int u16;
void DeviceCtrl(u8 p2data, u8 p0data) {
P0 = p0data; // 给数据
P2 = (P2 & 0x1f)|p2data; // (开门)
P2 &= 0x1f; // (关门)
}
void Timer2Init(void) { //1毫秒@12.000MHz
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初始值
T2H = 0xD1; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //开定时器2的中断
EA = 1; //总中断
}
void main() {
DeviceCtrl(0xa0, 0x10); //buzz --close relay --open
DeviceCtrl(0x80, 0xfe); //open led1
Timer2Init();
while (1) {}
}
void Timer2Handler() interrupt 12 {
static u16 one_sec = 0;
one_sec++;
if(one_sec <= 1000){
DeviceCtrl(0x80, 0xfe); //open led1
}else if(one_sec <= 2000){
DeviceCtrl(0x80, 0xff); //灭
}else{
one_sec = 0;
}
}
```