赞
踩
图1
图2
图3
图4
图3表示SYSclk的工作原理:因为ST89C52开发板上的晶振为12MHZ,所以系统会产生脉冲,慢慢达到12M,达到12MHZ之后经过上面的12兆分频的话,就是1兆赫兹,1兆赫兹1个周期就是1us。联通如图所示的计数器,就是每隔1us记一次数,记到最大值,产生中断。
图·5
SYSclk:系统时钟,即晶振周期,ST89C52开发板上的晶振为12MHZ。
定时器工作原理:如图4所示左边的计数系统会发送给定时器脉冲,计数器每隔一个脉冲就会加1,但因为是之前选择定时器工作模式是模式1,所以定时器只能接受到65535,到了65535就会溢出,TF0置于1,计数器归0,产生中断。
寄存器是连接软硬件的媒介。
在单片机中寄存器就是一段特殊的RAM存储器一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式。
寄存器相当于一个复杂机器的“操作按钮。
每个定时器主要有两种寄存器:TCON TMOD。
TCON 包括:TF, TR, IE, IT。
定时器和中断结合:时钟计数,到了时间之后,定时器发起中断请求,中断导通后实现主函数的中断,先去执行中断函数,再执行主函数。
图6
编写代码的时候,首先编写TMOD=0X01;即0000 0001,倒数第3位为0表示是定时器状态,M1和M0为01表示工作在模式1,使用16位定时器;
低四位中GATE=0表示定时器只需要图2所示的TR0控制——因为从图3可知,中间那部分为计数单元,GATE如果给0,经过非门之后,得到1,INTO是或门,所以无需考虑它,计数单元只由TR0控制。
图7
编写定时器代码首先编写:TMOD=0X01;
图8
可位寻址:表示能分开,eg:P3=0;P3_1=1;
不可位寻址:表示不能分开
TF=0;表示不会刚开始就去申请中断
TR0=1;TR表示定时器是否开始,TR=1表示开启,TR=0表示中断
图9
关于计时问题
0~65535
每隔1us计数加一
总共定时时间65535us
开始定64535离计数器溢出差值1000,所以计时时间为1ms
TH0和TL0是存储数值的,其中TH0存储的是高位,TL0存储的是低位
所以定时器存储数据代码为:
TH0=64535/256
TL0=64535%256
ET0=1;//打开定时器0 中断允许
EA=1;//打开总中断
PT=0;//优先级默认是低位
到此定时器模块函数构造完成。
time0.c代码
#include <REGX52.H>
void Timer0_Init(void) //1毫秒@12.000MHz
{
//这里只用到一个定时器,一个就行
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //打开定时器0 中断允许
EA=1; //打开总中断
PT0=0; //优先级为0
}
中断部分的代码不需要调用,直接就能运行,原理已在之前讲过。
time0.h包含time0.c的函数,INTRINS.H是为了使用_crol_和_cror_函数
main.c代码
#include <REGX52.H>
#include "time0.h"
#include "Delay.h"
#include <INTRINS.H>
unsigned char flag=0;
unsigned int time=0;
void main()
{
P2=0xfe;
Timer0_Init();
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
time++;
if(time%2!=0)
{
flag=1;
}
else
{
flag=0;
}
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int count;
count++;
TL0 = 0x18; //设置定时初始值否则从0开始计数
TH0 = 0xFC; //设置定时初始值
if(count>=1000)
{
count=0;
if(flag!=0)
{
P2=_crol_(P2,1);
}
else
{
P2=_cror_(P2,1);
}
}
}
最终效果可实现按键控制LED灯左右移动。
基于定时器的按键控制LED流水灯
自己做了一下按第一个按键LED流水灯向右移动,按第二个按键向左移动的代码。
#include <REGX52.h>
#include <time0.h>
#include <Delay.h>
unsigned char num=0;
unsigned char flag;
void main()
{
time0_init();
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
flag=1;
}
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
flag=0;
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int count;
count++;
TL0 = 0x18; //设置定时初始值否则从0开始计数
TH0 = 0xFC; //设置定时初始值
if(count>=1000)
{
count=0;
if(flag==1) //LED流水灯向做右移动的代码
{
if(num<8)
{
P2=~(0x01<<num);
num++;
if(num==8)
{
num=0;
}
}
}
else //LED流水灯向做左移动的代码
{
if(num>0)
{
num--;
P2=~(0x01<<num);
if(num==0)
{
num=8;
}
}
}
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。