请帮我看看是这个程序有问题还是我单片机连线有问题?
现在我只能实现功能A。 B实现不了。但是我检查好久没看出来程序错在哪里了,请帮我看看,谢谢
火焰传感器和声音传感器都是低电平有效,都可以直接接单片机。
//我的思路; //"打火机靠近火焰传感器模块一次"使进入“led灯一直亮”和“蜂鸣器循环放歌”两个中断
//"随时向声音传感器模块吹一口气" 使退出“led灯一直亮”和“蜂鸣器循环放歌”两个中断
//由主函数中断进入“led灯一直亮”和“蜂鸣器循环放歌”两个部分。
//在中断1中不断检查是否有吹气声音
//led用P1.0,1.1口
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P2^3; //蜂鸣器
sbit fire_sensor=P3^0;//定义火焰传感器管脚
sbit sound_sensor=P3^1; //定义声音传感器管脚。
uchar code SOUNDLONG[]= //控制音调
{
18,6,24,24,24,48,
18,6,24,24,24,48,
18,6,24,24,24,24,24,
18,6,24,24,24,48,0
};
uchar code SOUNDTONE[]= //控制音色
{
212,212,190,212,159,169,
212,212,190,212,142,159,
212,212,106,126,159,169,190,
119,119,126,159,142,159,0 //生日快乐end
};
void delay(uint z);
void Play_Music();
void Music(uchar number);
void delay10us(uchar time);
void delay50us(uchar time);
void main()
{
uint x=60000,y=110; //60秒内检测是否有热源,开机超过60秒不再检测
TH0=(65536-50000)/256; //两个定时器的初值可任意设置
TL0=(65536-50000)%256;
TH1=(65536-50000)/256; //两个定时器的初值任意设置可
TL1=(65536-50000)%256;
EA=1;
ET0=1;
ET1=1;
for(;x>0;x--)
for(;y>0;y--)
{
if(fire_sensor==0) //如果有热源
{
TR0=1;
TR1=1; //开启定时器T0,T1
}
}
}
void light() interrupt 1
{
TR0=0;
TH0=(65536-65000)/256;
TL0=(65536-65000)%256;
P1=0xfc; //1111 1000
delay(1);
if(sound_sensor==0) //如果有声音(吹气)
{
TR0=0;
TR1=0;
P1=0xff; //关掉led
BEEP=1;//关蜂鸣器
delay(1000); //延时
}
TR0=1;
}
void sound() interrupt 3
{
TR1=0;
while(1)
{
Play_Music(); //生日快乐
delay10us(250);
}
TR1=1;
}
void Play_Music()
{
uint k,n;
uint SoundLong,SoundTone;
uint i,j,m;
do
{
if(i>=25) i=0;
SoundLong=SOUNDLONG[i];
SoundTone=SOUNDTONE[i];
i++;
for(n=0;n<SoundLong;n++)
{
for(k=0;k<12;k++)
{
BEEP=0;
for(m=0;m<SoundTone;m++);
BEEP=1;
for(m=0;m<SoundTone;m++);
}
}
delay50us(6);
}while((SOUNDLONG[i]!=0)||(SOUNDTONE[j]!=0));
}
void delay50us(uchar time)
{
uchar a,b;
for(a=0;a<time;a++)
for(b=0;b<6;b++);
}
void delay10us(uchar time)
{
uchar a,b,c;
for(a=0;a<time;a++)
for(b=0;b<10;b++)
for(c=0;c<120;c++);
}
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
兄弟,你这程序有很大问题,在中断中运行长时间程序,然后这么简单的程序居然用了2个中断,中断不是这样用的
逻辑容易混乱。当然你写这程序是为了连续中断用法那又是另外一回事了
unsigned char Play_Music()
{
uint k,n;
uint SoundLong,SoundTone;
uint i,j,m;
do
{
if(i>=25) i=0;
SoundLong=SOUNDLONG[i];
SoundTone=SOUNDTONE[i];
i++;
for(n=0;n<SoundLong;n++)
{
for(k=0;k<12;k++)
{
BEEP=0;
for(m=0;m<SoundTone;m++);
BEEP=1;
for(m=0;m<SoundTone;m++);
}
}
delay50us(6);
if(sound_sensor==0) //如果有声音(吹气)
{
return 1;
}
}while((SOUNDLONG[i]!=0)||(SOUNDTONE[j]!=0));
return 0
}
void delay50us(uchar time)
{
uchar a,b;
for(a=0;a<time;a++)
for(b=0;b<6;b++);
}
void main()
{
uint x=60000,y=110; //60秒内检测是否有热源,开机超过60秒不再检测
for(;x>0;x--)
for(;y>0;y--)
{
if(fire_sensor==0) //如果有热源
{
P1=0x00; //开led
while(1)
{
if( Play_Music()) //一直生日快乐直到吹气退出
{
P1=0xff; //关掉led
BEEP=1;//关蜂鸣器
break;
}
}
break;//跳出检测
}
}
while(1);
}
下面没有注释的语句都是些放歌啊,延时啊什么的,应该不会错在那里,
没注意打错了,main中初值和中断中初值都是50000,中断中初值不是65000
修改了一下,重发一次
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P2^3; //蜂鸣器
sbit fire_sensor=P3^0;//定义火焰传感器管脚
sbit sound_sensor=P3^1; //定义声音传感器管脚。//有时得要定义全局变量 ,用于控制是否进入中断
uchar code SOUNDLONG[]= //控制音调
{
18,6,24,24,24,48,
18,6,24,24,24,48,
18,6,24,24,24,24,24,
18,6,24,24,24,48,0
};
uchar code SOUNDTONE[]= //控制音色
{
212,212,190,212,159,169,
212,212,190,212,142,159,
212,212,106,126,159,169,190,
119,119,126,159,142,159,0 //生日快乐end
};
void delay(uint z);
void Play_Music();
void Music(uchar number);
void delay10us(uchar time);
void delay50us(uchar time);
void main()
{
uint x=60000,y=110; //60秒内检测是否有热源
TH0=(65536-50000)/256; //两个定时器的初值随便,反正只进一次中断且进中断后延时液与定时器无关
TL0=(65536-50000)%256;
TH1=(65536-50000)/256; //两个定时器的初值随便,反正只进一次中断且进中断后延时液与定时器无关
TL1=(65536-50000)%256;
EA=1;
ET0=1;
ET1=1;
for(;x>0;x--)
for(;y>0;y--)
{
if(fire_sensor==0) //如果有热源
{
TR0=1;
TR1=1; //开启定时器T0,T1
}
}
}
void light() interrupt 1
{
TR0=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
P1=0xfc; //1111 1000
delay(1); //延时多少秒有待测试,根据音乐定,音乐大约33秒 //但是后来发现中断执行是有先后顺序的,就像语句一样,中断1第一遍执行完了之后才会开始执行中断2的第一遍
if(sound_sensor==0) //如果有声音 //在中断1或3里面检测是否应该关灯与停止放音乐,而不是在main中,因为main函数这部分语句只执行一次,可能等不到有声音就执行过去了
{
TR0=0;
TR1=0;
P1=0xff;//关掉led
BEEP=1;
delay(1000);
}
TR0=1;
}
void sound() interrupt 3
{
TR1=0;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
while(1)
{
Play_Music(); //生日快乐
delay10us(250);
}
TR1=1;
// if(sound_sensor==0) //如果有声音 //在中断1或3里面检测是否应该关灯与停止放音乐,而不是在main中,因为main函数这部分语句只执行一次,可能等不到有声音就执行过去了
// {
// P1=0xff;//关掉led
// EA=0;
// delay(1);
// }
}
void Play_Music()
{
uint k,n;
uint SoundLong,SoundTone;
uint i,j,m;
do
{
if(i>=25) i=0;
SoundLong=SOUNDLONG[i];
SoundTone=SOUNDTONE[i];
i++;
for(n=0;n<SoundLong;n++)
{
for(k=0;k<12;k++)
{
BEEP=0;
for(m=0;m<SoundTone;m++);
BEEP=1;
for(m=0;m<SoundTone;m++);
}
}
delay50us(6);
}while((SOUNDLONG[i]!=0)||(SOUNDTONE[j]!=0));
}
void delay50us(uchar time)
{
uchar a,b;
for(a=0;a<time;a++)
for(b=0;b<6;b++);
}
void delay10us(uchar time)
{
uchar a,b,c;
for(a=0;a<time;a++)
for(b=0;b<10;b++)
for(c=0;c<120;c++);
}
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
能给图看看吗
第一张是板子和传感器整个
这是单片机左边接线
这是右边接线
上面是声音传感器,下面是火焰传感器。
谢谢,看懂了,确实不用中断,下载好后没问题了。我写太复杂了。
已解决,下面是完整程序。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P2^3; //蜂鸣器
sbit fire_sensor=P3^0;//定义火焰传感器管脚
sbit sound_sensor=P3^1; //定义声音传感器管脚。
void delay50us(uchar time);
uchar code SOUNDLONG[]= //控制音调
{
18,6,24,24,24,48,
18,6,24,24,24,48,
18,6,24,24,24,24,24,
18,6,24,24,24,48,0
};
uchar code SOUNDTONE[]= //控制音色
{
212,212,190,212,159,169,
212,212,190,212,142,159,
212,212,106,126,159,169,190,
119,119,126,159,142,159,0 //生日快乐end
};
unsigned char Play_Music()
{
uint k,n;
uint SoundLong,SoundTone;
uint i,j,m;
do
{
if(i>=25) i=0;
SoundLong=SOUNDLONG[i];
SoundTone=SOUNDTONE[i];
i++;
for(n=0;n<SoundLong;n++)
{
for(k=0;k<12;k++)
{
if(sound_sensor==0) //如果有声音(吹气)
{
return 1;
}
BEEP=0;
for(m=0;m<SoundTone;m++);
BEEP=1;
for(m=0;m<SoundTone;m++);
}
}
delay50us(6);
if(sound_sensor==0) //如果有声音(吹气)
{
return 1;
}
}
while((SOUNDLONG[i]!=0)||(SOUNDTONE[j]!=0));
return 0;
}
void delay50us(uchar time)
{
uchar a,b;
for(a=0;a<time;a++)
for(b=0;b<6;b++);
}
void main()
{
uint x,y; //60秒内检测是否有热源,开机超过60秒不再检测
for(x=60000;x>0;x--)
for(y=110;y>0;y--)
{
if(fire_sensor==0) //如果有热源
{
P1=0x00; //开led
while(1)
{
if( Play_Music()) //一直生日快乐直到吹气退出
{
P1=0xff; //关掉led
BEEP=1;//关蜂鸣器
break;
}
}
break;//跳出检测
}
}
while(1);
}
原来那个版本音乐难听,现在修改了音乐,比较和听,重发一下。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P2^3; //蜂鸣器
sbit fire_sensor=P3^0;//定义火焰传感器管脚
sbit sound_sensor=P3^1; //定义声音传感器管脚。
sbit light_sensor=P3^2;//定义光电传感器管脚
//生日快乐歌的音符频率表,不同频率由不同的延时来决定
uchar code SONG_TONE[]=
{
212,212,190,212,
159,169,212,212,
190,212,142,159,
212,212,106,126,
159,169,190,119,
119,126,159,142,
159,0
};
//生日快乐歌节拍表,节拍决定每个音符的演奏长短
uchar code SONG_LONG[]=
{
9,3,12,12, //9,3,12,12
12,24,9,3, //12,24,9,3
12,12,18,24, //12,12,12,24
10,4,20,20, //9,3,12,12
19,14,14,12, //12,12,12,9
8,16,16,16, //3,12,12,12
24,0 //24,0
};
void DelayMS(uint x)
{
uchar t;
while(x--)
{
for(t=0;t<80;t++); //播放函数 yuanlai s 120
}
}
uint PlayMusic() //大改
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{
//播放各个音符,SONG_LONG 为拍子长度
for(j=0;j<SONG_LONG[i]*30;j++) //20
{
if(sound_sensor==0)
{
P1=0xff;
BEEP=1;
return 1; //return 1?
}
BEEP=~BEEP;
//SONG_TONE 延时表决定了每个音符的频率
for(k=0;k<SONG_TONE[i]/3;k++) ; //3
}
DelayMS(30);//yuanlai s 10
i++;
}
return 0; //return 0?
}
//光电传感器要实现的功能:在有光(光太强)时不能点亮蜡烛,在无光(弱光)时可以点亮蜡烛
void main()
{
while(1)
{
if((fire_sensor==0)&&(light_sensor==1)) //如果有热源,且没光(或弱光)
{
P1=0x00; //开led
while(1)
{
if( PlayMusic()) //一直生日快乐直到吹气退出
{
P1=0xff; //关掉led
BEEP=1;//关蜂鸣器
break;
}
}
//break是跳出最近的循环
}
}
}
串口那块不太懂,想问下,下面是书上程序
uchar readbyte()
{
uchar i,k;
SCL=0;
delay();
SDA=1;
for(i=0;i<8;i--)
{
SCL=1;
delay();
k=(k<<1)|SDA;//这一句看不懂,不知道为什么就能完成8位的接收
SCL=0;
delay();
}
delay();
return k;
}
书上的解释是:串行接收一个字节时需要将8位一位一位地接收,然后再组合成一个字节,上面代码中我们定义了一个临时变量k,将k左移一位后与SDA进行“或”运算,依次把8个独立的位放入一个字节中来完成接收。
它为什么要k<<1之后与SDA1 按位或?怎么完成把8位放入一个字节? 这个字节放入了谁中?