一.操作LED实现流水灯
二.操作蜂鸣器和继电器实现系统的初始化
三.操作数码管实现动态显示
一.操作LED实现流水灯
我之前玩过郭天祥老师的那块51板子,那块板子点亮LED要简单许多,我如果没记错的话应该是只用控制P0口就行了,但这块板子不一样,它涉及到了或非门,锁存器,译码器。废话不多说,上电路图:
这里我们可以到发光二级管的阳级接了一个限流电阻之后就与Vcc相连接(也就所谓的高电平),这时二级管的阴极接了一个74HC573的非反转透明锁存器(讲人话就是当Y4C为高电平状态时,P0的某位输出高电平,二级管的阴极就是高,输出低电平,阴极对应的就是低,然而当Y4C为低电平时,此时则不能通过P0端来调整,二级管的阴极的电平,即数据状态被锁存),此时使二级管亮的问题,就变成了,使Y4C为高电平,我们继续看电路图:
说这个图之前,我觉得有必要讲讲单片机的两种编程模式:IO扩展模式和存储器映射模式。比赛推荐第一种方式。怎么选择IO扩展模式呢?这里我们需要调整板子上的J13跳线帽,使得2,3口短接。上图:
由上上图可知Y4C被一个或非门控制着,而WR口已经与地相接,由或非门的定义我们可以得出只有当Y4为低电平时,Y4C才为高电平(先或,两口都为0,最后一非,不就为1了)。
问题继续转变,要使Y4C高,得使Y4为低,如何做,继续看图:由图我们可以看出,Y4被一个38译码器控制着(为啥叫38译码器?我的理解是3位控制8位),这38译码器又是如何工作的呢?我们就要去查芯片手册了,上图:
上图是38译码器的真值表,由电路图可知G1接了Vcc(高电平),G2接地(低电平),此时P2端的5,6,7位就可以控制Y1,Y2…Y8。如何控制,你可以看真值表,其实就是二进制表示方法,三位二进制数(CBA)000(十进制对应0),Y0为低,001(十进制对应1),Y1为低,010(十进制对应2),Y2为低,到这我相信你已经看出规律了。以上就是点亮LED的理论部分,新手看来,可能心中在骂娘(为什么要搞这么复杂?直接P0口控制不好吗?)不过大家可以想想,这样是不是使得有限的引脚能控制更多硬件。不过话也说回来,只要搞懂上面所说这是小玩意,你基本上就能很自如的控制LED,数码管,蜂鸣器,继电器。
接下来上代码:
#include<reg52.h>
#include"intrins.h" //_nop_()这个函数的头文件
sbit HC138A=P2^5;
sbit HC138B=P2^6;
sbit HC138C=P2^7;
void Delay300ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 14;
j = 174;
k = 224;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
unsigned char i;
void main()
{
while(1)
{
HC138A=0;
HC138B=0;
HC138C=1;//使得Y4为低电平,此时MR为低 通过或非门后 Y4C为高
for(i=0;i<8;i++)
{
P0=0xff<<i+1;//左移多少位,后面自动补0,补一位亮一位LED
Delay300ms();
}
for(i=0;i<8;i++)
{
P0=~(0xFF<<i+1);//跟上面相反正好
Delay300ms();
}
}
}
这里有人会说,你这延时函数怎么看着B格有点高。我不想解释,我上图:
烧写软件可方便了,我怎么实现跑马灯的不重要,重要的是要学会怎么使它跑起来,小小总结:要使LED亮得使得阴极端为低电平,要使阴极端为低电平得使得Y4C为高,要使YC4为高,得使Y4为低,说着可能感觉有点复杂,但其实,用代码实现起来并没有那么复杂。
二.操作蜂鸣器和继电器实现系统的初始化
大家在操作上面那个实验历程的时候,如果在实验室,可能会感觉有点小尴尬,一上电,蜂鸣器响个不停,全实验室的人都看过来了,就知道了你又开始学单片机了。该如何使它关闭呢?这也是我们去打比赛时的一个步骤,常常比赛文件会要求我们关闭外设,我们继续看图:
这里解释一下继电器的原理吧,其实这就是一个电磁铁,当N_RELAY为低电平的时候,电磁铁上开始有电流,K1就会被吸下来,L10就会点亮(继电器旁边的小灯),蜂鸣器就是N_BUZZ为低电平的时候就会响。怎么控制这两个端口呢?我们继续看电路图:
看到左边,我们笑了,笑的十分开心,为什么?因为在学LED点亮的时候,我们学过了,看到右边,于是我们哭了,为什么,没学过。怎么办?看芯片手册:
学会查找芯片手册,是学习单片机一种十分重要的手段,看到这张图,我们觉得这十分简单,不就是一个非门吗,名字取那么唬人干嘛(达林顿管)。然后怎么控制Y5C,如果不知道请从头开始看,我一开始讲的就是这个。又上面的知识我们可以得出当Y5C为高电平时,P0的第4位,6位为低时(通过达林顿管电平变高),就可以关闭继电器和蜂鸣器了。来上代码:
void System()
{
HC138A=1;
HC138B=0;
HC138C=1;//使Y5变成低电平
P0=0x00;
}
同样的逻辑代码实现很简单,但里面的逻辑一定要懂。小小总结:这里面设计到了一个新名词(达林顿管)我的理解是就是一个非门(起码在这些实验历程里是这样的),要控制继电器和蜂鸣器就得控制N_BUZZ和N_RELAY,要控制这两个口,就得控制573和达林顿管,要控制这两,就得控制Y5C,要控制Y5C就得控制Y5,里面也同样涉及到或非门。
这里大家应该慢慢开始能明白为什么要这么做了,通过一个锁存器,P0既可以控制LED,还能控制蜂鸣器和继电器。其实还能控制数码管,来我们接着来看数码管。
三.操作数码管实现动态显示
这里我们来看数码管的电路图:蓝桥杯所用的这块板子里面的数码管是一个共阳数码管,什么意思呢?我们知道这些数码管都是二级管,二级管就有所谓的阴阳级之分,这里就把所有的数码管每一段的二级管的阳级接在了一起,并且是一个高电平,所以我们只需要在阴极那里输入第电平就可以使二极管点亮。这里我们从上图可看出,有两种端子,一种com端控制位的亮灭,com1口为1,则com1那一位的数码管亮;还有一种是a1,b1,c1…这种是控制数码管哪几段在亮的,我们这里是共阳级,所以只需要将其制低电平,就可以使某些段亮。这里明白人可能会想,这16个口怎么就能控制八位数码管呢(控制一个数码管亮灭需要一个口,呈现出什么信息需要八位,这样算起来需要8*8+8)?假设人的眼睛没有视觉残留效应,二级管切换亮灭是一瞬间的,那么你会发现这些数码管要么就一起亮一样的数,要么就单个亮不同的。这些都是我们不喜欢的,可是这种假设是错误的,我们是有视觉残留效应的,二级管灭了在极短时间内是有余晖的,所以动态扫描显示这种方法就应运而生了。我们来动态显示一个“2022–01”,来我们来看代码:
#include<reg52.h>
#include"intrins.h"
unsigned char code SMG_duanma[18]={0xc0,0xf9,0xa4,0xb0
,0x99,0x92,0x82,0xf8
,0x80,0x90,0x88,0x80
,0xc6,0xc0,0x86,0x8e
,0xbf,0x7f};
void selectHC573(unsigned char channal)
{
switch(channal)
{
case 4: //选择打开哪些锁存器
P2=(P2&0X1F)|0X80; //至于为什么可以这么写,来评论区讨论吧
break;
case 5:
P2=(P2&0X1F)|0XA0;
break;
case 6:
P2=(P2&0X1F)|0XC0;
break;
case 7:
P2=(P2&0X1F)|0XE0;
break;
}
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void show_SMG(unsigned char value,unsigned char pos)
{
selectHC573(6);
P0=0X01<<pos; //控制数码管亮的位置
selectHC573(7);
P0=SMG_duanma[value];//控制该位亮的内容
}
void System()
{
selectHC573(5); //关闭继电器和蜂鸣器 减少尴尬
P0=0x00;
}
void main()
{
System();
while(1)
{
show_SMG(2,0);
Delay1ms();
show_SMG(0,1);
Delay1ms();
show_SMG(2,2);
Delay1ms();
show_SMG(2,3);
Delay1ms();
show_SMG(16,4);
Delay1ms();
show_SMG(16,5);
Delay1ms();
show_SMG(0,6);
Delay1ms();
show_SMG(1,7);
Delay1ms();
}
}
动态显示的延时函数大概设置为1~2个毫秒就可以了,这个可以自己调整,调整到不闪烁,亮度足够就行了。
这里就不小结了,其实重点还是在573锁存器,和38译码器。
大总结:上到这就结束了,重点就是573锁存器,和38译码器,多敲,多练就熟悉了,慢慢的其实这些不看电路图,也是可以实现的。
可能码字过程中有错字,或者有bug的存在,希望大家在评论中指出。来我们共同进步。
如果有人看的话,在中篇我会讲:按键,定时器1,pwm脉宽调制。