蓝桥杯51单片机之数码管从点亮到动态时钟的实现【单片机开发初学者必掌握】

2023-11-11

一、点亮数码管

首先看一下案例源码:

#include <reg52.h>

sbit dula= P2^6;  //声明U1锁存器的锁存端
sbit wela= P2^7;  //声明U2锁存器的锁存端

int main()
{
	wela= 1;	//打开U2锁存端(控制灯亮的锁存器)
	P0= 0xfc;  //送入位选信号(亮灯的位置,十六进制从右到左,显示的是从左到右)
	wela= 0;

	dula= 1;	//打开U1锁存端(控制灯显示的锁存器)
	P0= 0x07;	//送入段选信号(灯亮的数字,十六进制转二进制依次对应hgfe dcba段,h段为0其余为1则全亮)
	dula= 0;	//关闭U1锁存端
	while(1);  //程序停止
}

(1)全局变量区域的sbit表示声明锁存器的锁存端,简单来说就是需要用这两个锁存端来控制段选和位选信号的保持。段选用来控制数码管上的数字,位选用来控制数码管上的位置,因此这两个索存端就是用来控制在数码管的哪个(或哪几个)位置上显示什么数。
(2)主函数中就用上了在全局声明的锁存端,wela则是控制位选(哪个位置),为1时则打开,为0时则关闭,并保持设定好了的位选。dula段选控制同理。
(3)不管是段选还是位选,都是用P0来传入信号。

二、八位数码管同时从0到F

首先提供一下从0到F的段选信号:

//0到F段选信号
uchar code table[]={
	0x3f, 0x06, 0x5b, 0x4f,
	0x66, 0x6d, 0x7d, 0x07,
	0x7f, 0x6f, 0x77, 0x7c,
	0x39, 0x5e, 0x79, 0x71	
};

(1)我们的本次要显示的是所有的数码管,这里是八位数码管,wela= 1; P0= 0x00; //位选信号,全亮 wela= 0;
(2)在点亮全部数码管的基础上,将这一系列的段选信号依次遍历,传入到P0中,再加上延迟函数,就能够实现动态变化了。

/*让8个数码管同时点亮,
依次显示0到F,时间间隔为0.5秒*/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

//锁存器与全局变量
sbit dula= P2^6;
sbit wela= P2^7;
uchar num;
//0到F段选信号
uchar code table[]={
	0x3f, 0x06, 0x5b, 0x4f,
	0x66, 0x6d, 0x7d, 0x07,
	0x7f, 0x6f, 0x77, 0x7c,
	0x39, 0x5e, 0x79, 0x71	
};
void delay(uint);  //函数声明

void main()
{
	wela= 1;
	P0= 0x00;  //位选信号,全亮
	wela= 0;
	while(1)
	{
		for(num=0; num<16; num++)	//16个数循环显示
		{
			dula= 1;
			P0= table[num];	  //段选信号,依次取数组中的值
			dula= 0;
			delay(500);	  //延时0.5秒
		}
	}
}

void delay(uint x)  //延时x毫秒的函数
{
	uint i,j;
	for(i=x; i>0; i--)
	{
		for(j=110; j>0; j--) ;
	}
}

三、显示学号(指定数字)

稍微想一下就明白了,只要我们将依次将各个学号数字所对应的段选信号通过P0传入,位选信号我们都不用变,就可以在数码管上显示所对应的数字了。

/*显示学号*/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
void delayms(uint x);  //延时函数声明

//U1和U2锁存器的锁存端
sbit dula = P2^6;
sbit wela = P2^7;
//学号的段选信号
uchar code table[]={
0x5b, 0x3f, 0x06, 0x6f,
0x66, 0x5b, 0x7d, 0x3f
};

//存放位选信号
uchar D[]= {
0xfe, 0xfd, 0xfb, 0xf7,
0xef, 0xdf, 0xbf, 0x7f
};

void main()
{
	uint i;
	while(1)
	{
		for(i=0; i<sizeof(table); i++)
		{
			dula= 1;
			P0= table[i];  //送入段选信号
			dula= 0;
			P0= 0xff;  //送位选数据前关闭数码管的显示,防止位选锁存器混乱
			wela= 1;
			P0= D[i];  //送入位选信号,只亮一位,但由于视觉残留效应,会觉得是同时亮着的
			wela= 0;
			delayms(2);  //(必须有延时)延时2毫秒,对于人眼的视觉暂留根本看出来在跳 
		}
		
	}
}

//延时x毫秒的函数
void delayms(uint x)  
{
	uint i,j;
	for(i=x; i>0; i--)
	{
		for(j=110; j>0; j--) ;
	}
}

四、中断机制的引入

首先理解一下中断是什么,举个例子:我本来在上课,突然有电话打来,我去接了个电话,然后继续回来上课。在这个例子中,我去接电话就是在执行一个中断请求,执行完该中断之后,我会继续回到课堂上,继续断点位置的讲课,而不是从头开始讲课,这也就是中断的好处了。

1、中断允许控制位
EA:中断允许总开关控制位。(1:所有中断请求被允许;0:所有中断请求被屏蔽)

  • ES:串行口中断允许控制位。(1:允许串口中断;0:禁止串口中断)
  • ET1:定时器/计数器T1的溢出中断允许控制位。(1:允许T1溢出中断;0:禁止T1溢出中断)
  • EX1:外部中断1中断允许位。(1:允许外部中断1中断;0:禁止外部中断1中断)
  • ET0:定时器/计数器T0的溢出中断允许控制位。(1:允许T1溢出中断;0:禁止T1溢出中断)
  • EX0:外部中断0中断允许位。(1:允许外部中断1中断;0:禁止外部中断1中断)

注意:除了EA总中断控制,以上中断类型中EX0即外部中断0的等级是最高的,就是0;从下往上依次递减,ES串行口中断等级为4,即最低的。

2、中断请求方式的选择
01

  • IT0(TCON.0),外部中断0触发方式控制位。
    当IT0=0时,为低电平触发方式。
    当IT0=1时,为边沿触发方式(下降沿有效)。
  • IE0(TCON.1),外部中断0中断请求标志位。
  • IT1(TCON.2),外部中断1触发方式控制位。
  • IE1(TCON.3),外部中断1中断请求标志位。
  • TF0(TCON.5),定时/计数器T0溢出中断请求标志位。
  • TF1(TCON.7),定时/计数器T1溢出中断请求标志位。

3、中断服务的必要操作
(1)中断初始化

 EA=1//打开总中断开关
EX0=1//开外部中断0
IT0=0/1//设置外部中断的触发方式
//便是以上中断方式TOCN的选择

(2)写中断服务函数

void int0 () interrupt 0  //外部中断0,即最高级别的中断,所以为0
 
{
  //do anything that you want
}

3、外部中断0简单案例

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
void delayms(uint z);
void display();

//锁存器
sbit wela= P2^7;  //位选
sbit dula= P2^6;  //段选
//0到9的段选信号
uchar code table[]={
0x3F, 0x06, 0x5B, 0x4F, 0x66,
0x6D, 0x7D, 0x07, 0x7F, 0x6F
};

void main()
{
	//主函数变量
	uint i;

	//初始化中断方式
	IT0= 0;  //低电平触发中断0
	//中断基础设置
	EA= 1;  //开总中断
	EX0= 1;  //允许外部中断0
	PX0= 1;  //外部中断0为高优先级

	
	while(1)
	{
		for(i=0; i<=6; i++)
		{
			wela= 1;
			P0= 0xbF;
			wela= 0;
			dula= 1;
			P0= table[i];
			dula= 0;
			delayms(10000);
		}	
	}
}

void display() interrupt 0
{
	uint i;
	uchar temp= P0;
	for(i=0; i<10; i++)
	{
		wela= 1;
		P0= 0x7F;
		wela= 0;
		dula= 1;
		P0= table[i];
		dula= 0;
		delayms(10000);
	}
	P0= temp;
}

void delayms(uint z)
{
	uint i, j;
   	for(i=z; i>0; i--)
		for(j=0; j<110; j--)  ;
}

五、利用中断实现动态时钟

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

void time_init();
void delay(uint x);
void display(uchar addr, uchar sign);
void write_addr(uchar addr);
void write_data(uint sign);
void timer();
void dis_gang();

sbit dula = P2^6;
sbit wela = P2^7;
code uchar table[]={0x3F, 0x06, 0x5B, 0x4F, 0x66,
					0x6D, 0x7D, 0x07, 0x7F, 0x6F}; //0-9段选
uint sign[6]={0, 0, 0, 0, 0, 0};  //用来显示数据的位置,不包括横杠

uint second=0;
uint minute=0;
uint hour=0;
uint n=0;  //用来计数判断的中间变量

void time_init()
{
	TMOD = 0x02;
	ET0 = 1;	  //可用定时器0
	TR0 = 1;	  //运行定时器0
	TH0 = 156;
	TL0 = 156;
	EA = 1;
}

void display(uchar addr, uint j)	 //传入段选下标和位选信号
{
	//送段选数据,点亮数码管 
	dula= 1;
	P0= table[j];
	dula= 0;
	P0= 0xff;  //关闭数码管,防止打开位选锁存器时原来的段选数据通过位选造成混乱 
	//送位选数据 
	wela= 1; 
	P0= addr;
	wela= 0;
	delay(1);	  //等待会触发中断,执行后一位的计数

	dis_gang();	
}

void dis_gang()	  //在数字交界显示横杠
{
	wela = 1;
	P0 = 0xDB;	//第3位和第6位
	wela = 0;
	dula = 1;
	P0 = 0x40;  //一个杠
	dula = 0;
	delay(1);	
}	

void delay(uint x)
{
	uint i, j;
	for(i=x; i>0; i--)
		for(j=110; j>0; j--) ;
}

void main()
{
	time_init();
	while(1)
	{
		display(0x7F, sign[0]);
		display(0xBF, sign[1]);
		display(0xEF, sign[2]);
		display(0xF7, sign[3]);
		display(0xFD, sign[4]);
		display(0xFE, sign[5]);
	}
}

void timer() interrupt 1
{
    n++;
    if(n==10000)
    {
		n=0;
   		second++;
		if(second==60)
		{
			second=0;
			minute++;
			if(minute==60)
			{
				minute=0;
				hour++;
				if(hour==24)
				{
					hour=0;
				}
			}
		}
		sign[0]= second%10;  //获得秒个位的下标
		sign[1]= second/10;  //获得秒十位
		sign[2]= minute%10;
		sign[3]= minute/10;
		sign[4]= hour%10;
		sign[5]= hour/10;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

蓝桥杯51单片机之数码管从点亮到动态时钟的实现【单片机开发初学者必掌握】 的相关文章

随机推荐

  • ARM体系结构简介 —— 迅为

    目录 单片机和ARM处理器 内存管理单元 MMU 高速缓冲存储器 CACHE 指令集 ARM的指令系统 ARM处理器工作模式 ARM处理器的内部寄存器 ARM处理器的异常 ARM中断向量 ARM架构的发展 单片机和ARM处理器 内存管理单元
  • 10. adb截图命令

    adb截图命令 adb shell screencap 输入以下命令进行截屏 adb shell screencap sdcard screen png 将截图上传到PC的F盘 已创建目录F screenshot adb pull sdca
  • docker 笔记1

    目录 1 为什么有docker 2 Docker 的核心概念 3 容器与虚拟机比较 3 1传统的虚拟化技术 3 2容器技术 3 3Docker容器的有什么作用 3 4应用案例 4 docker 安装下载 4 1CentOS Docker 安
  • 排序(7)归并排序

    6 归并排序 将两个有序表合并为一个有序表
  • (万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)

    文章前言 一个普通的ACM算法竞赛选手 以前只知道写题 却没有自己弄一个算法流程 思考许久 决定整理一下算法 先从入门算法入手 如有不足 望指出 持续更新 直到完善 现在已经破万了 最后字数粗略估计将会达到6万字 写完有时间的话会写进阶版的
  • Angularjs的http请求

    1 使用 http发起请求 scope exportWord function item var config headers Content Type application json http post commonFileUrl pa
  • html怎么调用数据库数据类型,引用数据类型是什么?

    引用数据类型是指由类型的实际值引用 类似于指针 表示的数据类型 如果为某个变量分配一个引用类型 则该变量将引用 或 指向 原始值 不创建任何副本 引用类型包括类 接口 委托和装箱值类型 引用数据类型的概念 引用 reference 是c 的
  • 2020美赛D题解题思路方法:团队合作策略

    随着社会之间的联系越来越紧密 它们面临的一系列挑战也越来越复杂 我们依靠具有不同专业知识和不同观点的跨学科团队来解决许多最具挑战性的问题 在过去50多年里 我们对团队成功的概念性理解有了显著的进步 使得更好的科学 创新或物理团队能够解决这些
  • MobaXterm_Personal_12.2软件连接开发板

    MobaXterm Personal 12 2软件连接开发板会出现乱码 有以下几个原因 1 波特率没设置对 2 编码格式不对 要选GBK 我这边板子对应波特率是115200 流控也要关掉
  • OpenMMLab AI实战营第二天笔记

    图像分类与基础视觉模型 卷积神经网络 AlexNet 2012 第一个成功实现大规模图像的模型 在 ImagNet 数据集上达到 85 的 top 5 的准确率 5 个卷积层 3 个全连接层 共有 60M 个可学习参数 使用 ReLU 激活
  • linux环境部署jmeter并执行测试

    下载jmeter和jdk jmeter官网和java jdk官网下载压缩包文件 jmeter下载地址 点此下载 jmeter Apache JMeter Download Apache JMeter java jdk下载地址 点此下载 jd
  • C# HTML转图片

    C HTML转图片 一 WebBrowser 二 实例 1 HTML文件 2 CS代码 三 总结 一 WebBrowser WebBrowser常用来做应用内嵌的WebUI 使用时需要进入System Windows Forms程序集 二
  • Gitee Config服务读取加载远程信息

    Config服务读取加载远程信息 课程回顾 1 微服务调用常见现象 客户端会多次请求不同的微服务 增加了客户端的复杂性 存在跨域请求 在一定场景下处理相对复杂 认证复杂 每个服务都需要独立认证 难以重构 随着项目的迭代 可能需要重新划分微服
  • 【SpringMVC】JSON数据传输与异常处理的使用

    文章目录 一 Jackson 1 1 Jackson是什么 1 2 常用注解 1 3 实例 1 3 1导入依赖 1 3 2 配置spring mvc xml 1 3 3 JsonController java 二 Spring MVC异常处
  • 程序猿专属的国庆中秋放假通知!

    无bug 不用加班 系统上线一切正常 批准放假 程序猿祝大家 国庆中秋快乐
  • ibatis.binding.BindingException: Invalid bound statement (not found): com.suntang.storage.mapper.Per

    今天新来的小弟弟调试代码时发现控制台报错了 自己调试了半天也没找到原因 该排查的方案也都排查了 就是解决不了 无奈找到了我 我也照着网上的方案排查了一遍 确实不行 然后就自己分析了一下 这个问题已经两个人问过我了 还是在此记录一下吧 控制台
  • 单目视觉里程记代码

    在Github上发现了一个简单的单目vo 有接近500星 链接如下 https github com avisingh599 mono vo 这个单目里程计主要依靠opencv实现 提取fast角点并进行光流跟踪 然后求取本质矩阵并恢复两帧
  • 计算机基础知识(基础入门小白专属)八

    作者 小刘在这里 每天分享云计算网络运维课堂笔记 疫情之下 你我素未谋面 但你一定要平平安安 一 起努力 共赴美好人生 夕阳下 是最美的 绽放 愿所有的美好 再疫情结束后如约而至 目录 Linux 系统基本操作 实例 安装web 服务器 目
  • 【翻译】我们能从英国教育考试院的算法失败中学到什么?

    如果你想找一个表面上聪明的人是如何不小心把别人的生活搞得一团糟的例子 那就看看去年英国公开考试的情况吧 简而言之 政府认识到科维德 19的威胁 取消了英国学生的公开考试 在寻求另一种评分方法时 政府及其教育监管机构可以说是由于无知或选择而违
  • 蓝桥杯51单片机之数码管从点亮到动态时钟的实现【单片机开发初学者必掌握】

    文章目录 一 点亮数码管 二 八位数码管同时从0到F 三 显示学号 指定数字 四 中断机制的引入 五 利用中断实现动态时钟 一 点亮数码管 首先看一下案例源码 include