09-定时器的进阶综合案例

定时器的进阶综合案例

1172284-20180210000640013-871146784

由上可知,这边使用的是定时器1的模式,所以这边需要先了解下定时器:

1. 定时器/计数器0/1控制寄存器TCON

TCON为定时器/计数器T0、T1的控制寄存器,同时也锁存T0、T1溢出中断源和外部请求

中断源等,TCON格式如下:

TCON : 定时器/计数器中断控制寄存器 (可位寻址)

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
TCON 88H name TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0

TF1:T1溢出中断标志位。产生溢出时,硬件置1,请求中断。进入中断后硬件清0;

TR1:0—关闭T1,1—打开T1;

TF0:T0溢出中断标志位。产生溢出时,硬件置1,请求中断。进入中断后硬件清0;

TR0:0—关闭T0,1—打开T0;

IE1:外部中断1请求源(INT1/P3.3)标志。IE1=1,外部中断向CPU请求中断,当CPU响应该

中断时由硬件清“0”IE1。

IT1:外部中断源1触发控制位。IT1=0,上升沿或下降沿均可触发外部中断1。IT1=1,外部中

断1程控为下降沿触发方式。

IE0:外部中断0请求源(INT0/P3.2)标志。IE0=1外部中断0向CPU请求中断,当CPU响应外

部中断时,由硬件清“0”IE0(边沿触发方式)。

IT0:外部中断源0触发控制位。IT0=0,上升沿或下降沿均可触发外部中断0。IT0=1,外部中

断0程控为下降沿触发方式

2.TMOD定时器/计数器0/1工作模式寄存器

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
TMOD 89H name GATE C/ \(\overline{T}\) M1 M0 GATE C/ \(\overline{T}\) M1 M0
定时器1 定时器0
高四位控制定时器1:

GATE :置1时只有在INT1脚为高及TR1控制位置1时才可打开定时器/计数器1;

C / \(\overline{T}\):0—T1为定时器模式,对内部系统时钟计数,1—T1为计数器模式,对引脚T1/P3.5的外部脉冲计数;

M1 M0 定时器/计数器1模式选择
0 0 16位自动重装载模式,溢出时将RL_TH1和RL_TL1存放的值自动装入TH1和TL1
0 1 16位不可重装载模式
1 0 8位自动重装载,溢出时将TH1存放的值自动装入TL1
1 1 定时器/计数器1无效(停止计数)
低4位控制定时器0:

GATE ::置1时只有在INT0脚为高及TR0控制位置1时才可打开定时器/计数器0;

C / \(\overline{T}\):0—T0为定时器模式,对内部系统时钟计数,1—T0为计数器模式,对引脚T0/P3.4的外部脉冲计数;

M1 M0 定时器/计数器1模式选择
0 0 16位自动重装载模式,溢出时将RL_TH0和RL_TL0存放的值自动装入TH0和TL0
0 1 16位不可重装载模式
1 0 8位自动重装载,溢出时将TH0存放的值自动装入TL0
1 1 不可屏蔽中断的16位自动重装载定时器,即中断不受EA控制,只由ET0控制(此处与T1不同)

3.AUXR辅助寄存器(不可位寻址)

STC15系列单片机是 1T 的8051单片机,为兼容传统8051,定时器0 、定时器1,和定时器2复位后是传统8051的速度,即12分频,这是为了兼容传统8051。但也可不进行12分频,通过设置新增加的特殊功能寄存器AUXR,将T0,T1,T2设置位1T,

AUXR:辅助寄存器(不可位寻址)

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
AUXR 8EH name T0x12 T1x12 UART_M0x6 T2R T2_C / \(\overline{T}\) T2x12 EXTRAM S1ST2

T0x12: 定时器0速度控制位

​ 0, 定时器0是传统8051速度,12分频;

​ 1, 定时器0的速度是传统8051的12倍,不分频

T1x12: 定时器1速度控制位

​ 0, 定时器1是传统8051速度,12分频;

​ 1, 定时器1的速度是传统8051的12倍,不分频

如果UART1/串口1用T1作为波特率发生器,则由T1x12决定UART1/串口1是12T还是1T

UART_M0x6: 串口1模式0的通信速度设置位。

​ 0, 串口1模式0的速度是传统8051单片机串口的速度,12分频;

​ 1, 串口1模式0的速度是传统8051单片机串口速度的6倍,2分频

T2R: 定时器2允许控制位

​ 0, 不允许定时器2运行;

​ 1, 允许定时器2运行

T2_C / \(\overline{T}\): 控制定时器2用作定时器或计数器。

​ 0, 用作定时器(对内部系统时钟进行计数);

​ 1, 用作计数器(对引脚T2/P3.1的外部脉冲进行计数)

T2x12: 定时器2速度控制位

​ 0, 定时器2是传统8051速度,12分频;

​ 1, 定时器2的速度是传统8051的12倍,不分频

如果串口1或串口2用T2作为波特率发生器,则由T2x12决定串口1或串口2是12T还是1T.

EXTRAM: 内部/外部RAM存取控制位

​ 0, 允许使用逻辑上在片外、物理上在片内的扩展RAM;

​ 1, 禁止使用逻辑上在片外、物理上在片内的扩展RAM

S1ST2: 串口1(UART1)选择定时器2作波特率发生器的控制位

​ 0, 选择定时器1作为串口1(UART1)的波特率发生器;

​ 1, 选择定时器2作为串口1(UART1)的波特率发生器,此时定时器1得到释放,可以作为

独立定时器使用

5.定时器T0和T1的中断控制寄存器:IE和IP

IE:中断允许寄存器(可位寻址)

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
IE A8H name EA ET1 ET0

EA: CPU的总中断允许控制位,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申请。

​ EA的作用是使中断允许形成多级控制。即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。

ET1 : 定时/计数器T1的溢出中断允许位,ET1=1,允许T1中断,ET1=0,禁止T1中断。

ET0 : T0的溢出中断允许位,ET0=1允许T0中断,ET0=0禁止T0中断。

IP:中断优先级控制寄存器(可位寻址)

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
IP B8H name PT1 PT0

PT1:

​ 定时器1中断优先级控制位。

​ 当PT1=0时,定时器1中断为最低优先级中断(优先级0)

​ 当PT1=1时,定时器1中断为最高优先级中断(优先级1)

PT0:

​ 定时器0中断优先级控制位。

​ 当PT0=0时,定时器0中断为最低优先级中断(优先级0)

​ 当PT0=1时,定时器0中断为最高优先级中断(优先级1)

注意:当定时器/计数器0工作在模式3(不可屏蔽中断的16位自动重装载模式)时,不需要允许EA/IE.7(总中断使能位)只需允许ET0/IE.1(定时器/计数器0中断允许位)就能打开定时器/计数器0的中断,此模式下的定时器/计数器0中断与总中断使能位EA无关。一旦此模式下的定时器/计数器0中断被打开后,该定时器/计数器0中断优先级就是最高的,它不能被其它任何中断所打断(不管是比定时器/计数器0中断优先级低的中断还是比其优先级高的中断,都不能打断此时的定时器/计数器0中断),而且该中断打开后既不受EA/IE.7控制也不再受ET0控制了,清零EA或ET0都不能关闭此中断

7. 定时器T2T3T4的中断控制寄存器:IE2

IE2 : 中断允许寄存器 (不可位寻址)

SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
IE2 AFH name ET4 ET3 ES4 ES3 ET2 ESPI ES2

ET4:定时器4的中断允许位。

​ 1,允许定时器4产生中断;

​ 0,禁止定时器4产生中断。

ET3:定时器3的中断允许位。

​ 1,允许定时器3产生中断;

​ 0,禁止定时器3产生中断。

ES4: 串行口4中断允许位。

​ 1,允许串行口4中断;

​ 0,禁止串行口4中断

ES3:串行口3中断允许位。

​ 1,允许串行口3中断;

​ 0,禁止串行口3中断。

ET2:定时器2的中断允许位。

​ 1,允许定时器2产生中断;

​ 0,禁止定时器2产生中断。

ESPI:SPI中断允许位。

​ 1,允许SPI中断;

​ 0,禁止SPI中断。

ES2: 串行口2中断允许位。

​ 1,允许串行口2中断;

​ 0,禁止串行口2中断。

以上案例代码如下:

#include <REGX52.H>
sbit S4 = P3^3;
sbit S5 = P3^2;

unsigned char minute,second,ms=0;
void _74HC138(unsigned char n) {
	switch(n) {
		case 4: P2 = (P2 & 0x1f) | 0x80;
		break;
		case 5: P2 = (P2 & 0x1f) | 0xa0;
		break;
		case 6: P2 = (P2 & 0x1f) | 0xc0;
		break;
		case 7: P2 = (P2 & 0x1f) | 0xe0;
		break;
	}

}



void SystemInit(void) {
	_74HC138(5);
	P0 = 0x00;
	_74HC138(4);
	P0 = 0xff;

}


void Display_Key(unsigned int t) {
	while(t--);
}


void Nixie(unsigned char Location,Number) 
{
	unsigned char code Num[11] = {
		0xc0,         // 0     1100 0000
		0xf9,        // 1           1111 1001
		0xa4,		// 2                1010 0100
		0xb0,       // 3        1011 0000
		0x99,            // 4       1001 1001
		0x92,              // 5     1001 0010
		0x82,                 //6        1000 0010
		0xf8,                   // 7     1111 1000
		0x80,                   // 8         1000 0000
		0x90,              // 9           // 1001 0000
		0xbf                     // -      1011 1111
	};
	
	switch(Location) {
		case 1: _74HC138(6);P0 = 0x01;break;
		case 2: _74HC138(6);P0 = 0x02;break;
		case 3: _74HC138(6);P0 = 0x04;break;
		case 4: _74HC138(6);P0 = 0x08;break;
		case 5: _74HC138(6);P0 = 0x10;break;
		case 6: _74HC138(6);P0 = 0x20;break;
		case 7: _74HC138(6);P0 = 0x40;break;
		case 8: _74HC138(6);P0 = 0x80;break;
	
	}
	_74HC138(7);
	P0 = Num[Number];
	// 动态数码扫描
	Display_Key(600);
	P0 =0xFF;

}




void Display_Nixie(void) {
	Nixie(1,minute/10);
	Nixie(2,minute%10);
	
	Nixie(3,10);
	
	Nixie(4,second/10);
	
	Nixie(5,second%10);
	
	Nixie(6,10);
	
	Nixie(7,ms/10);
	
	Nixie(8,ms%10);
	

} 
void ScanKey(void) {
	if(S4 == 0) {   // 启动与暂停
		Display_Key(200);
		if(S4 == 0) {
			// 第一次按下S4时,关闭定时器,第二次按下定时器开启
			TR1 = ~TR1;
			while(S4 == 0) {
				Display_Nixie(); 
			}
		
		}
	
	}
	
	if(S5 == 0) {
		Display_Key(200);
		if(S5 == 0) {
			minute = 0;
			second = 0;
			ms = 0;
			// 当S5按下的时候实时进行数码管的更新
			while(S5 == 0) {
				Display_Nixie(); 
			}
		}
	}

}

void Timer1Init(void) {
	
	TMOD = 0x10;
	// 50000 us == 50ms     50*20 = 1000ms = 1s
	TH1 = (65535 - 50000) /256;
	TL1 = (65535 - 50000) %256;
	ET1 = 1;   
	EA = 1;   // 打开总中断
	TR1 = 1;  // 打开定时器

}
void main(void) {
	SystemInit();
	Timer1Init();
	while(1) {
		Display_Nixie();
		ScanKey();
		
	}

}

void Timer1_Rountine(void) interrupt 3 {
	TH1 = (65535 - 50000) /256;
	TL1 = (65535 - 50000) %256;
	
	ms++;
	
	if(ms > 20) {
		second++;
		ms= 0;
		
		
		if(second > 59) {
			minute++;
			
			second=0;
			
			if(minute > 59) {
				minute = 0;
			}
		}
	
	}
	
	
	

}
posted @ 2023-10-06 12:09  夏日清凉~  阅读(98)  评论(0编辑  收藏  举报