目录
三、定时器/计数器寄存器配置(使用STC-ISP工具配置定时器)
(1)例程1:使用中断系统→定时器操作LED流水灯。本例以外部中断0(上升沿中断/上升沿下降沿均可中断)为例,中断产生后将L6灯取反操作。
(2)例程2:解决按键时效不稳定的问题。本例以S7按键控制LE200ms为间隔D自动向左移位,S6按键控制LED200ms为间隔自动向右移位S5按键控制LED停止循环移位,S4按键关闭所有LED为例。
一、定时器/计数器概述
(1)实现定时功能的几种方法
- 软件定时:软件定时不占用硬件资源,但占用了CPU时间,降低了CPU的利用率
 - 采用时基电路定时:例如采用555电路
 - 采用可编程电路芯片定时:这种定时芯片的定时值及定时范围很容易用软件来确定和修改,此芯片定时功能强,使用灵活
 - 单片机定时器、扩展定时器芯片:方便、精准
 
(2)定时器和计数器的区别
- 计数的概念:假如有一个水杯(1000滴水正好能够装满),初始时已经有了500滴水,还需滴入500滴水才能将其装满,第501滴水时容器溢出。
 - 定时的概念(如果滴入1滴水的时间为1秒):还需500秒时间才能将其装满,第501秒时容器溢出
 
(3)基本概念
- 定时器是对周期固定的脉冲信号进行计数(如MCU内部的系统时钟)
 - 计数器是对周期不确定的脉冲信号进行计数:如MCU的I/O引脚所引入的外部脉冲信号
 - 结论:定时器和计数器本质上都是计数器,定时器是计数器的一种特例
 
二、定时器/计数器相关寄存器
(1)控制寄存器TCON(可位寻址)

(2)工作方式寄存器TMOD(不可位寻址)
- TMOD不可位寻址,意味着TMOD只可以进行整体赋值,而不能例如进行GOAT=0进行赋值
 - 自动装载,溢出后重新装置;不可重装载,溢出后停止
 - (在蓝桥杯的学习中)不涉及终端引脚,所以GOAT位一般设置为0;一般使用定时器,所以C/T位一般设置为0
 - 上电后,默认为0,只需操作控制寄存器即可进行计时
 

(3)辅助寄存器AUXR
STC15系列单片机是1T(即不存在机器周期)的8051单片机。(之前在使用8051单片机的时候,时钟系统是每12个系统时钟,8051才有一个机器周期)

(4)计数器/定时器-计数(定时)寄存器
- 用于计数器/定时器的计数或定时
 - 定时器0:TL0定时器0低八位寄存器,TH0定时器0高八位寄存器
 - 定时器1:TL1、YH1是定时/计数器T1的低8位、高8被状态值寄存器
 - 定时器2:T2H、T2L是定时/计数器T2的高八位、低8位状态值寄存器
 - 计时器/定时器的初始值计算:THx,TLx=65536-SYSCLK*T(sysclk是系统时间频率,T是要计时的时间)
 
(5)中断控制寄存器
开放总中断→开放部分中断(ET1\ET0) 若将ET0置为1,允许T0向CPU申请中断

三、定时器/计数器寄存器配置(使用STC-ISP工具配置定时器)
定时器初始化代码
- STC-ISP软件→定时器计算器
 - 选择使用的定时器、定时器模式、定时器时钟
 - 选择系统时钟频率(下载时是什么频率,时钟就设置什么频率)
 - 设置定时长度
 - 生成C代码(注意:此为仅定时器初始化代码且已开始计时,但并没有开启定时器中断允许、也没有开启总中断)
 

四、定时器例程
(1)例程1:使用中断系统→定时器操作LED流水灯。本例以外部中断0(上升沿中断/上升沿下降沿均可中断)为例,中断产生后将L6灯取反操作。
            
            
              cs
              
              
            
          
          #include <STC15F2K60S2.H>
unsigned char LED = 1;
unsigned int LED_Refresh=0;
//函数声明区域
void Timer0Init(void);	//1毫秒@11.0592MHz
void main(void)
{
	
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
	Timer0Init();
	EA=1;ET0=1;
	
	while(1)
	{
		
	}
	
}
void Timer0(void) interrupt 1
{
	
	if(++LED_Refresh == 1000)
	{
		LED_Refresh = 0;
		P0=~(0X01<<LED);
		if(++LED == 9) LED=0;
	}
	
}
        (2)例程2:解决按键时效不稳定的问题。本例以S7按键控制LE200ms为间隔D自动向左移位,S6按键控制LED200ms为间隔自动向右移位S5按键控制LED停止循环移位,S4按键关闭所有LED为例。
            
            
              cs
              
              
            
          
          #include <STC15F2K60S2.H>
#include<intrins.h>
unsigned char LED = 0 ;
unsigned char S7_Flag = 0, S6_Flag = 0, S5_Flag = 0, S4_Flag = 0 ;
unsigned char LED_Flag = 0 ;
unsigned int LED_tt = 0 ;
void KeyScan(void);
void Timer0Init(void);
void Delay_MS(unsigned int MS);
void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;	
	Timer0Init();
	EA=1;ET0=1;
	
	while(1)
	{
		KeyScan();
	
		if(S7_Flag == 1){ S7_Flag = 0 ; LED_Flag = 1 ; }
		if(S6_Flag == 1){ S6_Flag = 0 ; LED_Flag = 2 ; }
		if(S5_Flag == 1){ S5_Flag = 0 ; LED_Flag = 0 ; }
		if(S4_Flag == 1){ S4_Flag = 0 ; P0 = 0XFF ; }
	}
}
void Timer0(void) interrupt 1
{
	if(LED_Flag == 1)
	{
		if(++LED_tt >= 200)
		{
			LED_tt = 0 ;
			P0=~(0X01<<LED); 
			LED++;
			if(LED >= 8)LED = 0 ;
		}	
	}
	
	if(LED_Flag == 2)
	{
		if(++LED_tt >= 200)
		{
			LED_tt = 0 ;
			P0=~(0X80>>LED); 
			LED++;
			if(LED >= 8)LED = 0 ;
		}			
	}
}
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}
void KeyScan(void)
{
	if(P30==0)
	{
		Delay_MS(10);
		if(P30==0)S7_Flag = 1 ;		
		while(!P30);
	}
	else if(P31==0)
	{
		Delay_MS(10);
		if(P31==0)S6_Flag = 1 ;		
		while(!P31);
	}	
	else if(P32==0)
	{
		Delay_MS(10);
		if(P32==0)S5_Flag = 1 ;		
		while(!P32);
	}	
	else if(P33==0)
	{
		Delay_MS(10);
		if(P33==0)S4_Flag = 1 ;		
		while(!P33);
	}	
}
void Delay_MS(unsigned int MS)
{
	unsigned char i, j;
	while(MS--)
	{
	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}
}