本节是接着上节讲的,可以先看本节,如果不懂可以去蓝桥杯单片机比赛学习:1、led点亮原理_Do My Best的博客-CSDN博客
看一下基本原理。 也可以去我的主页看一下整个蓝桥杯的章节Do My Best的博客_CSDN博客-蓝桥杯单片机比赛学习,sim800c模块领域博主
蜂鸣器和继电器的基本原理:
如图1,图2为继电器的部分电路图,图1中的m2连接图2中的m2,当继电器吸合时GND、K1、m2、L10、VCC组成完整电路使得继电器LED点亮。那什么时候吸合呢?图2中的RELAY-SPDT是一个有磁性的线圈,当N_RELAY为低电平0的时候组成完整的电路使线圈有磁性,从而吸合继电器。
如图3所示,为蜂鸣器的部分电路图 ,当图中的N_BUZZ为低电平时,蜂鸣器发出响声。
上面图2中的N_RELAY和图3中的N_BUZZ连接图4中的ULN2003达林顿管,可能你这里不理解ULN2003,我们也不需要详细理解,我们只需要知道这里是取反的作用(输入1输出0或者输入0输出1)。(图5是达林顿管的内部电路图,它的内部是由多个非门组成的电路)。接着向前是一个573锁存器,只要LE(Y5C)为高电平1锁存器导通,此处就不再详细讲如有不懂请去上一节蓝桥杯单片机比赛学习:1、led点亮原理_Do My Best的博客-CSDN博客
J13中的WR为低电平0,要使Y5C为高电平1则Y5为低电平0。Y5与图7中的138译码器的输出端相连,要使Y5为低电平0就要选中Y5,则输入P27/P26/P25就要为101。到此整个继电器和蜂鸣器的原理到此结束,下面按上述原理写代码。
代码实现:
实现每500ms LED闪烁3下、继电器吸合三下、蜂鸣器响三下 循环,此处代码注释很重要!
#include "stc15f2k60s2.h"
/* 选择通道并且输入数据 */
void slect_138_573(unsigned char channel, unsigned char dat)
{
P0 = 0x00; /* 将原来P0口中的数据清0 */
P0 = dat; /* 这里用P0而不用其他端口是因为我们操作LED、数码管、继电器、蜂鸣器都是对P0进行操作 */
switch(channel) /* 选择通道 */
{
case 4: /* 使Y4输出低电平0,也就是操作LED */
P2 = (P2 & 0x1f) | 0x80; /* (P2 & 0x1f)就是将前3位清0,再操作前3位。将0x80转为2进制1000 0000,这里只看前3位100就是Y4 */
break;
case 5: /* 使Y5输出低电平0,也就是操作继电器和蜂鸣器 */
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6: /* 使Y6输出低电平0,也就是操作8个数码管 */
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7: /* 使Y7输出低电平0,也就是操作8个数码管中的1个数码管显示值 */
P2 = (P2 & 0x1f) | 0xe0;
break;
case 0: /* 关闭所有通道 */
P2 = (P2 & 0x1f) | 0x00;
break;
}
P2 = (P2 & 0x1f) | 0x00; /* 使用后,关闭所有通道 */
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay(int time)
{
while(time--)
{
Delay1ms();
}
}
void summing(void)
{
char i;
/* LED闪烁三次 */
for(i=0;i<3;i++)
{
slect_138_573(4, 0x00); //打开LED灯
delay(500);
slect_138_573(4, 0xff); //关闭LED灯
delay(500);
}
/* 继电器吸合三次 */
for(i=0;i<3;i++)
{
slect_138_573(5, 0x10); //打开继电器 P0^4==0x10(0001 0000)
delay(500);
slect_138_573(5, 0xaf); //关闭继电器和蜂鸣器(必须同时关掉,会相互影响)0xaf(1010 1111),P0端口其它位不变,只将P0^4清0、P0^6清0
delay(500);
}
/* 蜂鸣器闪烁三次 */
for(i=0;i<3;i++)
{
slect_138_573(5, 0x40); //打开蜂鸣器 P0^6==0x40(0100 0000)
delay(500);
slect_138_573(5, 0xaf); //关闭继电器和蜂鸣器(必须同时关掉,会相互影响)
delay(500);
}
}
void main()
{
slect_138_573(0,0x00);
while(1)
{
summing();
}
}
扩展知识——位操作 很重要!!!
1.把变量的某位清零
把变量a 的某一位清零,且其它位不变。
若设 a=1111 1111,进行如下操作
a &= ~(1<<3)
则a = 1111 0111
a 的 bit3 位被置零,而其它位不变
2.把变量的某几个连续位清零
把变量a 的某几个连续位清零,且其它位不变。
若设 a=1111 1111,进行如下操作
连续两位清0:a &= ~(3<<3) 3在2进制中就是11,则a = 1110 0111
a 的 bit3、bit4 位被置零,而其它位不变
连续三位清0:a &= ~(7<<3) 7在2进制中就是111,则a = 1100 0111
a 的 bit3、bit4、bit5 位被置零,而其它位不变
....
3.对变量的某几位进行赋值
把变量a 的某几位赋值,且其它位不变。
若设 a=0000 0000,进行如下操作
例1:a |= (1<<3) 则a = 0000 1000
a 的 bit3 位被置1,而其它位不变
例2:a |= 0x55 则a = 0101 0101
a 的 bit0、bit2、bit4、bit6 位被置1,而其它位不变
4.对变量的某位取反
某个位进行取反操作,即 1 变 0 , 0 变 1,这可以直接用如下操作,其它位不变。
若设 a=0000 0000,进行如下操作
a ^=(1<<3) 则a = 0000 1000
a 的 bit3 位取反,而其它位不变
后续模块更新中。。。