关键词:定时器;中断;寄存器配置;定时器计时初值计算;长定时编程思想;小蜜蜂
一、知识点
1.定时/计数器原理,内部时钟脉冲和外部输入信号
2.计数初值寄存器TLX和THX
65535 - 10000 = 55535 = 0xd8ef
TH0 = 0xd8;或者 TH0 = (65535 - 10000) / 256;
TL0 = 0xef; 或者 TL0 = (65535 - 10000) % 256;
3.TMOD和TCON
4.初始化函数和中断服务函数的编程思想
详细参考:
1.【蓝桥杯单片机08】定时器的基本原理与应用
https://bbs.21ic.com/icview-2477676-1-1.html?fromuser=%E9%9B%B6%E5%9F%BA%E7%A1%80%E5%B0%8F%E5%A4%95
(出处: 21ic电子技术开发论坛)
2.51单片机学习笔记(中断系统)http://t.csdnimg.cn/4XaH8
二、实验
实验目的:
实验步骤:
S1:L1和L8位声明+HC573锁存器让Y4使能
sbit L1=P0^0;
sbit L8=P0^7;
//让HC573的Y4信道打开,使P0控制LED
void SelectHC573(void)
{
P2=(P2&0x1F)|0x80;
}
S2:定时器0初始化函数
思想:!!!可模块化
1.TMOD设置(以字节为单位),只管定时器0,TMOD=0x01
2.计数初值设置TL0和TH0——>长定时编程思想:最大65.5ms,要求0.5s即500ms闪烁L1,故将500ms分为50ms*10,以50ms对应50000个脉冲(1us对应1个脉冲,在12MHZ、12分频下),中断服务函数中对每满50ms进行计数——>计数变量count,直到count=10,执行L1闪烁功能,并将count清零
3.中断开关打开(EA=1;ET0=1;)
4.定时器开始工作(TR0=1;)
代码:
void Init_Timer0()//初始化计数/定时器0
{
TMOD=0x01;
TH0=(65535-50000)/256;//12MHZ,12分频后,为1MHZ,每个脉冲的周期为1us
TL0=(65535-50000)%256;//这里则记了50000个脉冲,相当于记了50ms,小单元,最大记65.5ms
ET0=1;
EA=1;//中断开关打开
TR0=1;//定时器开始工作,计时
}
S3:定时器0的中断服务函数
代码:
unsigned char count=0;
void ServiceTimer0() interrupt 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;//没有自动重装功能,溢出后到中断里需要重新定初值
count++;
if(count==10)
{
L1=~L1;//L1闪烁
count=0; //清零count
}
}
S4:main函数
void main()
{
SelectHC573();
Init_Timer0();
while(1)
{
}
}
实验现象:
L1每隔0.5s闪烁1次
S5:对L8也进行相同处理
unsigned char count1=0;
unsigned char count=0;
void ServiceTimer0() interrupt 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;//没有自动重装功能,溢出后到中断里需要重新定初值
count++;
count1++;
if(count==10)
{
L1=~L1;//L1闪烁
count=0; //清零count
}
if(count1==100)
{
L8=~L8;
count1=0;
}
}
优化:对于L8还需要一个count1,能否共用1个count呢?——>L1闪烁是每逢10的倍数,清零只需在大的(count1==100中)
unsigned char count=0;
void ServiceTimer0() interrupt 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;//没有自动重装功能,溢出后到中断里需要重新定初值
count++;
if(count%10==0)
{
L1=~L1;//L1闪烁
}
if(count==100)
{
L8=~L8;
count=0;
}
}
三、总结收获
1.定时器计数初值计算
2.长定时编程思想
3.中断初始化函数和中断服务函数
感谢B站小蜜蜂老师的教程,本笔记资料及代码均来自教程,仅作为个人复习、整理和学习交流用。