51单片机定时器

定时器的工作原理
定时器的工作模式
定时器的时钟
中断系统

中断的流程
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);
						}
				}	
}

...

相关推荐
Little At Air6 分钟前
C++stack模拟实现
linux·开发语言·c++·算法
nuoxin11414 分钟前
CH6001FN/BW-富利威
网络·人工智能·嵌入式硬件·fpga开发·dsp开发
特长腿特长28 分钟前
LVS_DR 模式的原理
linux·运维·网络·云原生·centos·lvs
|华|39 分钟前
GFS 分布式文件系统
linux
恶魔泡泡糖42 分钟前
stm32F103C8T6标准库流水灯1——输出模式
stm32·单片机·嵌入式硬件
yyk的萌1 小时前
Claude Code 命令大全
linux·运维·服务器·ai·claude code
Fanfanaas1 小时前
Linux 系统编程 进程篇(五)
linux·服务器·c语言·网络·学习·进程
代码论斤卖1 小时前
OpenHarmony teecd频繁崩溃问题分析
linux·harmonyos
三佛科技-134163842121 小时前
FT838NB1-RT_5W(5V1A)原边反馈(5级能效)典型应用电路分析
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
Harvy_没救了1 小时前
【Linux】Nginx - 反向代理
linux·运维·nginx