第5章 定时器与数码管基础

时钟周期:时钟周期 T 是时序中最小的时间单位。晶振是 11.0592M,则时钟周期=1/11059200 秒。

机器周期:单片机完成一个操作的最短时间。51单片机系列,在其标准架构下一个机器周期是 12 个时钟周期,也就是 12/11059200 秒。对于增强型单片机,一个机器周期可能只需要4个时钟周期。

定时器:作用用来定时。定时器内部有一个寄存器,我们让它开始计数后,这个寄存器的值每经过一个机器周期(标准51单片机也就是12/11059200 秒)就会自动加 1。当计数达到某一值,产生溢出,具体溢出值根据定时器模式不同而不同。

标准的 51 单片机内部有 T0 和 T1 这两个定时器。对应特殊功能寄存器如下:

是定时器控制寄存器 TCON 位分配寄存器各位功能描述:

TMOD寄存器介绍:

模式 1,是 THn 和 TLn 组成了一个 16 位的定时器,计数范围是 0~65535,溢出后,只要不对 THn 和 TLn 重新赋值,则从 0 开始计数。

模式 2,是 8 位自动重装载模式,只有 TLn做加 1 计数,计数范围 0~255,THn 的值并不发生变化,而是保持原值,TLn 溢出后,TFn就直接置 1 了,并且 THn 原先的值直接赋给 TLn,然后 TLn 从新赋值的这个数字开始计数。 

使用定时器步骤:

第一步:设置特殊功能寄存器 TMOD,配置好工作模式。
第二步:设置计数寄存器 TH0 和 TL0 的初值。
第三步:设置 TCON,通过 TR0 置 1 来让定时器开始计数。
第四步:判断 TCON 寄存器的 TF0 位,监测定时器溢出情况。 

 

使用定时器计算时间,假如需要定时0.2s,首先需要确定定时器需要多长时间才会使计数器加1,一般是1/11059200s,那么需要计数多少才能达到0.2s?

应该是0.2/(1/11059200);再计算需要给计数器赋初始值多少,才能确保计数0.2/(1/11059200)之后达到溢出状态?对于模式1的16位定时器,其最大计数到65535,那么可以得到需要给定时器赋初值为65536-0.2/(1/11059200)。

 

使用定时器完成小灯一秒钟的闪烁,代码如下:

#include <reg52.h>

sbit LED = P0^0;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

void main()
{
    unsigned char cnt = 0;  

    ENLED = 0;   
    ADDR3 = 1;
    ADDR2 = 1;
    ADDR1 = 1;
    ADDR0 = 0;
    TMOD = 0x01;  //设置T0为模式1
    TH0  = 0xB8;  //定时0.2s赋初值,计算得出
    TL0  = 0x00;
    TR0  = 1;     //启动T0
    
    while (1)
    {
        if (TF0 == 1)        //判断T0是否溢出
        {
            TF0 = 0;         //清零中断标志并重新赋初值
            TH0 = 0xB8;     
            TL0 = 0x00;
            cnt++;           
            if (cnt >= 50)   //溢出达到50次,累计计时正好1秒钟
            {
                cnt = 0;     
                LED = ~LED;  
            }
        }
    }
}

数码管

数码管原理图:

数码管共有 a、b、c、d、e、f、g、dp 共8 个段,每段可以当作是一个led小灯。

数码管有共阴极和共阳极两种,其结构示意图如下:

数码管真值表如下 :

数码管原理图:

对应译码器电路图:

数码管静态显示,让数码管DS1显示数字1,代码如下:

#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void main()
{
 ENLED = 0; //使能 U3,选择数码管 DS1
 ADDR3 = 1;
 ADDR2 = 0;
 ADDR1 = 0;
 ADDR0 = 0;
 P0 = 0xF9; //点亮数码管段 b 和 c
 while (1);
}

实现数码管从0到F依次显示,间隔时间为1秒,代码如下:

#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
unsigned char code LedChar[] = {
 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void main()
{
	 unsigned char cnt = 0; //记录 T0 中断次数
 unsigned char sec = 0; //记录经过的秒数
 ENLED = 0; //使能 U3,选择数码管 DS1
 ADDR3 = 1;
 ADDR2 = 0;
 ADDR1 = 0;
 ADDR0 = 0;
 TMOD = 0x01; //设置 T0 为模式 1
 TH0 = 0xB8; //为 T0 赋初值 0xB800
 TL0 = 0x00;
 TR0 = 1; //启动 T0
 
 while (1)
 {
 	if (TF0 == 1) //判断 T0 是否溢出
 	{
		 TF0 = 0; //T0 溢出后,清零中断标志
		 TH0 = 0xB8; //并重新赋初值
		 TL0 = 0x00;
		cnt++; //计数值自加 1
		 if (cnt >= 50) //判断 T0 溢出是否达到 50 次
		 {
		 cnt = 0; //达到 50 次后计数值清零
		 P0 = LedChar[sec]; //当前秒数对应的真值表中的值送到 P0 口
		 sec++; //秒数记录自加 1
		 if (sec >= 16) //当秒数超过 0x0F(15)后,重新从 0 开始
			 {
				 sec = 0;
			 }
		 }
	 }
}

}

 

posted @   灵动24  阅读(573)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示