关键词:蜂鸣器;继电器;跑马灯;关闭无关器件;小蜜蜂;&和|操作;模块化编程
一、知识点
1、分析各个部件,要使其工作,某接头处应该是低电平还是高电平
2、ULN2003由达林顿管组成,里面有非门
3、或非门:先进行或判断,后进行非判断
4、P0=0x10对应0001 0000,对应P07-P00
二、实验
实验目的;实现蜂鸣器和继电器的基本控制
实验原理:
S1:想让蜂鸣器和继电器运行,需使达林顿管正确运行(非门)——>锁存器使能,则Y5C=1——>或非门Y5=0——>138译码器CBA=101
S2;P04=1,继电器吸合,P0=0关闭; P06=1,蜂鸣器开启,P0=0关闭;
实验步骤:
S1:1-1跑马灯源代码复制粘贴
S2:定义一个初始化函数,调用即可关闭无关器件Y5输出低电平,P0=0x00;
S3:在逐个点亮LED后,通过138译码器让Y5输出低电平,控制锁存器使继电器(P04)吸合(0x10对应0001 0000,对应P07-P00),延迟一会儿后关闭(P0=0x00;)
S4:Y4输出低电平,转为控制LED亮灭,逐个熄灭后,通过138译码器让Y5输出低电平,控制锁存器使蜂鸣器(P06)打开,延迟一会儿后关闭(P0=0x00;)
S5:在main中while前加上InitSystem函数
代码:
#include <REGX52.H>
sbit HC138_A=P2^5;
sbit HC138_B=P2^5;
sbit HC138_C=P2^5;
void Delay(unsigned int t)
{
while(t--);
while(t--);
}
void LEDrunning(void)
{
unsigned char i;
HC138_C=1;
HC138_B=0;
HC138_A=0;//Y4输出低电平
for(i=0;i<3;i++)
{
P0=0x00;
Delay(60000);
Delay(60000);
P0=0xFF;
Delay(60000);
Delay(60000);
}
for(i=1;i<=8;i++)
{
P0=0xFF<<i;
Delay(60000);
Delay(60000);
}
HC138_C=1;
HC138_B=0;
HC138_A=1; //Y5输出低电平
P0=0x10; //让继电器吸合,P04=1
Delay(60000);//0x10对应0001 0000,对应P07-P00
Delay(60000);
P0=0x00;
HC138_C=1;
HC138_B=0;
HC138_A=0;//Y4输出低电平,这样才能将控制LED的锁存器打开
for(i=1;i<=8;i++)
{
P0=~(0xFF<<i);
Delay(60000);
Delay(60000);
}
HC138_C=1;
HC138_B=0;
HC138_A=1; //Y5输出低电平
P0=0x40; //让P06打开,蜂鸣器开启
Delay(60000);
Delay(60000);
P0=0x00; //过一会儿再把蜂鸣器关闭
}
void InitSystem(void)
{
HC138_C=1;
HC138_B=0;
HC138_A=1; //Y5输出低电平
P0=0x00; //通过非门,输出全部变成高电平,继电器和蜂鸣器关闭
}
void main()
{
InitSystem();
while(1)
{
LEDrunning();
}
}
三、改进
改进1:
改进原因:138译码器需要选择Y4和Y5来切换哪个器件使能,代码较长且重复
改进思路:编写一个138译码器选择端口的函数,参数为需要打开的口,用switch语句进行分支选择
改进后的代码:
void InitHC138(unsigned char n)
{
switch(n)
{
case 4:HC138_C=1;HC138_B=0;HC138_A=0;break;
case 5:HC138_C=1;HC138_B=0;HC138_A=1;break;
case 6:HC138_C=1;HC138_B=1;HC138_A=0;break;
case 7:HC138_C=1;HC138_B=1;HC138_A=1;break;
}
}
(其余用到选择138译码器时,用该函数替换)
改进2:
改进原因:每一次都是选中Y4或Y5,然后对P0的输出进行设置,可进行模块化
改进思路:P0口输出函数,2个参数(信道和数据),其余重复均用该函数替换,整体性好
改进后的代码:(已成型)
#include <REGX52.H>
sbit HC138_A=P2^5;
sbit HC138_B=P2^6;
sbit HC138_C=P2^7;
void Delay(unsigned int t)
{
while(t--);
while(t--);
}
void InitHC138(unsigned char n)
{
switch(n)
{
case 4:HC138_C=1;HC138_B=0;HC138_A=0;break;
case 5:HC138_C=1;HC138_B=0;HC138_A=1;break;
case 6:HC138_C=1;HC138_B=1;HC138_A=0;break;
case 7:HC138_C=1;HC138_B=1;HC138_A=1;break;
}
}
void OutputP0(unsigned char channel,unsigned char dat)
{
InitHC138(channel);
P0=dat;//data是关键字
}
void LEDrunning(void)
{
unsigned char i;
for(i=0;i<3;i++)
{
OutputP0(4,0x00);//选中4信道,打开所有的LED
Delay(60000);
Delay(60000);
OutputP0(4,0xFF);
Delay(60000);
Delay(60000);
}
for(i=1;i<=8;i++)
{
OutputP0(4,(0xFF<<i));
Delay(60000);
Delay(60000);
}
OutputP0(5,0x10); //让继电器吸合,P04=1
Delay(60000);//0x10对应0001 0000,对应P07-P00
Delay(60000);
OutputP0(5,0x00);//关闭所有无关设备
for(i=1;i<=8;i++)
{
OutputP0(4,~(0xFF<<i));
Delay(60000);
Delay(60000);
}
OutputP0(5,0x40); //让P06打开,蜂鸣器开启
Delay(60000);
Delay(60000);
OutputP0(5,0x00); //过一会儿再把蜂鸣器关闭
}
void InitSystem(void)
{
OutputP0(5,0x00);
}
void main()
{
InitSystem();
while(1)
{
LEDrunning();
}
}
改进3:
改进原因:138译码器的高三位不必进行声明、自定义,而可以直接利用&、|操作进行置位,整体赋值
改进思路:直接利用&、|操作进行置位,整体赋值
改进后的代码:(简介版)
void InitHC138(unsigned char n)
{
switch(n)
{
case 4:P2=(P2&0x1F)|0x80;break;//1001 1111 //100->8
case 5:P2=(P2&0x1F)|0xA0;break;//1011 1111 //101->A
case 6:P2=(P2&0x1F)|0xC0;break;//1101 1111 //110->C
case 7:P2=(P2&0x1F)|0xE0;break;//1111 1111 //高三位清零&,|将高三位置值
}
}
感谢B站小蜜蜂老师的教程,本笔记资料及代码均来自教程,仅作为个人复习、整理和学习交流用。