当前位置:首页 > 工业园区 >定时器控制数码管(利用定时器控制数码管的显示原理)

定时器控制数码管(利用定时器控制数码管的显示原理)

1.2.3 定时器程序应用

了解了定时器相关的寄存器之后,我们来做一个定时器程序来巩固一下所学的知识。本课我们的程序首先使用定时器0。使用定时器时,需要执行以下步骤:

定时器控制数码管(利用定时器控制数码管的显示原理)

步骤1:设置特殊功能寄存器TMOD并配置工作模式;

步骤2:设置计数寄存器TH0和TL0的初始值;

步骤3:设置TCON,并通过打开TR0位让定时器开始计数。

第四步:判断TCON寄存器的TF0位,监控定时器溢出。

在编写程序之前,我们首先要学会如何使用定时器来计算时间。我们的晶振是11.0592M,时钟周期是1/11059200,机器周期是12/11059200。如果我们要计时20ms,那就是0.02秒。需要x 个机器周期才能获得0.02 秒。我们来计算x*12/11059200=0.02,得到x=18432。那么我们当前的16位定时器溢出值为65536。我们可以这样做,首先给TH0和TL0一个初始值,让它们在18432个机器周期后刚刚溢出。溢出后,我们通过检测TF0位就可以知道,正好。是0.02秒。这个初始值y=65536 - 18432=47104,转换为十六进制是0xB800,那么TH0=0xB8,TL0=0x00。

我们已经超时了0.02 秒。细心的同学会发现,如果我们直接给初始值0x0000,直到65536溢出,定时器最大计时值约为71ms。那么如果我们想要计时的时间更长的话该怎么办呢?使用你在小学学到的逻辑,多重关系可以解决这个问题。

好了,我们用程序来实现下面的功能。

#include //包含寄存器的库文件

sbit LED=P0^0;

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ENLED=P1^4;

无效主()

{

无符号字符计数器=0;ENLED=0;地址0=0;地址1=1;地址2=1;地址3=1; LED=1; //74HC138及LED灯初始化部分TMOD=0x01; //设置定时器0为模式1TH0=0xB8;TL0=0x00; //定时器值TR0的初始值=1; //打开定时器0 while(1){ if(1==TF0) //判断定时器0是否溢出{ TF0=0; TH0=0xB8; //一旦溢出,重新分配TL0=0x00;计数器++; if(50==counter) //判断定时器0是否溢出50次{ counter=0; //计数器清0并重新计数LED=!引领; //LED反转操作, 0--1, 1--0 } } }}

程序都有注释,所以理解起来并不困难。这里需要解释的一件事是两个if判断。细心的同学会发现,在if(1==TF0)这句话中,我在它的前面写了1。我建议新手按照我这里的说明进行操作。我们这样写,是因为如果我们写if(TF0==1),作为新手,不小心丢了一个‘=’号后,我们写成if(TF0=1),其实语法上是可以接受的。我们使用的Keil4也会发出警告说明,以前版本的Keil和其他一些软件可能根本不会发出任何错误或警告,但是当这样生成的Hex文件下载到单片机时,程序就会出错。你可以尝试改变一下。

这个程序的结果是我们板上最右边的小灯亮一秒灭一秒,即以0.5HZ的频率闪烁。

1.3 数码管学习

小灯是一个简单的LED,给我们带来视觉效果,只能通过打开和关闭来表达简单的信息。在本课中,我们将研究一种表达更清晰的设备——数码管。

1.3.1 数码管基本介绍

我先给大家提供一个示意图,如图5-1所示。

图5-2 数码管原理图

这是一个比较常见的数码管的原理图。我们的板上一共有6个数码管。有了前面LED小灯的学习,数码管的学习就会轻松很多。从图5-1可以看出,数码管有8段a、b、c、d、e、f、g、dp。其实这8段每段都是一个小LED灯,所以数码管是由8个小LED灯组成的。我们看一下数码管的内部结构,如图5-2。

图5-3 数码管结构图

数码管分为共阳极数码管和共阴极数码管。所谓共阴极数码管,就是8个LED小灯的阴极连接在一起,即阴极为公共端,阳极控制小灯的亮或灭。同理,共阳极数码管就是阳极连接在一起的。大家可以仔细研究下图5-2。细心的同学还会发现数码管上有两个com,其实就是我们数码管的公共端子。为什么有2个?我个人认为,一方面,有2个可以达到对称的效果,正好是10个引脚。另一方面,通过公共端子的电流较大。我们初中就学过,并联电路中的电流之和等于总电流。使用2个COM可以将公共电流平均到2个引脚,减少线路所能承受的电流。

从我们板子的电路图可以看出,我们使用的数码管是共阳极数码管,如图5-3所示。

图5-4 共阳极数码管电路

它们的com 连接到正极端子。当然,与LED灯电路类似,74HC138也通过控制三极管的导通来控制整个数码管的电流。我们先看DS1数码管。从原理图中可以看出,控制DS1的晶体管是Q17,控制Q17的引脚是LEDS0,对应74HC138上Y0的输出。

图5-5 74HC138控制框图

我们当前的目标是让LEDS0引脚输出低电平。相信你现在已经可以根据之前所学的知识,独立写出ADDR0、ADDR1、ADDR2、ADDR3、ENLED这四种输入状态了。现在别偷懒了。去按照138手册去写吧。这些结论不要求你记住,遇到就写一次。多练习几次,遇到类似的芯片就知道如何解决问题了。

数码管通常用来显示数字。我们板上的6个数码管习惯上称为6位,选择的控制位是74HC138。数码管内部的8个小LED灯称为数码管的段。然后通过P0口控制数码管的段选择(即段的亮灭),由74HC245驱动。

1.3.2 数码管真值表

我们直接控制数码管的8段作为8个小LED灯,即a、b、c、d、e、f、g、dp,一共8个小LED灯。从图5-1我们不难看出,如果我们点亮两个小LED灯b、c,也就是数码管的b、c段,而其他段全部熄灭,则数码管DS1虽然显示数字1 ,那么此时P0的二进制值实际上是0b11111001,十六进制值是0xF9。还有可以自动生成数码管段码的软件。您可以从http://www.51hei.com/mcudown/下载。文件名为“数码管分段编码程序.rar”。那我们就写一个程序,让数码管显示出来。看。

#include //包含寄存器的库文件sbit ADDR0=P1^0;sbit ADDR1=P1^1;sbit ADDR2=P1^2;sbit ADDR3=P1^3;sbit ENLED=P1^4;void main(){ unsigned char j=0;无符号整数i=0;使能LED=0;地址0=0;地址1=0;地址2=0;地址3=1; //74HC138 打开晶体管Q17 while(1) //程序无限循环{ P0=0xF9 ; //打开数码管的b段和c段}}

如果你编译这个程序并下载到单片机中,你会发现最右边的数码管成功显示了数字1。

表5-1 数码管真值表

Number 01234567 真值表0xC00xF90xA40xB00x990x920x820xF8 number 89ABCDEF 真值表0x800x900x880x830xC60xA10x860x8E 可以随意修改程序中数码管显示1 的P0 的赋值为我们表5-1 真值表中的数字尝试一下,把数字管显示屏上显示数字。

1.3.3 数码管静态显示

我们在第三课学习了74HC138后,了解到74HC138一次只能使一个输出口为低电平,即一次只能使一个数码管显示,总是选择数码管,可以根据我们的P0总线信号改变了这个数码管的值,我们可以理解为数码管的静态显示。

数码管的静态显示对应于动态显示。静态显示适合一两个数码管。但如果有多个数码管,静态显示就没有意义了。本课我们首先利用数码管的静态显示来实现一个简单的秒表,为下一课的动态显示打下基础。

首先介绍一下51单片机的关键字代码。在前面的课程中我们定义变量的时候,一般都会用到unsigned char或者unsigned int这两个关键字。以这种方式定义的变量被放置在我们微控制器的RAM 中。我们可以在程序中随意改变这个变量的值。但是还有另一种常量,我们在程序中使用但不改变其值。我们可以添加一个code关键字来修改这个值。修改完成后,该值将被存储到我们的程序空间中。在闪存中,这可以大大节省我们微控制器的RAM使用量。毕竟我们的RAM空间比较小,但是程序空间却很大。比如我们现在要用到的数码管真值表,下面看看我们的程序。

#include //包含寄存器的库文件

sbit LED=P0^0;

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ENLED=P1^4;

无符号字符代码LedChar[]={

0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,

0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e}; //用一个数组来存储数码管的真值表。下一课将详细介绍数组。

无效主()

{

无符号字符计数器=0;无符号字符j=0;ENLED=0;地址0=0;地址1=0;地址2=0;地址3=1; P0=0XFF; //74HC138及P0初始化部分TMOD=0x01; //设置定时器0为模式1 TH0=0xB8;TL0=0x00; //定时器值TR0的初始值=1; //打开定时器0 while(1){ if(1==TF0) //判断定时器0是否溢出{ TF0=0; TH0=0xB8; //溢出后,重新赋值TL0=0x00;计数器++; if(50==counter) //判断定时器0是否溢出50次{ counter=0; //计数器清0,重新计数P0=LedChar[j++]; //将数组中对应的值发送到P0 if(16==j) //当显示F时,返回0并重新开始{ j=0; } } }}}

最新资讯

推荐资讯