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/ T M1 M0 GATE C/ T M1 M0
定时器1 定时器0
高四位控制定时器1:

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

C / 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 / 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 / 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 / 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中断。

以上案例代码如下:

copy
#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 @   夏日清凉~  阅读(138)  评论(0编辑  收藏  举报
相关博文:
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起