一、数码管分类与定义
分类:数码管分为静态数码管(单个,一位)和动态数码管(联排,如2位、4位、8位)。
定义:数码管是由多个发光二极管封装在一起形成“8”字形的器件,用于显示数字和符号。
二、数码管构造与原理
构造:数码管内部由八个发光二极管组成,分别对应a、b、c、d、e、f、g和dp段,用于显示不同的数字和图形。
原理:通过控制对应的发光二极管亮灭来显示数字和符号。共阳极和共阴极数码管分别通过给予低电平和高电平来点亮LED。
三、数码管显示方式
静态显示:每个数码管的段选接一个8位的数据线来保持显示的字形码,显示稳定但硬件电路复杂,成本较高。
动态显示:通过扫描方式控制各个数码管轮流显示,节省I/O口资源,适用于多位数码管显示。
四、数码管在51单片机中的应用
在51单片机系统中,数码管常用于显示数字、字符等信息,如温度、时间等。
通过编程控制数码管的段选和位选信号,实现动态或静态显示。
可以利用译码器等外设进一步减少需要操作的引脚数,提高显示控制的灵活性。
五、硬件设计
我们可以通过阴极控制显示的位置,通过阳极控制显示的内容。两个数码管共有8个阴极引脚和16和阳极引脚,如果所有引脚都直接接入MCU,会造成MCU引脚的极大浪费。为了节省MCU的引脚,我们可以将两个数码管的阳极接在一起。
74HC138
由于8位数码管同一时刻只需显示1位,因此数码管的阴极可使用74HC138芯片进一步节省MCU的引脚
74HC245
由于51单片高电平的驱动能力很微弱,不足以点亮数码管,因此可以使用74HC245N作为驱动芯片
有了74HC245之后,51单片引脚的输出就只用作信号,而驱动数码管的电流则由74HC245的电源提供
硬件原理图
静态实现
确定显示位置称为数码管的位选,确定显示内容称为数码管的段选
数码管的位选通过74HC138芯片控制,更具体的说,是通过单片机的P13、P14、P15引脚控制
数码的段选通过单片机的P00~P07这7个引脚控制,具体的对应关系如下。
#include <STC89C5xRC.H>
typedef unsigned char u8;// 数字0-9的编码
static u8 codes[10] = {0x3F, // 00x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 80x6F // 9
};void DigitalTube_DisplaySingle(u8 position, u8 num_code)
{// 位选:P15 P14 P13position <<= 3; //先左移3位P1 &= 0xC7; //11000111 先把13 14 15位置0P1 |= position; //赋值// 段选:P0P0 = num_code;
}void main()
{//第一个数码管显示数字1DigitalTube_DisplaySingle(0, codes[1]);while (1) {}
}
动态实现
#include <STC89C5xRC.H>
#include <INTRINS.H>
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;// 数字0-9的编码
static u8 codes[10] = {0x3F, // 00x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 80x6F // 9
};//数码管要显示每一位的数字
u8 buffer[8];void Delay1ms(u16 count)
{u8 i, j;while (count > 0) {count--;_nop_();i = 2;j = 199;do {while (--j);} while (--i);}
}//显示一位
void DigitalTube_DisplaySingle(u8 position, u8 num_code)
{P0 = 0x00;// 位选:P15 P14 P13position <<= 3;P1 &= 0xC7;P1 |= position;// 段选:P0P0 = num_code;
}//显示多位
void DigitalTube_DisplayNum(u32 num)
{//先将数组所有值设置零u8 i;for (i = 0; i < 8; i++) {buffer[i] = 0x00;}//如果显示数字为0直接赋值最后一位为0,函数停止if (num == 0) {buffer[7] = codes[0];return;}//提取数字每一位到数组对应位置上i = 7;while (num > 0) {buffer[i] = codes[num % 10];num /= 10;i--;}
}//显示每个数字
void DigitalTube_Refresh()
{u8 i;for (i = 0; i < 8; i++) {DigitalTube_DisplaySingle(i, buffer[i]);Delay1ms(1);}
}void main()
{//显示多位数字DigitalTube_DisplayNum(1234567);while (1) {//不断刷新DigitalTube_Refresh();}
}