我们已经了解了最简单的流水灯模型,我们就开始学习数码管啦!我们可以慢慢的循序渐进学习这些神奇的现象,从这篇开始我们重点只介绍实验原理和代码
八位数码管实际上很多的案例,这里主要介绍
其实验现象为:
从左到右8个数码管分别显示1、2、3、4、5、6、7、8
我们就直接进入到其
先放图:
在学习流水灯的时候我们已经接触过这个图了,心细的同学可能已经发现八位数码管也存在这里面
扩展:(这些我们下面的例子会具体的涉及到)
A在8位中的最低位,DP位为最高位。组合成的八位对应P0口的八位。数码管又分为共阴极和共阳极两种类型;其中共阴极就是将八个LED阴极连在一起,让其接地,这样给任何一个LED发光管另一端高电平,它便能点亮。而共阳极就是将八个LED的阳极连在一起
共阴极数码管相应段位输入编码位1,则相应段灯亮;而共阳极数码管对应段位输入编码为0,则相应段灯亮。本处是采用的共阴极数码管。如果想让共阴极数码管显示数字0,则A、B、C、D、E、F、G位都需要输入为1。H与DP位为0,组合即为00111111
编写任何代码,我们都需要心里有一个框架,即我们需要做哪些工作
uint i=0; //全局定义
uchar duanxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};
//即按照a-h顺序定义了各段.
//e.g. 数组中第一个应该显示0,其对应的段选有效应为0011 1111
//即a-f均有效,
//注意低位为a
uchar weixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
//选择数码管0-7中的一个
void Delay(int n)
{
while(n--);
}
void main()
{
P2M0=0xff;
P2M1=0x00;
//只要设置p2.3为推挽输出即可
//即P2M0也可设置为0x08
P0M0=0xff;
P0M1=0x00;
//设置推挽输出
while(1)
{
//利用for循环,不断扫描数码管
//使数码管在点亮一段时间,视觉上达到一直亮的状态。
for(i=0;i<8;i++)
{
P0=0; //最开始设置不发光
P2=weixuan[i]; //选择第i位数码管发光
P0=duanxuan[i+1]; //第i位显示数字i+1
Delay(600); //设定一定的延时
}
}
}
看到这,可能会有同学有疑惑,为啥我们观察到的实验现象是一直在亮,而不是一个一个亮呢,这是由于我们的视觉暂留效应
应为:
从左到右8个数码管分别显示1、2、3、4、5、6、7、8。LED灯从右到左依次亮起
再放图:
还是这个图,是不是越看越亲切捏
数码管和流水灯的原理我们都已经涉及过了,那只要设置其同时显示就可以了(但是他能同时显示吗)
细心的同学可能会发现一个问题,上面在说数码管的时候,我们说到
P2.3经反相器U4C控制74HC138的使能信号E3
也就是P2.3为高电平的话,E3只能为低,那么数码管的使能就不能有效了,这不就是只能存活一个嘛,那是不是我们就可以结束了,这个就不能实现了呢
(毕竟人眼的感光不是那么的强,我们几乎是观察不到他们不是同时显示的呢)
(下面的这段原理就不用看啦,实际上就是考虑LED_SEL有多长时间为1还是为0,时间确定很重要,如果还是不懂,可以看代码的解释)
P0口的8位输出分别控制8个发光二极管L0~L7的阳极
而P2.3经反相器U4C控制8个发光管阴极E3;当阳极为高(对应P0口位为1)、阴极为低时,对应的二极管将会发光
而P2.3经反相器U4C控制74HC138的使能信号E3,结合P2.0、P2.1、P2.2这3个位选控制信号确定8个LED数码管中的哪个被点亮;电阻R15~R22为限流电阻。当段选为高、使能信号有效时,对应的LED管将会发光
通过以一定频率扫描位选信号,选择段选信号进行数码管点亮一段时间,从而给人视觉上几个数码管几乎同时显示的效果;同时扫描led,使led从左到右不断亮起
sbit sbtLedSel = P2 ^ 3;
这是一种引脚别名定义的方式
uchar uiLed = 0x01;
定义其最开始二极管为最低位有效
void Init()
{
P0M1 = 0x00;
P0M0 = 0xff;
P2M1 = 0x00;
P2M0 = 0x08;
//这些讲过很多遍,就放过它们吧,不拿它们念经了(嘻嘻嘻)
sbtLedSel = 0;
//设定最开始是数码管亮
}
void main()
{
Init();
while( 1 ) //永真循环
{
sbtLedSel = 0;
//每次执行完一次循环,仍设定其初始为数码管先亮
for( i = 0; i < 8; i++ )
{
P0 = 0;
P2 = arrDigitSelect[i]; //Ñ¡ÔñÊýÂë¹ÜµÄλÊý
P0 = arrSeg7Select[i + 1]; //ÏÔʾ¶ÔÓ¦µÄÊýÖµ
delay_ms( 1 );
}
//数码管8位显示正确数字
uiLedCnt++; //累加其次数
sbtLedSel = 1; //设定其为二极管亮
P0 = uiLed; //设定初始情况为最右边的灯先亮
delay_ms( 1 ); //构造流水灯效果
if( uiLedCnt == 50 ) //累加到50次才改变一位的二极管
{
if( uiLed == 0x80 )
uiLed = 0x01;
else
uiLed = uiLed << 1;
uiLedCnt = 0;
}
}
}
嘻嘻嘻,加上代码和原理,感觉这些东西都简单了很多呢
那就继续往下深入学习吧
该案例算是数码管里的黄金级别了吧,因为代码辣么长
8个数码管从左到右分别显示0到7的八个数字
隔一段时间后显示1到8,接着是2到9,再接着是3到0……重复这样的规律显示
达到的效果是0到9这10个数字循环向左移动
只需要改变其扫描的频率,并且每过多久改变一次显示的数值即可并且循环显示,原理比较简单
其中涉及的定时计数概念,我们将在后面详细讲解
void Init()
{
P2M0 = 0xff;
P2M1 = 0x00;
P0M0 = 0xff;
P0M1 = 0x00; //推挽输出
ucSeg7State = 0; //统计中断次数
ucCount = 0; //内部统计数码管扫描频率
ucDig1Tmp = 0; //初始化设置数码管显示为从左到右0-7
ucDig2Tmp = 1;
ucDig3Tmp = 2;
ucDig4Tmp = 3;
ucDig5Tmp = 4;
ucDig6Tmp = 5;
ucDig7Tmp = 6;
ucDig8Tmp = 7;
TMOD = 0x01; //寄存器0,方式1
ET0 = 1; //开启定时器中断
TH0 = ( 65535 - 1000 ) / 256; //定时器高8位设置
TL0 = ( 65535 - 1000 ) % 256; //定时器低8位设置
TR0 = 1; //启动定时器
EA = 1; //打开总的中断
}
//当定时器0初始值不断加一最终溢出时激发的处理方法
void T0_Process() interrupt 1 //把数码管的显示提到中断里
{
//重设TH0、TL0
TH0 = ( 65535 - 1000 ) / 256; //重新装载定时器0的初始值,为下一次定时做准备
TL0 = ( 65535 - 1000 ) % 256;
ucSeg7State++;
if( ucSeg7State == 8 ) //每中断8次才让count加一
{
ucSeg7State = 0;
ucCount++;
}
if( ucCount == 100 ) //count每递加到100,设定每一位显示的新值
{
ucCount = 0;
ucDig1Tmp++;
ucDig2Tmp++;
ucDig3Tmp++;
ucDig4Tmp++;
ucDig5Tmp++;
ucDig6Tmp++;
ucDig7Tmp++;
ucDig8Tmp++;
}
P0 = 0; //使P0显示不受上一次的影响
P2 = arrDigSelect[ucSeg7State]; //位选,选择第ucSeg7State个数码管
switch( ucSeg7State ) //每次中断选择一个数码管来显示
{
case 0:
P0 = arrSegSelect[ucDig1Tmp % 10];
break; //从左到右,第一个
case 1:
P0 = arrSegSelect[ucDig2Tmp % 10];
break; //第二个
case 2:
P0 = arrSegSelect[ucDig3Tmp % 10];
break; //第三个
case 3:
P0 = arrSegSelect[ucDig4Tmp % 10];
break; //...
case 4:
P0 = arrSegSelect[ucDig5Tmp % 10];
break;
case 5:
P0 = arrSegSelect[ucDig6Tmp % 10];
break;
case 6:
P0 = arrSegSelect[ucDig7Tmp % 10];
break;
default:
P0 = arrSegSelect[ucDig8Tmp % 10];
break;
}
}
void main()
{
Init();
while( 1 )
{
}
}
只要设定永真循环就好,因为定时器只要溢出,就会自动中断
这个似乎涉及到了我们的定时器,我们后面好好学习一下
那我们现在学习一下数码管中的骨灰级的案例趴(因为我们现在这个案例可以自己来控制很多显示现象了)
很神奇有没有
那么赶紧学一下原理把
似乎看完原理没啥用,那还是直接看代码吧
菜菜似乎能力不够,老师这一节都没给我们分享代码(/(ㄒoㄒ)/~~,感谢老师没有为难我们
那我们这一节的学习就到此结束啦!