蓝桥杯单片机-定时器
定时器与中断是绑定一起的,在软件生成定时器初始化函数之后,要自己加上ET和EA使能,即赋为1.与中断寄存器不一样,TCON可以位寻址,TCON应该就是中断寄存器,他包括EA,ET0,.Tmod模式寄存器只能字节寻址,TMOD有八位,他的高四位控制定时器1和计数器1的模式选择,低四位控制的是定时器0和计数器0的模式选择。上图是小蜜蜂的视频,我的理解是,定时器和计数器本质上是计数器,作为定时器是他的信

上图是小蜜蜂的视频,我的理解是,定时器和计数器本质上是计数器,作为定时器是他的信息来源也就是脉冲来源就是内部晶振,等计数满了,也就是定时的时间到了,就去执行定时中断。作为计数器是就是外部信息作为一个脉冲,比如传感器监控传送带上通过了几个物体,然后设置的计数数量满了就触发计数中断,在ne555上测量频率,用的就是八位重装模式,所以本质上他们都是计数器,通过寄存器的不同设置可以用做不同的用途

上图为定时器和计数器的初值是如何设定的,也 就是TL0和TH0,这个只做理解。具体的初值设定有软件设定,

定时器与中断是绑定一起的,在软件生成定时器初始化函数之后,要自己加上ET和EA使能,即赋为1.与中断寄存器不一样,TCON可以位寻址,像上图,但是上图是其他51单片机的;TCON应该就是中断寄存器,他包括EA,ET0,.Tmod模式寄存器只能字节寻址,TMOD有八位,他的高四位控制定时器1和计数器1的模式选择,低四位控制的是定时器0和计数器0的模式选择。GAME位为0的时候就需要用TR0和TR1来启动,一般都是用TR0启动,我们一般用的是01模式,16位不重载,就需要在中断服务函数里面重新设置初值,重载就不需要,他会自动设置初值。c/t为0就是定时器,为1是计数器,
void Timer0_INT() interrupt 1 //大概1毫秒进一次中断服务函数
{
static unsigned int count;
TL0 = 0x66; //重装定时初值
TH0 = 0xFC; //重装定时初值
count++;
if(count>=1000) //建议要大于等于,不然可能刚好卡在一个机器周期瞬间超过之后就不响应
{
count=0;
sign=1;
}
}
以上是定时器中断的服务函数,有个基本的框架,容易忽视的是在函数中要记得重装定时初值,还有就是大于等于的问题,具体看上面;但是好像软件设置的定时初值有点模糊,具体还要看看江科大和小蜜蜂的视频;
2025-3-1修正:在软件上计算计时器就是我想的那样,具体还是看江科大的视频,小蜜蜂看到现在并没有教软件计算定时器
#include <REGX52.H>
#include "registerr.h"
unsigned char sign=0;
void Timer0Init(void) //1毫秒@11.0592MHz
{
// AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //软件生成之后要自己加上,EA也是;
EA=1;
}
void LED_run()
{
if(sign==1)
{
sign=0;
registerr(4);
P0=0x00;
}
}
void main()
{
Timer0Init();
while(1)
{
LED_run();
}
}
void Timer0_INT() interrupt 1 //大概1毫秒进一次中断服务函数
{
static unsigned int count;
TL0 = 0x66; //重装定时初值
TH0 = 0xFC; //重装定时初值
count++;
if(count>=1000) //建议要大于等于,不然可能刚好卡在一个机器周期瞬间超过之后就不响应
{
count=0;
sign=1;
}
}
以上是总体代码示例,可能定时精度有点问题;但是具体功能是实现了的;
#include <REGX52.H>
#include "registerr.h"
#include "Close.h"
unsigned char hour;
unsigned char min;
unsigned char sec;
unsigned char Keynum;
unsigned char Keynum_m;
unsigned char sign=1;//为1才进入中断
void Delay(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++)
for(j=0;j<110;j++);
}
void Timer0Init(void) //1毫秒@12.000MHz
{
// AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
unsigned char code SMG[]=
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf
};
void SMGG(unsigned char pos,unsigned char dat)
{
registerr(6);
switch(pos)
{
case 1 : P0=0x01;break;
case 2 : P0=0x02;break;
case 3 : P0=0x04;break;
case 4 : P0=0x08;break;
case 5 : P0=0x10;break;
case 6 : P0=0x20;break;
case 7 : P0=0x40;break;
case 8 : P0=0x80;break;
}
registerr(7);
P0=SMG[dat];
Delay(5);
}
void Scan_SMG()
{
SMGG(1,hour/10);
SMGG(2,hour%10);
SMGG(3,10);
SMGG(4,min/10);
SMGG(5,min%10);
SMGG(6,10);
SMGG(7,sec/10);
SMGG(8,sec%10);
}
void Ctrl()
{
if(Keynum==7)
{
sign=1;
}
if(Keynum==6)
{
sign=0;
}
if(Keynum_m==5)
{
hour=0;
min=0;
sec=0;
Keynum_m=0;
}
}
void KEY() //7启动;6暂停;5清零
{
if(P3_0==0)
{
Delay(20);
if(P3_0==0)
{
while(P3_0==0);
Keynum=7;
}
}
if(P3_1==0)
{
Delay(20);
if(P3_1==0)
{
while(P3_1==0);
Keynum=6;
}
}
if(P3_0==2)
{
Delay(20);
if(P3_2==0)
{
while(P3_2==0);
Keynum_m=5;
}
}
}
void main()
{
Timer0Init();
Close();
while(1)
{
KEY();
Ctrl();
Scan_SMG();
}
}
void Timer0_Rountine() interrupt 1
{
if(sign==1)
{
static unsigned int count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
count++;
if(count>=1000)
{
count=0;
sec++;
if(sec>=60)
{
sec=0;
min++;
if(min>=60)
{
min=0;
hour++;
if(hour>=24)
{
hour=0;
}
}
}
}
}
}
以上是用一个定时器制作时钟;唯一不足是数码管有点闪烁,解决办法有一个,用定时器扫描数码管,这个方法可以到江科大那里看教学,方法很精妙;
更多推荐



所有评论(0)