目录
三、定时器/计数器寄存器配置(使用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);
}
}