可以发现两个电路一端都接着VCC,所以我们只要给另一端接上低电平就可以让蜂鸣器和继电器进行工作。与操作LED类似,只不过换了一个74HC573进行控制。一样的只需要操作P00~P07、P27、P26、P25这几个IO口。
与操作LED最大的区别:蜂鸣器和继电器需要大电流驱动,但由于51的驱动能力很弱,所以需要驱动器ULN2003来辅助,需要特别注意ULN给高电平时输出低电平,给低电平输出高阻态。所以当我们向打开蜂鸣器时,需要令P06=1,而不是P06=1,因为ULN进行了一次反向
。
#include <stc15.h>
#include <intrins.h>
/*
num从4到7,分别对应
4:LED灯
5:蜂鸣器、继电器、电机
6:数码管段选
7:数码管位选
*/
void Delay1000ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void selectHC573(unsigned char num)
{
switch(num)
{
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;
case 0:
P2=(P2 & 0x1f) | 0x00;
break;
}
}
void all_Led_Blink()
{
int i;
selectHC573(4);
for(i=0;i<3;i++)
{
P0=0x00;
Delay1000ms();
P0=0xff;
Delay1000ms();
}
}
void system_Init()
{
selectHC573(5);
P0=0x00;
}
void led_low2high()//LED从低位亮到高位
{
char i=0;
selectHC573(4);
for(i=0;i<8;i++)
{
P0=(0xfe<<i); //1111 1110
Delay1000ms();
}
}
void led_high2low()//LED从高位亮到低位
{
char i=0;
selectHC573(4);
for(i=0;i<8;i++)
{
P0=(0x7f>>i); //0111 1111
Delay1000ms();
}
selectHC573(0); // 关闭控制LED的573
}
void relay_holdon()
{
selectHC573(0); //在操作不同模块时,先失能所有573的LE
P0=~0xef; //1110 1111,在打开模块对应的573之前设置好P0口,避免先前模块的P0口数据传进来
selectHC573(5);
Delay1000ms();
P0=~0xff;
selectHC573(0); //关闭此模块对应的573数据通道
}
void buzz_holdon()
{
selectHC573(0); //在操作不同模块时,先失能所有573的LE
P0=~0xbf; //1011 1111,在打开模块对应的573之前设置好P0口,避免先前模块的P0口数据传进来
selectHC573(5);
Delay1000ms();
P0=~0xff;
selectHC573(0); //关闭此模块对应的573数据通道
}
void main(){
system_Init();
while(1)
{
all_Led_Blink();
relay_holdon();
led_low2high();
buzz_holdon();
}
}
没啥可解析的,看注释就好了,想到你们不会去认真看上面的代码注释,这里拖出来提醒你们看一下。😛
void relay_holdon()
{
selectHC573(0); //在操作不同模块时,先失能所有573的LE
P0=~0xef; //1110 1111,在打开模块对应的573之前设置好P0口,避免先前模块的P0口数据传进来
// 由于ULN2003的反向作用,所以需要我们软件在进行一次反向操作,当然你们可以P0=0x10,我比较喜欢上面的方式。
selectHC573(5);
Delay1000ms();
P0=~0xff; //反向操作符~
selectHC573(0); //关闭此模块对应的573数据通道
}