c51单片机利用蜂鸣器与二极管同时工作模拟炸弹倒计时爆炸效果
今天是学习c51单片机的第二天,这两天学习了蜂鸣器的使用与点亮二极管,我想趁着刚刚学习来把他们巩固一下,于是自己折腾了半天写了一个他们同时工作的程序。此程序可以通过二极管闪烁与蜂鸣器一响一响的效果来模拟炸弹倒计时爆炸的效果。
首先,我们来看看我用的开发板(普中51-双核-A7开发板)的蜂鸣器和二极管的原理图(由于开发板上没有专门的发光二极管,于是我用LED&交通灯模块来代替二极管)。
当蜂鸣器J7-1端接低电平时蜂鸣器工作。
下图为开发板实物图。
下面为最后实现的代码
#include<reg51.h>
#define uint unsigned int
void delay(uint z); //延时函数
void fmq(uint a); //蜂鸣器工作函数
void lighton(); //二极管点亮函数
void lightoff(); //二极管熄灭函数
sbit D1 = P1^0; //P1^0引脚接二极管
sbit deep = P0^0; //P0^0引脚接蜂鸣器
void main(){
uint a = 0; //此处a代表二极管闪多少次,即蜂鸣器响多少声
while(1){
for(a = 8; a > 0; a--){
lighton();
fmq(500);
lightoff();
delay(50000); //50000代表每一次闪间隔的相对时长,由于时间关系,没有严格模拟正确的时间
}
for(a = 10; a > 0; a--){
lighton();
fmq(500);
lightoff();
delay(20000);
}
for(a = 20; a > 0; a--){
lighton();
fmq(500);
lightoff();
delay(5000);
}
for(a = 20000; a > 0; a--){ //此循环代表最后蜂鸣器一直在工作,中间没有间隔,而二极管不在工作
deep = 0; //该循环未用fmq()函数,因为此处蜂鸣器要连续工作,而不是一响一响的工作
delay(5);
deep = 1;
delay(5);
}
}
}
void delay(uint z){
while(z--);
}
void fmq(uint a){ //a代表蜂鸣器响的相对时长
while(a) {
deep = 0;
delay(5);
deep = 1;
delay(5);
a-- ;
}
}
void lighton(){
D1 = 0;
}
void lightoff(){
D1 = 1;
}
//用我的开发板实现程序后,整个程序大约为12s
总结:一开始的思路是在一个大循环里先调用fmq()函数和light()函数(点亮二极管的函数),然而问题是他俩无法同时进行,即蜂鸣器响完之后二极管才发光,效果不好,于是便直接使用lighton()与lightoff()两个函数,分别在蜂鸣器工作前后调用,实现二极管与蜂鸣器同时工作。
错误分析:在此之前我为把蜂鸣器工作列入一个函数里,部分错误代码如下:
deep = ~deep;
delay(10);
D1 = 0;
delay(50000)
此代码不仅不能让蜂鸣器正常工作,也不能实现二极管的闪烁。
于是我将蜂鸣器工作的实现单独写进一个函数里:
void fmq(){
deep = ~deep;
delay(10);
}
此时主函数里面为:
void main(){
fmq();
D1 = 0;
delay(50000);
D1 = 1;
delay(50000);
}
利用此代码烧进开发板后,发现蜂鸣器没法发出声音,只是很沉接近无声的声音,代表蜂鸣器不能正常工作。思考之后,发现除了fmq()函数中的延迟函数外,蜂鸣器还会经过一个主函数中的delay()函数,于是导值蜂鸣器高低电平之间的变换太慢,导值蜂鸣器不能正常工作。
解决以上两种问题的办法就是不在主函数中加延迟,而是在fmq()中加延迟,可以控制每次响多长时间,而主函数主要控制能响多少次,并且让二极管与蜂鸣器同时工作,以及每次闪烁间隔的时间。此时,虽然主函数中仍有延迟函数,但是并不影响fmq()函数,因为fmq()函数调用运行完之后,才允许之函数中的延迟函数,所以并不影响蜂鸣器正常工作。当仔细思考后,写出了上面正确的可以实现的代码。
关于这个程序有问题的可以在评论里问,我会尽力为大家解答哒!