说明
本人使用的是清翔的51单片机开发板,如果型号相同最方便,但是如果型号不同也可以参考,因为芯片都是一样的,只是外设不同而已,使用时只需要对照自己的开发板原理图稍微修改下引脚即可。
本次笔记对应清翔视频教程的第16、17、18集 数码管静态显示和动态显示(理论+编程)
数码管内部由8个LED组层,排列成8字形,点亮对应的LED,熄灭其他的LED,即可显示想要的数组/字母
b图左侧是共阴极数码管,b图右边是共阳极数码管(把阳极或者阴极接在一起,就叫做共阳/阴极数码管)
比如我想显示1,那么只需要把bc点亮,其余熄灭,就可以了
根据原理图我们发现,如果我想显示1,那么只需要把ABCDEFGH电平变成0110 0000,根据连接关系,发现A连接的是P0端口的低位,H是P0端口的高位,也就是说P0端口应该是0000 0110 ,也就是0x06
单片机引脚网络
静态显示
LED显示器工作方式有两种:静态显示方式和动态显示方式。静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。
动态显示
动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
直接上图,清晰明了
简单来说,OE接地,当LE = 1,左右两侧是通的,当LE = 0;左右两侧断开,右侧数据保持断开前的状态不变
两个锁存器的OE引脚,位选接在P2^7,段选接在P2^6,因此可以控住这两个位的高低电平来决定P0端口数据是段选还是位选
复制一份工程模板,并改名为“5.数码管静态显示”,打开项目工程
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
这样锁存器就会把第一个数码管以及数字1锁住
原理图再放一下
#include
typedef unsigned char uchar;
typedef unsigned int uint;
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
void main()
{
DU = 0; //关闭段选
WE = 1; //打开位选
P0 = 0xfe; //位选,选中第一个数码管11111110
WE = 0; //关闭位选 HGFE DCBA
P0 = 0x06; //在开启段选之前,先把段选数据设置好 0000 0110
DU = 1; //开启段选
DU = 0; //关闭段选
while(1)
{
}
}
开发板上的是共阴极数码管,所以在位选中等于0的数码管才会被选中。在段选中,等于1的段才会点亮。
打开stc-isp软件,点击“打开程序文件”,在弹出的文件浏览窗口中进入“2.LED闪烁”,在Objects文件夹下选中.hex文件,再点击下载即可,详见清翔零基础教你学51单片机_个人学习笔记(1)_点亮开发板上的LED灯
3.3 点击编译 3.4 下载 这两个章节的内容
#include
typedef unsigned char uchar;
typedef unsigned int uint;
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
void main()
{
DU = 0; //关闭段选
WE = 1; //打开位选
P0 = 0xfc; //位选,选中第一个数码管11111100
WE = 0; //关闭位选
P0 = 0x4f; //在开启段选之前,先把段选数据设置好 0100 1111
DU = 1; //开启段选
DU = 0; //关闭段选
while(1)
{
}
}
静态显示只能让不同的数码管显示一样的数字,动态显示却能做到让不同的数码管显示不同的数字。
利用的原理就是先开启位选,选择某一个位之后关闭位选,再打开段选传输要显示的数字,传输完成再关闭段选锁存,如此快速变换,就可以让人眼感觉不同的数码管都在发光,并且由于送给不同数码管的显示数据不同,不同数码管的显示也不同。
void main()
{
while(1)
{
DU = 0; //关闭段选
P0 = 0XFE; //选择第1个数码管 1111 1110
WE = 1; //开启位选
WE = 0; //关闭位选
P0 = 0X4F; //传输显示数据 3 01001111
DU = 1; //开启段选
DU = 0; //关闭段选
delay(1);
P0 = 0XFD; //选择第2个数码管 11111101
WE = 1; //开启位选
WE = 0; //关闭位选
P0 = 0X07; //传输显示数据 7 0111
DU = 1; //开启段选
DU = 0; //关闭段选
delay(1);
}
}
延时的作用是清除残影,如果残影比较严重,可以增加延时
数组是一组有序数据的集合,数组中每一个数据都是同一数据类型。数组中的元素可以用数组名和下标来唯一确定,
C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。
数组的声明并不是声明一个个单独的变量,比如 runoob0、runoob1、...、runoob99,而是声明一个数组变量,比如 runoob,然后使用 runoob[0]、runoob[1]、...、runoob[99] 来代表一个个单独的变量。——选自菜鸟教程
详细的知识点可以参考C语言中文网-什么是数组
一般格式:数据类型 数组名[元素个数] = {元素};,当然数组也有二维数组等高维数组,这里不过多介绍。有时数组元素个数不确定,[元素个数]里面的元素个数也可省略,编译器会自动根据数组初始化的结果分配内存
#include
typedef unsigned char uchar;
typedef unsigned int uint;
void delay(unsigned int i);
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
//code它告诉编译器将数组中的数据存储在程序存储器中,而不是存储在数据存储器(RAM)中。
uchar code we[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
uchar code du[]={
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00, //熄灭
0x00 //自定义
};
void SEG_DIS(uchar position, uchar number)
{
DU = 0;
WE = 0;
P0 = we[position - 1];
WE = 1;
WE = 0;
P0 = du[number];
DU = 1;
DU = 0;
delay(1);
}
void main()
{
while(1)
{
SEG_DIS(1,3);
SEG_DIS(2,7);
}
}
void delay(unsigned int i)
{
unsigned int j;
for (; i > 0; i--)
for (j = 114; j > 0; j--);
}
现象跟刚才一样,在第一个数码管显示3,同时在第2个数码管显示7
显示3位数只需要把刚才的再给封装一下就行了
首先定义一个函数
void SEG_DIS3(uchar i)
{
SEG_DIS(1, i / 100);
SEG_DIS(2, i % 100 / 10);
SEG_DIS(3, i % 10);
}
然后再在main函数里面调用
void main()
{
while(1)
{
SEG_DIS3(137);
}
}
这样数码管前三位就会显示1, 3 ,7,非常方便
本次笔记对应清翔视频教程的第16、17、18集 数码管静态显示和动态显示(理论+编程),到此结束。下一个笔记将对应视频教程的19、20集 独立键盘(理论+实践)