静态数码管:最左端显示0
动态数码管:从左到右,显示0-9
数码管是一种半导体发光器件,其基本单元是发光二极管;
类别:
共阳数码管和共阴数码管:
我们开发板上使用的数码管是2个四位一体的共阴极数码管(即8个LED的阳极全部并联一起引出,阴极分别引出如A、B、……、DP);
如果要让共阴数码管显示数字0,即对应的段ABCDEF要点亮即给它高电平,其他的段熄灭即给它低电平,其他的数字显示方式一样;
共阴和共阳数码管的0-F段码数据表
0x3f | 0x06 | 0x5b | 0x4f | 0x66 | 0x6d | 0x7d | 0x07 | 0x7f | 0x6f | 0x77 | 0x7c | 0x39 | 0x5e | 0x79 | 0x71 | 0x00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 无显示 |
0xC0 | 0xF9 | 0xA4 | 0xB0 | 0x99 | 0x92 | 0x82 | 0xF8 | 0x80 | 0x90 | 0x88 | 0x83 | 0xC6 | 0xA1 | 0x86 | 0x8E | 0xFF |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 无显示 |
从上述共阳和共阴码表中不难发现,它们的数据正好是相互取反的值;
共阴数码管数字0段码,0x3f,其二进制是0011 1111,该段码数据由来,是将dp段做为最高位,a段作为最低位,共8位,正好和51单片机的一组端口数一样,因此可以直接使用某一组端口控制数码管的段选数据口,比如P0口
每个数码管的段选接一个8位数据线来保持显示的字形码,当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止;
优点是占用CPU时间少,显示便于监测和控制;
缺点是硬件电路比较复杂,成本较高,比如使用4个静态数码管,那么就得32个IO来控制,这对51单片机来说是无法承受的;
将所有数码管的段选线并联在一起,由位选线控制是哪一位数码管有效;
选亮数码管采用轮流显示的方式,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示;
动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路的电阻;
由原理图可以看出,P00-07管脚控制数码管显示的图形,P22-24控制哪个数码管被点亮;
因为单片机IO口外部都增加了外部上拉电阻,因此P22、P23、P24引脚默认就是高电平,根据74HC138译码器输出特点,此时Y7脚输出有效(即LED8点亮),为低电平;
而数码管的段选a-dp连接在74HC245驱动芯片输出口,由P0端口控制,所以只要控制P0口输出高电平,SMG1最左边那个数码管默认就可以显示;
让P0口设置为0的的段码数据,即可在最左端显示数字0
main.c
/*
* @Description: 静态数码管-最左端显示0
*/
#include "reg52.h"
typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;
#define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口
// 共阴极数码管显示0~F的段码数据
u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
void main()
{
SMG_A_DP_PORT = gsmg_code[0]; // 将数组第1个数据赋值给数码管段选口
while (1)
{
}
}
按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机
人的肉眼正常情况下只能分辨变化超过24ms间隔的运动;
所以我们可以循环点亮各个数码管,并且这个循环间隔不超过24ms,这样看起来就是每个数码管都被点亮了;
main.c
/*
* @Description: 动态数码管-从左到右,显示0-9
*/
#include "reg52.h"
typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;
#define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口
// 定义数码管位选信号控制脚
sbit LSA = P2 ^ 2;
sbit LSB = P2 ^ 3;
sbit LSC = P2 ^ 4;
// 共阴极数码管显示0~F的段码数据
u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
/**
* @description: 延时函数(循环一次大约10us)
* @param {u16} ten_us
* @return {*}
*/
void delay_10us(u16 ten_us)
{
while (ten_us--)
;
}
/**
* @description: 循环点亮各个数码管
* @return {*}
*/
void smg_display(void)
{
u8 i = 0;
for (i = 0; i < 8; i++)
{
switch (i) // 位选
{
case 0:
LSC = 1;
LSB = 1;
LSA = 1;
break;
case 1:
LSC = 1;
LSB = 1;
LSA = 0;
break;
case 2:
LSC = 1;
LSB = 0;
LSA = 1;
break;
case 3:
LSC = 1;
LSB = 0;
LSA = 0;
break;
case 4:
LSC = 0;
LSB = 1;
LSA = 1;
break;
case 5:
LSC = 0;
LSB = 1;
LSA = 0;
break;
case 6:
LSC = 0;
LSB = 0;
LSA = 1;
break;
case 7:
LSC = 0;
LSB = 0;
LSA = 0;
break;
}
SMG_A_DP_PORT = gsmg_code[i]; // 传送段选数据
delay_10us(100); // 延时一段时间,等待显示稳定
SMG_A_DP_PORT = 0x00; // 消影
}
}
void main()
{
while (1)
{
smg_display();
}
}
按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机