找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10999|回复: 3
打印 上一主题 下一主题
收起左侧

51单片机数码管显示60秒倒计时(C语言程序)

[复制链接]
跳转到指定楼层
楼主
本帖最后由 KeepYn 于 2021-7-2 07:30 编辑

基于普中51单片机开发板,运用定时器/计数器0和1,实现60秒的倒计时和LED灯0.5s间隔闪烁
本程序涉及中断,定时器的配置,数码管动态扫描知识。程序基于模块化编写。程序里有详细的注解。

一、数码管动态扫描
数码管分为静态和动态两种显示方法。一般多位数码管选用动态显示,这样可以节约单片机的端口资源。但是需要外加数码管驱动电路。在此用的是138译码器。可以简称为38译码器,三通道输入,八通道输出。通过3通道即可控制8位数码管。也就是说只用占用单片机的3个端口。
只用了解其真值表即可    A为控制端              Y为数码管端。

数码管动态扫描的原理是利用人肉眼的视觉残留。在此需要说两个概念位选和段选。位选就是用来控制那个数码管显示的。段选是用来控制显示的内容 的。在很短的时间内送出段码和控制未选来实现数码管的动态显示。
共阳数码管段码:
             char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};  0~F
共阴数码管段码:
            char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  0~F


二、中断、定时器/计数器
  中断、定时器/计数器。的难点就在于对各种相关寄存器。
定时器/计数器的相关寄存器,定时器/计数器的实质是加1计数器。可以对其选择是定时模式还是计数模式。

中断号格式,可以参照这个来。
  中断号0   外部中断0中断号
  中断号1    定时计数器0中断号
  中断号2    外部中断1中断号
  中断号3   定时计数器1中断号
  中断号4    串行口中断序号
  中断号5    定时计数器2中断号


有很多的相关资料,我能力有限,对此我就不过多赘述了。程序里有详细的注解。

现象视频下面是一个我上传到哔哩哔哩上十几秒的程序现象小视频 : https://b23.tv/IlFvwU


程序文件
程序源文件:https://download.csdn.net/download/qq_54311788/19976902

二、代码
1.MAIN

/*****
"hardware.h"自创的头文件、hardware翻译为:五金器具; 计算机硬件; 武器装备;
“”用于自己创建的头文件、<>反之 例:<reg51.h>

******/
#include "hardware.h"  //此头文件已包含了<reg51.h>头文件
void main()
{
        TMOD = 0X11;       //设置定时器1和定时器0为工作方式1,16位定时器/计数器
        /****
        0X11>0001 0001
        0X11 设置的全部内容为:设置定时器/计数器的启动停止只由寄存器TRX(X=0或1)控制 >>> TRX为定时器X运行控制位
                               设置定时器/计数器为定时器模式
                               设置定时器0和定时器1为工作方式1,16位定时器/计数器
        *****/
        TH0 = (65536-45872)/256; //装初值,11.0592M晶振,定时50ms,计数个数 N = 45872(在计数时需要预先填装初始计数个数)
        TL0 = (65536-45872)%256; //...
        TH1 = (65536-45872)/256; //...
        TL1 = (65536-45872)%256; //同上
        /*****
        THX、TLX为高八位和低八位寄存器。用来储存计数次数
        X=0或1
        计数个数 N = 中断时间 / 机器周期
        机器周期 = 12 * (1/时钟频率)
        例 ;时钟频率为11.0592MHz
             机器周期 = 12 * (1/110592) = 1.09 us (约)
             计数个数 N = 50 * 1000 / 1.09 = 45872 (约)<需要换算单位 * 1000>        1秒=1000毫秒(ms)
    1秒=1,000,000 微秒(μs)
        1毫秒=1000微秒     
        ******/
        EA = 1; //全局中断允许位 | 打开总中断(相当于中断的总开关,打开之后其他中断发生时才能有效)
        ET0 = 1;//定时器/计数器0中断允许位 | 打开
        ET1 = 1;//定时器/计数器1中断允许位 | 打开
        TR0 = 1;//定时器0运行控制位 | 允许定时器0运行
        TR1 = 1;//定时器1运行控制位 | 允许定时器1运行
        while(1)  //主循环 不断对数码管服务函数扫描
        {
                 tube();//数码管服务函数(不断对数码管进行扫描)
        }
}

2.中断定时相关程序代码

/*****
"software.h"自创的头文件、software.h翻译为:(计算机)软件;

******/
#include "software.h"
uchar num , num1; //定义num , num1的数据类型为无符号字符型类型
num2 = 60;        //初始化此变量的值

void delayms(uint xms)   //简单延时
{
        uint a , b;
        for(a=xms; a>0; a--)
         for(b=110; b>0; b--);
}

void Timer0_Rountine(void) interrupt 1  //中断号 定时器/计数器0中断  1为定时器/计数器0的中断号(重要)
{
        TH0 = (65536-45872)/256;      //方式1需要重装初值
        TL0 = (65536-45872)%256;
        num++;      //mun变量自加1
        if(num == 10)  //判断定时时间是否等于0.5s 为真之后 LED灯的电平状态转换
        {
                num = 0;   //清零,好判断下次计时
                LED =~ LED;//电平状态取反
        }
}

void TimerI_Routine(void) interrupt 3  //中断号 定时器/计数器1中断  1为定时器/计数器0的中断号 (重要)
{
        TH1 = (65536-45872)/256;  //方式1需要重装初值
        TL1 = (65536-45872)%256;
        num1++;   //mun1变量自加1
        if(num1 == 20)   //判断定时时间是否等于1s
        {
                num1 = 0;   //清零,好判断下次计时
                num2--;     //mun2变量自减1  mun2的初始值为60
                if(num2 == 0) //判断是否计时结束
                   num2 = 60; //重新赋值,以便重新计时
        }
        
}


3.数码管LED灯相关程序代码

/*****
"hardware.h"自创的头文件、hardware翻译为:五金器具; 计算机硬件; 武器装备;
“”用于自己创建的头文件、<>反之 例:<reg51.h>

******/
#include "hardware.h"
#include "software.h"  //调用此函数的变量(因此包含此文件)
//共阴数码管段码
uchar code block[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  //定义无符号字符型类型数组来储存段码

void tube()    //数码管扫描函数
{
  uchar i;  //定义i变量
        for(i=0;i<2;i++)
        {
                switch(i)        
                {                                                                                                                 
                   case(0):                         //位选,第一个数码管        
                                LSA=1;
                                LSB=1;
                                LSC=1;
                        P0 = block[num2/10];  //十位数拆分
                                 break;
                        case(1):          //位选,第一个数码管
                                LSA=0;
                                LSB=1;
                                LSC=1;
                            P0 = block[num2%10];  //个位数拆分
                                 break;
                }
//                P0 = block[num%10];
                delayms(5);   //延时一会(视觉残留)
                P0=0x00;      //消影
        }
}

4.相关H文件程序代码

#ifndef __SOFTWARE_H__  
#define __SOFTWARE_H__

#include <hardware.h>  //包含此头文件,以便在此C文件中调用

extern void delayms(uint xms);    // extern(外部的) 声明此函数给外部调用
extern num2;                      //声明此变量给外部函数调用
#endif



#ifndef __HARDWARE_H__
#define __HARDWARE_H__

#include <reg51.h>    //51单片机头文件
//#include <software.h>


//数码管    138译码器
sbit LSA=P2^2;        
sbit LSB=P2^3;        
sbit LSC=P2^4;
//LED灯
sbit LED=P2^0;

typedef unsigned int uint;          // typedef(类型定义) 用来给无符号整型类型数据 unsigned int 定义新名字 uint
typedef unsigned char uchar;  //用来给无符号字符型类型数据 unsigned char 定义新名字 uchar
extern uint;    //声明给外部函数使用
extern uchar;   //声明给外部函数使用
extern void tube(void);   // extern(外部的) 声明此函数给外部调用

#endif



以下是编译的结果:


Rebuild target 'porject'
assembling STARTUP.A51...
compiling main.c...
compiling hardware.c...
compiling software.c...
linking...
Program Size: data=14.0 xdata=0 code=529
creating hex file from ".\Objects\porject"...
".\Objects\porject" - 0 Error(s), 0 Warning(s).
Build Time Elapsed:  00:00:01

提示:模块化编程很重要,如果有不了解的小伙伴推荐大家去看这篇文章写得很好:https://blog.csdn.net/weixin_30764137/article/details/96185151

总结

  首先我也是一个单片机入门的小白,编写文章不易。如果我的文章对大家有所帮助,我感到很开心。其次有很多的不足之处,希望大家多多包涵。另外,如果大家有什么好的意见,欢迎大家留言讨论。一起共同进步!

程序下载地址:
数码管60s倒计时(模块化).rar (335.45 KB, 下载次数: 31)



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:328014 发表于 2021-7-2 15:39 | 只看该作者
好资料很详细,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:903848 发表于 2021-7-2 22:28 | 只看该作者
51hei团团 发表于 2021-7-2 15:39
好资料很详细,51黑有你更精彩!!!

多谢支持!!!
回复

使用道具 举报

地板
ID:58647 发表于 2021-7-6 16:45 | 只看该作者
讲解的详细,学习。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表