基于Proteus与keil联合仿真的51单片机学习记录(五)(使用T/C的工作方式0定时)
使用T/C的工作方式0定时
(一)、设计要求
用T0的工作方式0来设计一个控制灯闪烁。定时器0每5ms产生一个中断,每秒让灯闪烁一次;另外,用外部中断“开始”、“停止”按钮控制定时器T0的开始和关闭。
(二)、程序设计
首先是定时器初值的问题,定时器T0的工作方式0是13位定时器,也就是最大计数值是8 191,再计数加1后,溢出,共8 192个数。我们用12MHz的晶振,每一个机器周期计数器计数加1一次,而一个机器周期是12个时钟周期,也就是每微秒定时器计数加1。要使其每间隔5ms产生一个中断,就是计数器计数5 000产生一个中断,因而初始值是8 192-5000=3 192。而TL0是低5位有效(最大值0x1F即31),也就是每32个计数TH0进位一次。这样就可以计算TH0、TL0的初始值:TH0=3192/32=99=0x63;TL0=3 192%32=24=0x18(注:TL0的值是3 192对32取余)。
/*****************************************************************************
******************************************************************************************
***
* 文件名:main.c
* 说 明:使用T/C的工作方式0定时
******************************************************************************
******************************************************************************************
**/
#include "reg51.h"
#include "main.h"
#include "delay.h"
sbit LED1 = P2^0;
uchar g_ucNum;
/*****************************************************************************
******************************************************************************************
***
* 函数名:Int0中断函数,0是Int0的中断号
* 参 数:空
* 返回值:无
******************************************************************************
******************************************************************************************
***/
void int0_inter() interrupt 0
{
g_ucNum = 0;
TL0 = 0x18; //定时器赋初值,保证每一次开启中断号后都从此初值开始计数
TH0 = 0x63;
TR0 = 1; //打开定时器中断(由于默认gate为0,此时的定时器中断由TR控制)
}
/*****************************************************************************
******************************************************************************************
***
* 函数名:Int1中断函数,2是Int1的中断号
* 参 数:空
* 返回值:无
******************************************************************************
******************************************************************************************
***/
void int1_inter() interrupt 2
{
TR0 =0; //关闭定时器中断
}
/*****************************************************************************
******************************************************************************************
***
* 函数名:定时器T0的中断函数
* 参 数:空
* 返回值:无
******************************************************************************
******************************************************************************************
***/
void timer0_inter() interrupt 1
{
g_ucNum++; //在每次执行中断时对g_ucNum数值进行累加
TL0 = 0x18; //重新对定时器赋初值
TH0 = 0x63;
}
/*****************************************************************************
******************************************************************************************
***
* 函数名:主函数,初始化外部中断、定时器中断
* 参 数:无
* 返回值:无
******************************************************************************
******************************************************************************************
***/
void main (void)
{
g_ucNum = 0;
P2 = 0xFF;
P3 = 0xFF;
IT0 = 1; //下降沿触发模式 或可以写成 TCON |= 0x05;
IT1 = 1;
EX0 = 1; //打开Int0外部中断
EX1 = 1; //
TMOD = 0; //定时器模式,工作方式0
TL0 = 0x18;
TH0 = 0x63;
ET0 = 1; //定时器溢出中断允许
EA = 1; //打开全局中断
while(1)
{
if(g_ucNum >= 200)
{
g_ucNum = 0;
LED1 = ~LED1;
}
}
}
在主程序中完成了定时器的初始设置工作:TMOD=0,设定定时器的工作模式为定时器模式而非计数器模式,工作方式为方式0即13位定时器;TH0、TL0设定定时器的初始值;ET0=1使能定时器0的中断功能;然后通过EA=1使能全局中断,这样就可以进入外部中断和定时器中断了。
(三)、硬件设计
(四)、知识补充
一、可位寻址与不可位寻址
位寻址指的是这个寄存器中各位值可以直接调用
如:可位寻址的IE中有八位EA - ET2 ES ET1 EX1 ET0 EX0可以直接用ET2=1来操作;
不可位寻址的TMOD只能用TMOD=0x00来控制其中的各位。
不可以未开控制其中的某一位,不可以单独赋值给某一位。
二、几个专用寄存器
1.计数寄存器TH0、TL0、TH1、TL1
TH0、TL0是两个8位寄存器,正是由这两个寄存器组成了T/C0的16位定时/计数功能。同样,TH1、TL1是T/C1的两个8位计数寄存器。也就是说在我们将定时器中断打开的前提下,当这两个寄存器计数溢出时,就会发生定时/计数器中断。
2.T/C工作方式寄存器TMOD
从表中可以看出,TMOD的高4位是用来控制T/C1的,低4位是用来控制T/C0的,我们以低4位来说明每个位的用途。
T0_GATE:门控制位。该位设置为1,T/C0的启动与停止由TCON寄存器中TR0和外部中断引脚INT0上的电平状态共同控制;该位设为0,T/C0的启动与停止仅受TCON寄存器中TR0的控制。通常会使用后一种方式,即设定该位为0(系统复位时,该位默认为0)。
T0_CT:定时/计数器工作模式选择位。该位设置为1,T/C0为计数器工作模式;该位设为0,T/C0为定时器工作模式。
T0_M0、T0_M1:工作方式选择位。每个T/C都有4种工作方式,它们由M1M0来设定,具体见下表。
3.各工作方式的应用
注意:定时器0的工作模式3是分为两个8位的定时器,需要占用标志位TF1、TR1,这时定时器1不能使用中断,而且定时/计数器的工作方式3只对定时器0有效,当定时器1设定为工作方式3时,其将停止计数。
上一篇: PS制作一个只属于你的头像
下一篇: 主流数字加密技术面面观