0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

定时器和数码管解析(下)

jf_78858299 来源:硬件攻城狮 作者:硬件攻城狮 2023-04-21 14:40 次阅读

1.2.3 定时器程序应用

了解了定时器相关的寄存器,那么我们下面就来做一个定时器的程序,巩固一下我们学到的内容。我们这节课的程序先使用定时器0,在使用定时器的时候,需要以下几个步骤:

第一步:设置特殊功能寄存器TMOD,配置好工作模式;

第二步:设置计数寄存器TH0和TL0的初值;

第三步:设置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,转成16进制就是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;

void main()

{

unsigned char counter = 0;

ENLED = 0; ADDR0 = 0; ADDR1 = 1;

ADDR2 = 1; ADDR3 = 1; LED = 1;  //74HC138和LED灯初始化部分

TMOD = 0x01;   //设置定时器0为模式1

TH0  = 0xB8;

TL0  = 0x00;   //定时值初值

TR0  = 1;      //打开定时器0

while(1)

{

    if(1 == TF0)            //判断定时器0是否溢出

    {

        TF0 = 0;

        TH0 = 0xB8;        //一旦溢出后,重新赋值

        TL0 = 0x00;

        counter++;

        if(50 == counter) //判断定时器0溢出是否达到50次

        {

             counter = 0;  //counter清0,重新计数

             LED = !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能看出来,数码管共有a,b,c,d,e,f,g,dp这8个段,而实际上,这8个段每一段都是一个LED小灯,所以数码管就是由8个LED小灯所组成的。我们看一下数码管内部结构图5-2。

图片

图5-3 数码管结构图

数码管分为共阳数码管和共阴数码管,所谓的共阴数码管就是8只LED小灯的阴极是接在一起的,也就是阴极是公共端,由阳极来控制小灯是否亮灭。同理,共阳数码管就是阳极是接到一起的,大家可以仔细研究下图5-2。细心的同学也会发现,数码管上边有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这4个输入状态写出来,现在大家不要偷懒,都去根据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可以轻而易举的看出来,如果我们点亮b和c这两个LED小灯,也就是数码管的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;

    unsigned int  i = 0;

    

    ENLED = 0;

    ADDR0 = 0;

    ADDR1 = 0;

     ADDR2 = 0;

    ADDR3 = 1;           //74HC138开启三极管Q17           

    while(1)             //程序死循环  

    {

         P0 = 0xF9;      //打开数码管b和c段   

    }

}

大家把这个程序编译一下,下载到单片机里会发现,最右侧的数码管成功显示1这个数字。

同样的方法,我们可以把其他的数字都成功的在数码管上显示出来,而数码管显示的数字对应给P0的赋值,我们叫做数码管的真值表。我们来列一下我们这个电路图的数码管真值表,注意,这个真值表里显示的数字都不带小数点。

表5-1 数码管真值表

数字 0 1 2 3 4 5 6 7
真值表 0xC0 0xF9 0xA4 0xB0 0x99 0x92 0x82 0xF8
数字 8 9 A B C D E F
真值表 0x80 0x90 0x88 0x83 0xC6 0xA1 0x86 0x8E

大家可以把上边那个数码管显示1的那个程序中的P0的赋值随便修改成我们表5-1中的真值表里的数字试试看,把数码管显示的数字显示出来。

1.3.3 数码管的静态显示

从第三课我们学习74HC138以后,我们了解到74HC138同时一次只能让一个输出口为低电平,也就是在一个时刻内,我们只能让一个数码管显示,始终选通数码管并且可以根据我们的P0总线的信号来改变这个数码管的值,我们可以理解为数码管的静态显示。

数码管静态显示是对应动态显示而言的,静态显示对于一两个数码管还行,多个数码管,静态显示实现的意义就没有了。这节课我们先用一个数码管的静态显示来实现一个简单的秒表,为下节课的动态显示打下基础。

先来介绍一个51单片机的关键字code。我们前边课程定义变量的时候,一般用到unsigned char或者unsigned int这两个关键字,这样定义的变量都是放在我们的单片机的RAM中,我们在程序中可以随意去改变这个变量的值。但是还有一种常数,我们在程序中要使用,但是却不进行对这个值的改变,这种值我们可以加一个code关键字修饰一下,修饰完毕后,这个值就会存储到我们的程序空间flash中,这样可以大大节省我们单片机的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;

unsigned char code LedChar[] = {

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

0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e

}; //用数组来存储数码管真值表,下一课详细介绍数组

void main()

{

unsigned char counter = 0;

unsigned char j = 0;

ENLED = 0; ADDR0 = 0; ADDR1 = 0;

 ADDR2 = 0; ADDR3 = 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;

        counter++;

        if(50 == counter)      //判断定时器0溢出是否达到50次

        {

            counter = 0;        //counter清0,重新计数

            P0 = LedChar[j++]; //把数组里的对应值送给P0

            if(16 == j)         //当显示到F后,归0重新开始

            {

                 j = 0;

            }

         }

     }

}

}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5185

    浏览量

    118368
  • 定时器
    +关注

    关注

    23

    文章

    3186

    浏览量

    112710
  • 程序
    +关注

    关注

    114

    文章

    3673

    浏览量

    79869
收藏 人收藏

    评论

    相关推荐

    定时器扫描数码管、独立按键,秒表

    数码管定时器
    jf_63233237
    发布于 :2023年04月22日 13:34:00

    单片机定时器,编译后数码管不显示

    本帖最后由 tangbenchang 于 2014-2-14 15:48 编辑 程序如图所示,使用定时器数码管显示,从0-9。编译成功,仿真的时候数码管不显示,调试发现定时器
    发表于 02-14 15:45

    利用定时器精确设定时间,动态扫描数码管,显示当前时间

    6个数码管,利用两个573锁存,控制片选,段选,利用定时器精确定时1s,显示当前时间attach://201704.rar
    发表于 06-29 11:13

    单片机基础数码管按键定时器

    数码管显示一个十进制数范围00-59,按K6键一数值加1,按K5键一数值减1。 每按K
    发表于 05-01 09:06

    求按键控制数码管定时器定时显示的程序,我实在想不通按键怎么控制数码管

    求按键控制数码管定时器定时显示的程序,我实在想不通按键怎么控制数码管,例子也成
    发表于 10-20 12:33

    为什么定时器控制静态数码管会闪烁?

    定时器控制静态数码管闪烁,编译没有错误,但逻辑不知哪错了,求大佬指导
    发表于 10-09 02:28

    Template数码管的相关资料下载

    驱动:3、Template部分主程序:三、定时器定时扫描1、Template数码管显示转换:2、Template数码管显示:3、Template定时
    发表于 12-09 08:00

    基于单片机的综合应用程序数码管【C语言】定时器控制数码管

    基于单片机的综合应用程序数码管【C语言】定时器控制数码管
    发表于 01-06 13:44 27次下载

    LESSON3_数码管静态显示及定时器和中断应用

    LESSON3_数码管静态显示及定时器和中断应用
    发表于 02-18 18:21 0次下载

    定时器扫描数码管(不闪烁)

    定时器扫描数码管(不闪烁) C51单片机源码,KEIL源文件,C语言编写
    发表于 06-20 16:36 7次下载

    LESSON3_数码管静态显示及定时器和中断应用

    数码管是如何显示出字符的 数码管静态显示与动态显示原理 中断概念 单片机的定时器应用
    发表于 07-01 17:17 1次下载

    基于8051的Proteus仿真-定时器控制数码管动管显示

    基于8051的Proteus仿真-定时器控制数码管动管显示
    发表于 09-01 23:33 19次下载

    STM32+Proteus仿真实现滴答定时器计时和数码管实时显示功能

    STM32+Proteus仿真实现滴答定时器计时和数码管实时显示功能
    发表于 11-24 21:06 73次下载
    STM32+Proteus仿真实现滴答<b class='flag-5'>定时器</b>计时<b class='flag-5'>和数码管</b>实时显示功能

    定时器和数码管解析(上)

    不管是数字电路,还是C语言,我们都会经常遇到逻辑运算和逻辑电路,在这里我介绍一下,大家先简单了解一下,知道有这么回事,回头遇到了,再详细研究。 首先,在“逻辑”这个概念范畴内,存在真和假这两个逻辑值,而将其对应到数字电路或C语言中,就变成了“非0值”和“0值”这两个值,即逻辑上的“假”就是数字电路或C语言中的“0”这个值,而逻辑“真”就是其它一切“非0值”。
    的头像 发表于 04-21 14:27 570次阅读
    <b class='flag-5'>定时器</b><b class='flag-5'>和数码管</b><b class='flag-5'>解析</b>(上)

    使用定时器和数码管实现简易秒计时器

    从今天开始,我们利用上前几天学习的定时器和数码管,一起设计一个简单的秒计时器。
    的头像 发表于 11-02 10:50 951次阅读
    使用<b class='flag-5'>定时器</b><b class='flag-5'>和数码管</b>实现简易秒计时器