【1】显示原理

        LED数码管是常见的显示器件。LED数码管为“8”字型的,共计8段(包括小数点段在内)或者7段(不包括小数点段),每一段对应一个发光二极管,有共阴极和共阳极两种。如下图所示。

        共阴极:数码管的阴极连接在一起,通常此公共阴极接地。当某个发光二极管的阳极接高电平时,该发光二极管被点亮,相应的段被显示。 

        共阳极:数码管的阳极连接在一起,公共阳极接到+5V上。当某个发光二极管的阴极接低电平时,该发光二极管被点亮,相应的段被显示。

        编写程序时,共阴极1亮0灭,共阳极0亮1灭。 

        数码管的外形与各发光二极管对应的引脚,如下图所示。

        在单片机开发的过程中,把数码管的某些段点亮,就能让其显示不同的字符。因此,我们通过编写程序,以“a”段作为最低位,并且按照“dp g f e d c b a”的顺序,为每个数码管提供总长为1字节(8位)的二进制代码,即段码。如果要在数码管上显示某一字符,只需将该字符的段码加到各段上即可。

        当然,为了增加程序的可读性,避免冗余,通常使用2位十六进制数来表示数码管1字节的段码。例如,当共阴极数码管需要表示数字“0”时,段码“dp g f e d c b a”应该为“0011 1111”,即“0x3f”;当共阳极数码管需要表示数字“0”时,段码“dp g f e d c b a”应该为“1100 0000”,即“0xc0”。其他情况LED数码管的段码,如下表所示。

8位LED数码管的段码
显示字符

共阴极字型码

(二进制)

共阴极字型码

(十六进制)

共阳极字型码

(二进制)

共阳极字型码

(十六进制)

0 0011 1111 0x3f 1100 0000 0xc0
1 0000 0110 0x06 1111 1001 0xf9
2 0101 1011 0x5b 1010 0100 0xa4
3 0100 1111 0x4f 1011 0000 0xb0
4 0110 0110 0x66 1001 1001 0x99
5 0110 1101 0x6d 1001 0010 0x92
6 0111 1101 0x7d 1000 0010 0x82
7 0000 0111 0x07 1111 1000 0xf8
8 0111 1111 0x7f 1000 0000 0x80
9 0110 1111 0x6f 1001 0000 0x90
A 0111 0111 0x77 1000 1000 0x88
b 0111 1100 0x7c 1000 0011 0x83
C 0011 1001 0x39 1100 0110 0xc6
d 0101 1110 0x5e 1010 0001 0xa1
E 0111 1001 0x79 1000 0110 0x86
F 0111 0001 0x71 1000 1110 0x8e
“灭” 0000 0000 0x00 1111 1111 0xff
…… …… …… …… ……

        在编程过程中,我们通常使用数组来存储和调用所需的数码管段码,并且将该数组定义为code类型,把数据存储在程序存储器。

        代码示例:

uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//共阴极数码管0-9
uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//共阳极数码管0-9

【2】静态显示

        静态显示是指无论多少位LED数码管,都同时处于显示状态。

        优点:显示无闪烁,亮度较高,软件控制比较容易。

        缺点:占用I/O口线较多,硬件资源利用率较低。

        项目1

        题目:用单片机控制一个8段LED数码管,先循环显示单个偶数:0、2、4、6、8,再显示单个奇数:1、3、5、7、9,如此反复循环显示。

        原理图

项目1所需器件列表
关键字 元件名称 型号 数量(个)
AT89C51 单片机 AT89C51 1
CRYSTAL 晶体振荡器 12MHZ 1
7SEG-COM-ANODE 共阳极7段数码管 红色 1
CAP 电容 30pF 2
CAP-ELEC 电解电容 10uF 1
RES 电阻 1kΩ 1
RES 电阻 10kΩ 1
RES 电阻 560Ω 7
BUTTON 复位按键 1

代码

#include <reg52.h>

#define uchar unsigned char		//宏定义无符号字符型变量方便书写
#define uint unsigned int		//宏定义无符号整型变量方便书写
#define out P0		//宏定义P0口为out
uchar code seg[]={0xc0,0xa4,0x99,0x82,0x80,0xf9,0xb0,0x92,0xf8,0x90};		//共阳极段码表

void delay(uint n)		//延时函数ms
{
	uchar i;
	uint j;
	for(j=0;j<n;j++)
	for(i=0;i<123;i++);
}

void main(void)
{
	uchar i;
	while(1)
	{
		out=seg[i];
		delay(2000);
		i++;
		if(i>9)i=0;
	}
}

 实验现象

数码管项目1——静态显示实验现象

        项目2

        题目:单片机控制2位数码管,静态显示2个数字“2”和“7”。

        原理图

项目2所需器件列表
关键字 元件名称 型号 数量(个)
AT89C51 单片机 AT89C51 1
CRYSTAL 晶体振荡器 12MHZ 1
7SEG-COM-ANODE 共阳极7段数码管 红色 2
CAP 电容 30pF 2
CAP-ELEC 电解电容 10uF 1
RES 电阻 1kΩ 1
RES 电阻 10kΩ 1
RES 电阻 470Ω 14
BUTTON 复位按键 1

代码

#include <reg52.h>

#define uchar unsigned char		//宏定义无符号字符型变量方便书写
#define uint unsigned int		//宏定义无符号整型变量方便书写

uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};		//共阳极段码表

void main(void)
{
	P0=seg[2];	//将数字“2”的段码送到P0口
	P1=seg[7];	//将数字“7”的段码送到P1口
	while(1);		//无限循环
	;						//因为后续未对数码管进行熄灭的操作,数码管一直处于点亮的状态,所以while循环可有可无
}

实验现象

【3】动态显示

        动态显示是将所有LED数码管显示器的段码线的相应段都并联在一起,由一个8位I/O端口控制,而各显示位的公共端分别由另外单独的I/O端口线控制。

        其实质是,每一个时刻选中一位显示,其余各位均不显示,每隔一定的时间逐位点亮各数码管,利用数码管的余晖和人眼的“视觉暂留”作用,造成“多位同时亮”的假象,达到4位或者多位同时显示的效果。

        优点:占用I/O口线较少,硬件利用率较高。

        缺点:占用单片机时间较多。显示可能有闪烁,亮度较低,软件编程比较复杂。

        项目3

        题目:单片机控制8只数码管,分别滚动显示单个数字1~8。

        原理图

        原理图绘制技巧:蓝色粗线是总线。

        1、右键→“放置”→“总线”(或者单击左侧主工具栏“总线模式”的图标)。

        2、总线不能出现90°角的转折,可以在需要转折处先单击鼠标“左键”→按住“Ctrl”寻找合适的角度→延长斜线到合适位置后单击鼠标“左键”→继续绘制直线即可。

        3、总线分支需要画成与总线成45°角的相互平行的一组斜线,从外设或者单片机需要与总线相连的引脚出发,鼠标“左键”单击开始绘制,转折的处理与总线相同,也是借助“Ctrl”。

        4、在外设与单片机IO口相对应的总线分支上,需要添加“网络标号”,保障其正常的电气连接。

        在英文模式下,点击键盘上的字母“A”→将字符串(S)更改为“NET=P#”或者“NET=P0#”或者“NET=#”(前面“NET=”不变,如果标号是P0~P7,则为“NET=P#”;如果标号是P00~P07,则为“NET=P0#”;如果标号是18,则为“NET=#”)→根据实际需要调节“计数初值(C)”,即上述“P#”、“P0#”和“#”中“#”的起始值→在合适的位置放置网络标号即可。

项目3所需器件列表
关键字 元件名称 型号 数量(个)
AT89C51 单片机 AT89C51 1
CRYSTAL 晶体振荡器 12MHZ 1
7SEG-MPX8-CA-BLUE 8位8段共阳极数码管 蓝色 1
CAP 电容 30pF 2
CAP-ELEC 电解电容 10uF 1
RES 电阻 1kΩ 1
RES 电阻 10kΩ 1
RX8 双向排阻 220Ω 1
2N2222A NPN型三极管 8
BUTTON 复位按键 1

代码

#include <reg52.h>
#include <intrins.h>		//包含循环移位函数的头文件

#define uchar unsigned char		//宏定义无符号字符型变量方便书写
#define uint unsigned int		//宏定义无符号整型变量方便书写

uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};		//共阳极段码表

void delay(uint n)		//延时函数ms
{
	uchar i;
	uint j;
	for(j=0;j<n;j++)
	for(i=0;i<123;i++);
}

void main(void)
{
	uchar i,j=0x80;

	while(1)
	{
		for(i=1;i<=8;i++)
		{
			j=_crol_(j,1);		//循环移位函数_crol_(j,1)将j循环左移1位
			P2=j;		//P2口输出位控码
			P0=seg[i];		//P0口输出段码
			delay(1000);		//延时,控制每位显示的时间
			P0=0xff;		//消影
		}
	}
}

代码重点解析:

1、循环移位函数功能分析

        j的初始值为0x80(即0b1000 0000),每执行一次for循环,循环移位函数_crol_(j,1)都将j循环左移1位。例如:当第一次执行for循环时,i=1,j循环左移1位,由初始值0x80(即0b1000 0000)变为0x01(即0b0000 0001);当第二次执行for循环时,i=2,则由0x01(即0b0000 0001)变为0x02(即0b0000 0010)……具体情况如下表所示。

i 1 2 3 4 5 6 7 8
j

0x01

0b0000 0001

0x02

0b0000 0010

0x04

0b0000 0100

0x08

0b0000 1000

0x10

0b0001 0000

0x20

0b0010 0000

0x40

0b0100 0000

0x80

0b1000 0000

点亮位置 第1位 第2位 第3位 第4位 第5位 第6位 第7位 第8位
显示数字 1 2 3 4 5 6 7 8

2、先输出位码(即位控码、位选码),再输出段码,否则数码管某些位会出现乱码

P2=j;		//P2口输出位控码
P0=seg[i];		//P0口输出段码

3、消影:消除上一个数码管段选对下一个数码管的影响,同时也可以提高数码管的亮度。

P0=0xff;        //消影

实验现象

数码管项目3——滚动显示单个数字1~8实验现象

【4】数码管的驱动

        因为单片机IO口的驱动电流较小,驱动能力很弱,主要用于对外设传感器的控制,所以数码管显示需要增加驱动模块。驱动模块的选择主要有三极管驱动和数字芯片驱动两种方式。

三极管驱动

        如图所示,NPN三极管的发射极(有箭头的那个极)连接到共阳极数码管的位选引脚基极与单片机的IO口相连,集电极连接的是VCC(+5V)。

        在软件编程时,如果要让共阳极数码管的第1位工作,单片机的P20引脚向NPN三极管Q1的基极输入高电平,这样数码管1号引脚的电压略低于5V,数码管第1位实现共阳极连接,输入段码即可完成显示。

74HC245数字芯片驱动

        74HC245是方向可控的八路缓冲器,主要用于提高电流驱动。在ptoteus仿真中,可以理解为从A端输入B端输出后,单片机的IO口便可以驱动数码管等大功率外设。

        接线方式如图所示,引脚1接VCC,引脚19接GND,A端引脚连接单片机控制外设的引脚,B端引脚与外设相连。

        项目四

        题目:单片机控制8只数码管,同时显示数字1~8。

        原理图:由于proteus仿真软件与实物存在细微差别,动态显示时采用三极管驱动数码管显示不稳定,所以使用74HC245芯片作为驱动,完成动态数码管的实验。

项目4所需器件列表
关键字 元件名称 型号 数量(个)
AT89C51 单片机 AT89C51 1
CRYSTAL 晶体振荡器 12MHZ 1
7SEG-MPX8-CA-BLUE 8位8段共阳极数码管 蓝色 1
CAP 电容 30pF 2
CAP-ELEC 电解电容 10uF 1
RES 电阻 1kΩ 1
RES 电阻 10kΩ 1
RX8 双向排阻 220Ω 1
74HC245 8位双向总线驱动器 1
BUTTON 复位按键 1

代码:只需将项目三代码中的延时函数由“delay(1000);”改为“delay(10);”即可。

#include <reg52.h>
#include <intrins.h>		//包含循环移位函数的头文件

#define uchar unsigned char		//宏定义无符号字符型变量方便书写
#define uint unsigned int		//宏定义无符号整型变量方便书写

uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};		//共阳极段码表

void delay(uint n)		//延时函数ms
{
	uchar i;
	uint j;
	for(j=0;j<n;j++)
	for(i=0;i<123;i++);
}

void main(void)
{
	uchar i,j=0x80;

	while(1)
	{
		for(i=1;i<=8;i++)
		{
			j=_crol_(j,1);		//循环移位函数_crol_(j,1)将j循环左移1位
			P2=j;		//P2口输出位控码
			P0=seg[i];		//P0口输出段码
			delay(10);		//延时,控制每位显示的时间
			P0=0xff;		//消影
		}
	}
}

实验现象

【5】Proteus8.13 新建工程详细教程

1、桌面新建文件夹→重命名为“项目名”。(也可以在计算机的其他位置新建文件夹)

2、双击打开Proteus 8 Professional软件

3、【文件】→新建工程

4、更改工程名称为“项目名”;点击“浏览”→找到并打开第1步新建的文件夹→点击“选择文件夹”。

5、点击“Next”

6、保持默认选项,一直点击“Next”,最后选择“Finish”。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐