首页 > 其他分享 >数码管详解

数码管详解

时间:2024-10-18 14:01:28浏览次数:5  
标签:wela P0 存器 dula 数码管 详解 状态值

数码管详解

摘要

本文详细讲解了数码管的基本电路结构,包括单个和多个数码管的连接,以及如何通过锁存器解决电流问题。重点介绍了数码管显示数字时芯片引脚的状态变化,并展示了动态显示的实现方法,如逐个数字切换和多个数码管同步显示。

数码管介绍

数码管是一种常用的显示器件,由多个发光二极管(LED)组成,能够显示数字和一些字符。

数码管的分类

数码管分为共阴极共阳极两种类型,它们的驱动方式不同共阳数码管将所有LED的阳极接到一起形成公共阳极,而共阴数码管则是将所有LED的阴极接到一起形成公共阴极

数码管的检测

数码管的检测可以通过干电池检测法万用表检测法进行。干电池检测法是使用两节1.5V干电池串联起来,通过限流电阻连接到数码管的公共阴极或阳极,然后依次接触各笔段电极,观察对应笔段是否发光。万用表检测法则是将万用表拨至适当的电阻挡,通过测量正反向电阻来判断数码管是否正常。

驱动数码管

驱动数码管时,可以采用静态驱动动态驱动静态驱动每个数码管的每个段码由单片机的I/O端口直接驱动,而动态驱动则是通过分时轮流控制各个数码管的公共极以快速扫描的方式显示数字,这样可以节省I/O端口并降低功耗

数码管的应用

数码管的应用非常广泛,包括电子计时器、仪表仪器、电子钟表、数码显示屏和数字仪表盘等 。尽管LCD和OLED屏幕在某些方面取代了数码管,但数码管因其成本低廉、适应恶劣环境能力强等优势,在许多领域仍然是不可替代的。

在实际应用中,可以使用锁存器如74HC573来驱动数码管,这样可以减少I/O端口的使用,并提高显示的稳定性。74HC573锁存器是一种对脉冲电平敏感的存储单元电路,它可以在特定输入脉冲电平作用下改变状态,实现数据的锁存。

总的来说,数码管因其简单、成本低廉和可靠性高而在各种显示应用中得到广泛应用。无论是在简单的家用电器还是在复杂的工业设备中,数码管都能够提供清晰、直观的数字和字符显示。

数码管电路

单个数码管

一个数码管是由a、b、c、d、e、f、g、dp八个二极管组成,八个LED一端接在一起,另一端引脚引出来。二极管如果阳极连在一起,就是共阳极数码管阴极连在一起,就是共阴极数码管

如上图,是一个共阴极数码管要使数码管显示不同的数字只需点亮对应LED即可。如:数码管显示“0”,则a、b、c、d、e、f六个LED亮,g、dp这两个LED灭,即可显示“0”。

多个数码管

上图所示的六个数码管,在使用时,需要程序选定使用哪几个数码管,这就是“位选”,选定数码管后再对选定的数码管进行操作,其操作与单个数码管的操作一致(接下来还会进一步详解),这就是“段选”。

数码管与芯片的连接

为什么要使用锁存器

二极管正常工作时需要5mA以上的电流,若数码管引脚和芯片引脚直接相连,芯片的I/O口无法输出这么大的电流。对于共阴极的数码管,可以在阳极处接上拉电阻。对于共阳极的数码管,可以在阴极处接下拉电阻,但是也使得“位选”需做另外的处理。

引入锁存器,利用其输出电流大的特点,有效的解决了LED工作电流问题,而且还可以利用锁存器进行“位选”、“段选”。

锁存器的电路连接

上图所示,连接俩块锁存器,U1控制段选,U2控制位选。

根据电路图,OE始终接地,所以锁存器工作状态只有前三种,当LE软件置1时,锁存器的输入端D与输出端Q同高电平,同低电平,当LE软件置0时,锁存器输出为Q0。

由电路图可得,电路连接为:

单片机的芯片引脚P00—>P07分别接U1锁存器的D0——>D7,单片机的芯片引脚P00—>P07分别接U2锁存器的D0——>D7,也就是说U1、U2俩锁存器都与P0相连,所以在数码管工作状态下,俩个锁存器不能同时处于打开状态,即俩个锁存器的LE不能同时为高电平。锁存器U1的输出接数码管的LED阳极,锁存器U2的输出接数码管的WE,控制“数码管选择”。

锁存器U2控制位选,U2打开时,U1关闭,此时U2的输入和输出同高、同低电平。如下图,若使用数码管1,则只需D0置0,其他引脚置1,即芯片P00输出为0,P01——>P07输出为1,即P0寄存器的状态值为0xfe(上面低位,从下往上读)

锁存器U1控制段选,如刚刚位选了数码管1,则接下来段选是对数码管1的操作。此时关闭U2,打开U1,即U2的LE软件置0,U1的LE软件置1,而U2的LE与芯片的P27相连,U1的LE与芯片的P26相连(下图所示),所以只需使芯片的P27输出低电平来关闭U2锁存器,P26输出高电平来打开U1锁存器。

打开U1锁存器后,使数码管显示某个数字,我们在第一节中总结过了,比如显示一个数字“6”,需要a、c、d、e、f、g六个LED亮,所以锁存器输出01111101(共阴极数码管。输出1时点亮),即P0寄存器输出01111101,P0寄存器的状态值为0x7d。

第一个数码管显示数字“6”的程序如下:

#include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;
void main()
{
	wela=1;
	P0=0xfe;//位选第一个数码管
	wela=0;

	dula=1;
	P0=0x7d;
	dula=0;
	while(1);
}

分析上面程序:

首先对连接U1、U2锁存器LE的芯片引脚P26与P27进行位操作,重命名为“dula”与“wela”,表示“段选”和“位选”。主函数里,先打开位选:wela=1,选择第一个数码管,则U2锁存器输入和输出均为11111110(从下往上),P0的输出也为11111110,即0xfe,位选结束后关闭位选:wela=0。

接下来打开段选:dula=1,对第一个数码管操作,显示数字“6”,U1锁存器输入输出均为01111101,即P0输出为01111101,即P0的状态值为0x7d。最后关闭段选。

注:
正因为锁存器U1与U2同时接在芯片的P0引脚上,所以俩个锁存器不能同时打开,否则芯片引脚P0输出的状态值会在U1和U2上同时发生响应,造成紊乱。

数码管显示数字时芯片引脚的状态值

显示数字“0”,abcdef亮,状态值00111111——>0x3f
显示数字“1”,bc亮,状态值00000110——>0x06
显示数字“2”,abdeg亮,状态值01011011——>0x5b
显示数字“3”,abcdg亮,状态值01001111——>0x4f
显示数字“4”,bcfg亮,状态值01100110——>0x66
显示数字“5”,acdfg亮,状态值01101101——>0x6d
显示数字“6”,acdefg亮,状态值01111101——>0x7d
显示数字“7”,abc亮,状态值00000111——>0x07
显示数字“8”,abcdefg亮,状态值01111111——>0x7f
显示数字“9”,abcdfg亮,状态值01101111——>0x6f
显示字母“A”,abcefg亮,状态值01110111——>0x77
显示字母“B”,cdefg亮,状态值01111100——>0x7c
显示字母“C”,adef亮,状态值00111001——>0x39
显示字母“D”,bcdeg亮,状态值01011110——>0x5e
显示字母“E”,adefg亮,状态值01111001——>0x79
显示字母“F”,aefg亮,状态值01110001——>0x71

在编写程序时将上述状态值放入数组中,通过数组来实现数码管的动态显示

放在如下数组中:

#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
}

在table数组名前加了code,表示编码的意思,单片机程序把不需要更改的东西通过code关键字定义为编码,单片机执行程序时,table只占用程序存储空间,可以理解为占用flash,而不占用RAM。

数码管实现动态显示

一个数码管从0到F动态显示

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar num;
sbit dula=P2^6;
sbit wela=P2^7;
void delay_ms(uint );
void main()
{
	wela=1;
	P0=0xfe;
	wela=0;

	while(1)
	{	
		for(num=0;num<16;num++)
		{
			dula=1;
			P0=table[num];
			dula=0;
			delay_ms(500);	
		}
	}
}
void delay_ms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=110;j>0;j--);
}

此时第一个数码管从0变化到F,之后停止不动。

若使数码管从0到F反复变化,只需在while()语句里添加如下代码:

	if(num==16)
		num=0;

完整程序:

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar num;
sbit dula=P2^6;
sbit wela=P2^7;
void delay_ms(uint );
void main()
{
	wela=1;
	P0=0xfe;
	wela=0;

	while(1)
	{	
		for(num=0;num<16;num++)
		{
			dula=1;
			P0=table[num];
			dula=0;
			delay_ms(500);	
		}
		
     //------------新加
		if(num==16)
		num=0;	
	//----------------
	}
}
void delay_ms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=110;j>0;j--);
}

多个数码管从0到F动态显示

与之前的一个数码管比较,多个数码管的动态显示只需改变位选时P0的输出,如六个数码管同时显示,则P0输出11000000,即0xc0

位选代码:

	wela=1;
	P0=0xc0;
	wela=0;

完整代码:

//六个数码管从0到F循环动态显示
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar num;
sbit dula=P2^6;
sbit wela=P2^7;
void delay_ms(uint );
void main()
{
	wela=1;
	P0=0xc0;
	wela=0;

	while(1)
	{	
		for(num=0;num<16;num++)
		{
			dula=1;
			P0=table[num];
			dula=0;
			delay_ms(500);	
		}
		if(num==16)
		num=0;	
	}
}
void delay_ms(uint ms)
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=110;j>0;j--);
}

一个经典例子

题:
六个数码管,第一个数码管显示数字“1”,间隔1秒后再在第二个数码管上显示数字“2”,间隔1s后在第三个数码管上显示数字“3”,以此类推…在第六个数码管上显示数字“6”

分析:
六个数码管轮流显示,所以位选时依次选择数码管1、2…6,每次位选后,再段选输出需要显示的数字。

第一个数码管位选:

	wela=1;
	P0=0xfe;//第一个数码管
	wela=0;

第一个数码管段选输出数字“1”:

	dula=1;
	P0=table[1];
	dula=0;
	delay_ms(1000);

位选时P0的输出之前已经总结过了,再回忆一下,如下图,从左到右分别为数码管1、2、3、4…从下往上读,得到8位二进制码,变为16进制即可。

完整程序:

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar num;
sbit dula=P2^6;
sbit wela=P2^7;
void delay_ms(uint );
void main()
{
	while(1)
	{
		wela=1;
		P0=0xfe;//第一个数码管
		wela=0;
	
		dula=1;
		P0=table[1];
		dula=0;
		delay_ms(1000);
	
		wela=1;
		P0=0xfd;//第二个数码管
		wela=0;
	
		dula=1;
		P0=table[2];
		dula=0;
		delay_ms(1000);
	
		wela=1;
		P0=0xfb;//第三个数码管
		wela=0;
	
		dula=1;
		P0=table[3];
		dula=0;
		delay_ms(1000);
	
		wela=1;
		P0=0xf7;//第四个数码管
		wela=0;
	
		dula=1;
		P0=table[4];
		dula=0;
		delay_ms(1000);
	
		wela=1;
		P0=0xef;//第五个数码管
		wela=0;
		
		dula=1;
		P0=table[5];
		dula=0;
		delay_ms(1000);
	
		wela=1;
		P0=0xdf;//第六个数码管
		wela=0;
	
		dula=1;
		P0=table[6];
		dula=0;
		delay_ms(1000);
	}
}

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

标签:wela,P0,存器,dula,数码管,详解,状态值
From: https://www.cnblogs.com/bujidao1128/p/18457216

相关文章

  • 解锁二叉树的魅力:链式实现详解
    前言二叉树的简介及顺序实现引言在数据结构的浩瀚星空中,二叉树如同一颗璀璨的明珠,其优雅的结构和强大的功能使其成为计算机科学中不可或缺的工具。从数据库索引到编译器的语法树,二叉树以其独特的方式支撑着许多核心算法与数据处理。本文将深入探讨如何使用C语言实现二叉树的......
  • 支持向量机SVM原理详解
    SVM原理详解1、超平面2、SVM原理1.问题定义2.分类决策得到约束条件3.最大化间隔4.优化目标3、凸优化问题1.原始优化问题优化目标约束条件2.拉格朗日乘子法3.拉格朗日函数分析4.求解对w......
  • 超全!一文详解大型语言模型的11种微调方法
    导读:大型预训练模型是一种在大规模语料库上预先训练的深度学习模型,它们可以通过在大量无标注数据上进行训练来学习通用语言表示,并在各种下游任务中进行微调和迁移。随着模型参数规模的扩大,微调和推理阶段的资源消耗也在增加。针对这一挑战,可以通过优化模型结构和训练策略来......
  • RS485通信详解
    1.RS485介绍RS485是串行通信标准,使用差分信号传输,抗干扰能力强,常用于工控领域。RS485具有强大的组网功能,在串口基础协议之上还制定MODBUS协议。串口基础协议:仅指封装了基本数据包格式的协议(基于数据位)MODBUS协议:使用基本数据包组合成通讯帧格式的高层应用协议(基于数据包或......
  • 鸿蒙ArkTS中的资源管理详解
    在鸿蒙应用开发中,资源管理是一个非常重要的话题。ArkTS作为鸿蒙原生开发语言,提供了强大的资源管理功能。本文将深入探讨ArkTS中的资源管理,特别是$r语法的使用注意事项,以及其他实用的资源管理技巧。1.$r语法简介在ArkTS中,$r是一个用于引用资源的特殊语法。它允许开发者......
  • Linux驱动开发 platform设备注册详解
    常用的与平台设备注册相关的函数及其作用:1.platform_device_register()功能:用于注册平台设备到内核设备模型中。注册后,设备与相应的驱动程序绑定,驱动的probe函数被调用以进行初始化。函数原型:intplatform_device_register(structplatform_device*pdev);参数:pde......
  • 预科02》:Markdown语法详解
    Markdown学习标题三级标题四级标题标题语法:#空格标题名回车(几极标题就用几个#号)字体hello,word!hello,word!hello,word!hello,word!(前面后面加*号鼠标点一下可以看见)引用选择狂神说学java走向人生巅峰!(语法:>空格描述)分割线语法---或者***......
  • Java之Lambda表达式详解
    一、Lambda表达式的概念与特点Lambda表达式是Java8引入的一个重要特性,它提供了一种简洁、优雅的方式来处理集合、过滤、映射等操作。Lambda表达式可以看做是匿名函数,它允许开发者以更简洁的方式声明匿名函数。Lambda表达式的基本语法由箭头指示符“->”表示,它将参数与函数......
  • 【数据结构】之链表详解
    链表是一种常用的数据结构,它是一种线性数据结构,但与数组不同,它并非连续存储数据,而是通过指针将数据节点连接起来。每个节点都包含数据域和指向下一个节点的指针域。这种结构赋予链表独特的优势和局限性,使其在某些场景下优于数组,在另一些场景下则相对逊色。本文将深入探讨链表,包......
  • 【数据结构】之数组详解
    数组是数据结构中最基础的概念之一,它在编程中被广泛应用。理解数组的工作原理、操作方式以及底层实现,对于我们构建更复杂的数据结构和算法至关重要。本文将从多个角度深入剖析数组,并以Java语言示例进行讲解,帮助你建立对数组的深刻理解。一、什么是数组?数组是一种线性数据结构......