❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。⭐️ 专栏主要内容: 主要学习51单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v
本学习过程参考:https://space.bilibili.com/383400717
单片机安装软件、各种资料以及源码的路径:
https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng
提取码:gdzf
文章目录
- 一、本节背景和目标
- 1.1 数码管原理介绍(很重要!!!)
- 1.1.1 数码管介绍
- 1.1.2 一位数码管
- 1.1.3 四位一体数码管
- 1.1.4 多个数码管同时显示不同数字
- 1.1.5 数码管原理图解析
- 1.1.6 138译码器
- 1.1.7 74HC245(双向数据缓冲器)
- 1.2 本节目标
- 二、静态数码管显示
- 三、动态数码管显示
一、本节背景和目标
1.1 数码管原理介绍(很重要!!!)
1.1.1 数码管介绍
1.1.2 一位数码管
下图是个一位的数码管,
数码管是由8个LED组成的,其中共阴极数码管是8个LED共用一个阴极;共阳极数码管是8个LED共用一个阳极;每个数码管灯由图中左下角的8段LED构成,分别是ABCDEFG以及DP;正好和1个字节的8位相对应;从图中也可以看出,8段LED中,每段LED对应的引脚图,即每段LED和引脚之间的连接关系,基本是按照就近原则来连接的,比如A段,A段的正极连接3和8引脚(在共阳极数码管的情况下),A段的负极连接7号引脚;以此类推,其他引脚关系都可从图中看出来。
值得注意的是,我们开发板上的连接方式是共阴极连接。
如果想要使这个数码管显示数字“6”,该怎么操作呢?需要让A、F、E、D、C、G都亮起来即可。那么如何使A、F、E、D、C、G都点亮,其他的熄灭呢?参照上面的图可知,对于共阴极连接方式,首先3和8引脚都是要接地的(即负极、低电平、0);然后A、F、E、D、C、G都接正极(高电平,1),B和DP接负极,这样就能得到一个数字“6”,即A、B、C、D、E、F、G、DP设置为1011 1110
;
1.1.3 四位一体数码管
下图是一个四位一体的数码管:
可以看到,以共阴极数码管为例,每个数码管共用阴极,但是四个数码管阳极所有的对应引脚都是连接同一个引脚;例如这四个数码管的A段LED都是连接在一起的,和11引脚相连;这四个数码管的B段LED都是连接在一起的,和7引脚相连。这样做的好处是节省单片机的引脚,如图中有4*8=32个LED段,但是只用12个引脚就可以了。
对于这种数码管,如果想让第三位数码管显示一个数字1,怎么操作?
按照共阴极数码管的连接方式,应按下图方式操作:
因为是共阴极,所以12、9、8、6正常来讲都是负极才能点量对应的数码管。要想达到只第三个数码管显示1的目的:其中引脚12、9、6这三个阴极都置为1(高电平),这样第一、二、四个数码管就都不会亮;将引脚8设置为0(低电平),这样第三个数码管就有了电路连通的条件;然后再将B断和C段对应的引脚置为高电平,即7和4引脚置为1(高电平),此时就能第三个数码管中的B和C段对应的LED灯就亮了,其他段的灯不亮,即达到了只第三个数码管显示1的目的。
1.1.4 多个数码管同时显示不同数字
关于上面讲到的,这四个数码管四个数码管阳极所有的对应引脚都是连接同一个引脚,这样导致的结果是,如果我们想让第二个数码管和第三个数码管同时点亮,且第二个和是第三个数码管显示不同的数字,是无法做到的,因为即使为了让第二个数码管亮而将9号引脚置为0,那么此时9和8引脚都为0,7和4引脚都为1,结果是第二个二极管和第三个二极管都显示数字1,无法达到显示不同数字的目的;所以因为四个二极管对应段LED都共用同一个引脚,导致的结果是只能显示同样的数字。
那么如何使不同的数码管显示不同的数字呢?这就是我们的目标2要实现的了,即动态数码管显示;利用的原理是人眼的视觉暂留和数码管显示的余晖原理;比如我们想达到让前三个数码管分别显示“1”“2”“3”的目的,经过上面的理论我们可以知道让三个数码管同时显示三个不同的数字是不可能的,但是我们可以让第一个数码管显示数字1,然后迅速的让第二个数码管显示数字2,然后迅速的让第三个数码管显示数字3,这要他们的间隔足够短,在我们视觉上看起来就像是同时在显示1、2、3一样。
1.1.5 数码管原理图解析
数码管在开发板上的位置
数码管的原理图如下所示:
其中138译码器和数码管都是其组成部分。
如果想要使某个数码管亮,将其置为引脚0;如上图,LED6(引脚8)置为0,将其选中,则LED6具备了点亮的条件;其他的LED置为1,表示不选中,不会亮。
例如想要是LED6显示数字1,则按照如下图操作:
1.1.6 138译码器
由上面的原理图可知,LED1-8(即公共负极)其实是接在138译码器的LED1-8(引脚7、9、10-15)上的,也是138译码器的输出;而138译码器的输入是接在MCU的P22-P24口的;所以可以得知,138译码器由P22-P24三个输入口,控制LED1-8这8个输出口LED的状态;具体是怎么做到的呢?
138译码器是三个线到八个线的译码器;其实就是负责将三个输入A、B、C(P22-P24)转成八个输出Y0-Y7
(也对应LED1-8);A、B、C三个输入值分别表示为三个二进制的数(C为高位,B为中位,A为低位,即数字组成为CBA),这三个输入值,转换成十进制,就对应他们的输出。
例如输入A为0,B为0,C为0,则输入为000,其对应的十进制值是0,即Y0有效,其他无效(低电平为有效,高电平位无效),所以Y0是0,Y1-Y7为1;
再例如,如果输入A为1,B为0,C为0,则输入为001(CBA,前面说了,C为高位,B为中位,A为低位),其对应的十进制为1,即Y1有效,其他无效(低电平为有效,高电平位无效),所以Y1是0,Y0和Y2-Y7为1;
以此类推。。。。
其真值表如下所示
1.1.7 74HC245(双向数据缓冲器)
由原理图可以得知,晶体管的正极是接在74HC245(双向数据缓冲器)上的。
作用:双向的数据缓冲
如下图所示:DIR的高低电平决定了数据的流向;在74HC245中,如果将DIR,也就是LE(1引脚)设置为高电平,则表示数据流向为从左边到右边。由下图可知,A0对应B0,A1对应B1,以此类推;而B0-B7对应LCD0-7;
总结一下说就是,输入给P00-P07什么数据,该数据就原封不动的送给LCD0-LCD7
。
1.2 本节目标
目标1:在晶体管的任意位置显示任意数字,下图在第三个位置显示了数字6:
目标2:
在数码管的前三位显示三个数字123,即数码管的动态显示,可以在数码管的任意位置显示任意数字,且可以多个数字显示
二、静态数码管显示
经过上面的学习可以得知,如果想使数码管显示数字,
第一步是选择使哪个晶体管点亮:即要让目标点亮的等负极有效(参考第1.1.5和1.1.6节),而负极是接在138译码器上的,138译码器的8输出连接着静态数码管的负极,138译码器的3个输入连接着MCU的引脚(P22-P24口);所以我们要通过对P22-P24口的设置,来控制目标晶体管负极有效。
第二步是设置该目标点亮的晶体管具体显示什么数字;即通过对正极引脚的设置,控制具体LED的8段LED哪几段点亮,用以生成目标数字。而参考第1.1.7节,晶体管的正极是由74HC245的P00-P07等8个引脚来输入的;
总结:
- 第一步,选择哪个晶体管点亮,控制引脚为P22-P24;
- 第二步,选择具体点亮的数字,控制引脚为P00-P07;
代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\4-1 静态数码管显示
具体代码:
先写一个使第三个数码管显示数字6的程序:
首先第一步,选择第三个数码管点亮,即LED1设置为低电平0;由下图可知,LED3对应着138译码器上的Y2,那么要使Y2输出0,其他Y输出1;由1.1.6节中的真值表可以得知,C、B、A对应的值应该设置为0.1,0;所以应该设置P22为0,P23为1,P24为0;
第二步,显示数字6,则要使第一个数码管中的a、f、e、d、g、C六个LED点亮,参考上图,可以得知应将P00、P05、P04、P03以及P06、P02设置为1,P01设置为0;
具体代码如下所示:
#include <REGX52.H>
void main()
{
while(1)
{
P2_2=0;
P2_3=1;
P2_4=0;
P0_0=1;
P0_1=0;
P0_2=1;
P0_3=1;
P0_4=1;
P0_5=1;
P0_6=1;
P0_7=0;
}
}
该方法直接对P0的8个引脚逐个进行了赋值,当然除此之外,我们还可以对P0口整体进行赋值,以上面为例,P00、P05、P04、P03以及P06、P02设置为1,P01设置为0,则对应的P0口的值为:因为P0-P7中,P00为低位,P07为高位,按照从左到右为从高到低的写法,P0口的值为1111 1101
,转化成16进制就是0xFD
;所以方法2的代码如下:
#include <REGX52.H>
void main()
{
while(1)
{
P2_2=0;
P2_3=1;
P2_4=0;
P0 = 0xFD;
}
}
最终的效果为目标1:
最后,我们可以对代码进行完善,写一个函数,两个入参分别为:第一个参数为第几个等亮,第二个参数为显示什么数字,这样就能通过调用该函数时,传入参数的不同,控制不同的灯显示不同的数字,代码如下:
#include <REGX52.H>
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//数码管显示子函数
//Location表示第几个数码管点亮;Number表示该数码管显示什么数字
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
}
void main()
{
Nixie(3,6); //在数码管的第3位置显示数字6
while(1)
{
}
}
三、动态数码管显示
代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\4-2 动态数码管显示
基于1.1.4节的理论和第二节的代码,我们可以得到动态数码管的方法和代码,即如果想让第一个数码管显示1,第二个数码管显示2,第三个数码管显示3,且让他们同时显示;方法就是先让第一个显示1,然后立马让第二个显示2,再立马让第三个显示3;只要他们之间的间隔足够短,在我们视觉效果上看来就是在同时显示。
具体代码如下:
#include <REGX52.H>
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//延时子函数
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
Delay(1); //显示一段时间
P0=0x00; //段码清0,消影
}
void main()
{
while(1)
{
Nixie(1,1); //在数码管的第1位置显示1
// Delay(20);
Nixie(2,2); //在数码管的第2位置显示2
// Delay(20);
Nixie(3,3); //在数码管的第3位置显示3
// Delay(20);
}
}
代码解释:
其中的P0=0x00;
表示每次循环结束时都将所有的数码管进行清零,即全部熄灭,免得留下灯的残影。
结果如下: