定时器的工作原理
定时器的工作模式
定时器的时钟
中断系统
中断的流程
STC89C52的中断资源
AT89C52的中断资源
定时器相关寄存器
中断程序的编写
第一个中断程序案例使用模块化编程的方法
1:中断头文件
cpp
#ifndef __TIMER0_H_
#define __TIMER0_H_
void Timer0_Init(void);
#endif
2:中断实现函数
cpp
#include <REGX52.H>
// 第一步:初始化定时器
void Timer0_Init(void){
// firt 配置定时器的工作模式TMOD
// TMOD = 0x01;//0000 0001 这个写法会引发一种小的错误:当同时使用两个定时器时数据会被刷新
// 这个方法可以很好的解决数据刷新问题,也就是吧TMOD的低四位清0,高四位保持不变
// 1010 0011 & 1111 0000 也就是吧TMOD的低四位清0,高四位保持不变
TMOD = TMOD&0xF0;
// 把TMOD的低四位设置为1,然后高四位保持不变
TMOD = TMOD | 0X01;
TF0 = 0;
TR0 = 1; // 当TR0的值为1时表示中断开启
// 高八位和低八位0~65535每次间隔1微秒计数加1总共的定时时间
TH0 = (65535-1000)/256;
TL0 = (65535-1000)%256;
// 配置中断
ET0 = 1;
EA = 1;
PT0 = 0;
}
/*
todo 定时器模块化一秒的模版(中断函数模版)
// 第二步:中断函数的使用
void Timer0_Routime() interrupt 1{
static unsigned int T0Count;
// 每次中断以后要重新赋初始值
TH0 = (65535-1000)/256;
TL0 = (65535-1000)%256;
T0Count++;// 每次中断一次程序就统计一次
if(T0Count >= 1000){
T0Count = 0;
P1_0 = ~P1_0;
}
}
*/
主函数代码
主函数调用中断点亮其中的一个led灯
c
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"
#include "Key.h"
unsigned char KeyNum;
void main(){
// Timer0_Init();
while(1){
}
}
// 第二步:中断函数的使用
void Timer0_Routime() interrupt 1{
static unsigned int T0Count;
// 每次中断以后要重新赋初始值
TH0 = (65535-1000)/256;
TL0 = (65535-1000)%256;
T0Count++;// 每次中断一次程序就统计一次
if(T0Count >= 1000){
T0Count = 0;
P1_0 = ~P1_0;
}
}
第二个案例实现独立键盘控制
1:头文件
c
#ifndef __DELAY_H_
#define __DELAY_H_
void Delay(unsigned int xms);
unsigned char Key();
#endif
2:c语言函数实现文件
cpp
#include <REGX52.H>
#include "Delay.h"
// 独立按键模块化编程
unsigned char Key(){
unsigned char KeyNumber = 0;
if(P3_1 == 0){
Delay(20);
while(P3_1 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 1;
}
if(P3_2 == 0){
Delay(20);
while(P3_2 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 2;
}
if(P3_0 == 0){
Delay(20);
while(P3_0 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 3;
}
if(P3_3 == 0){
Delay(20);
while(P3_3 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 4;
}
return KeyNumber;
}
3:c语言主函数文件
c
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"
#include "Key.h"
unsigned char KeyNum;
void main(){
// Timer0_Init();
while(1){
KeyNum = Key();
if(KeyNum == 1){
P1_1 = ~P1_1;
}
if(KeyNum == 2){
P1_2 = ~P1_2;
}
if(KeyNum == 3){
P1_3 = ~P1_3;
}
if(KeyNum == 4){
P1_4 = ~P1_4;
}
}
}
// 第二步:中断函数的使用
//void Timer0_Routime() interrupt 1{
// static unsigned int T0Count;
// // 每次中断以后要重新赋初始值
// TH0 = (65535-1000)/256;
// TL0 = (65535-1000)%256;
// T0Count++;// 每次中断一次程序就统计一次
// if(T0Count >= 1000){
// T0Count = 0;
// P1_0 = ~P1_0;
// }
//}
案例三:实现按第一个独立键盘按钮改变流水灯的运动方向
1:延时函数的头文件
c
#ifndef __DELAY_H_
#define __DELAY_H_
void Delay(unsigned int xms);
#endif
2:独立键盘的头文件
c
#ifndef __DELAY_H_
#define __DELAY_H_
void Delay(unsigned int xms);
unsigned char Key();
#endif
3:独立键盘的c语言文件
c
#include <REGX52.H>
#include "Delay.h"
// 独立按键模块化编程
unsigned char Key(){
unsigned char KeyNumber = 0;
if(P3_1 == 0){
Delay(20);
while(P3_1 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 1;
}
if(P3_2 == 0){
Delay(20);
while(P3_2 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 2;
}
if(P3_0 == 0){
Delay(20);
while(P3_0 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 3;
}
if(P3_3 == 0){
Delay(20);
while(P3_3 == 0){ // 检测是否松手
}
Delay(20);
KeyNumber = 4;
}
return KeyNumber;
}
4:c语言主函数实现文件
c
#include <REGX52.H>
#include <INTRINS.H>
#include "Delay.h"
#include "Timer0.h"
#include "Key.h"
unsigned char KeyNum,LEDMode;
void main(){
P1 = 0xfe;
Timer0_Init();
while(1){
KeyNum = Key();
if(KeyNum == 1){
LEDMode++;
if(LEDMode >= 2){
LEDMode = 0;
}
}
}
}
// 第二步:中断函数的使用
void Timer0_Routime() interrupt 1{
static unsigned int T0Count;
// 每次中断以后要重新赋初始值
TH0 = (65535-1000)/256;
TL0 = (65535-1000)%256;
T0Count++;// 每次中断一次程序就统计一次
if(T0Count >= 500){
T0Count = 0;
if(LEDMode == 0){
// 循环左移
P1 = _crol_(P1,1);
}
if(LEDMode == 1){
// 循环右移
P1 = _cror_(P1,1);
}
}
}
...