根据论坛里51单片机GSM报警器的程序,写的用遥控器来控制GSM报警器开和关,现在遥控可以打开报警器工作,不能关闭。出现问题的原因应该是在报警程序里出现了死循环没有跳出来,有啥解决思路?单片机源程序如下:
- #include<reg52.h>
- #include <intrins.h>
- #include <absacc.h> //头文件
- #define uint unsigned int
- #define uchar unsigned char //宏定义
- sbit BUZZ=P2^3; //蜂鸣器
- sbit shake=P3^7; //震动传感器
- sbit LED_B=P1^3; //布防指示灯 蓝色
- sbit LED_S=P1^6; //短信指示灯 绿色
- sbit LED_J=P1^0; //报警指示灯 红色
- uchar code PhoneNO[]="13151993977"; //接受号码
- uchar code somebody[]="8BF76CE8610FFF0167094EBA8FDB516562A58B66830356F4FF01"; //请注意!有人进入报警范围!
- uint TIME_50ms=0; //计时的最小分辨率50ms
- uint time_continue; //蜂鸣器鸣响时计时数据暂存
- bit flag=0,flag_BF=0; //flag:值为0时,是布防计时模式,值为1时,是一分钟等待模式。flag_BF:布防标志位
- bit flag_time_start=0; //开始计时标志位
- bit again=0; //一分钟等待标志位(当发送一条短信后,不能马上发送第二天,所以等待一分钟后再检测是否有人,有人再发送短信)
- bit flag_alam; //报警标志位
- bit flag_continue; //继续计时
- sbit IR=P3^2; //红外接口标志
- unsigned char irtime; //红外用全局变量
- bit irpro_ok,irok;
- bit key1,key2; //开关键
- unsigned char IRcord[4];
- unsigned char irdata[33];
- void delay(uint z) //延时函数
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=222;y>0;y--);
- }
- void tim0_isr (void) interrupt 1 //定时器0中断
- {
- irtime++; //用于计数2个下降沿之间的时间
- }
- void EX0_ISR (void) interrupt 0 //外部中断0服务函数 红外接收信号
- {
- static unsigned char i; //接收红外信号处理
- static bit startflag; //是否开始处理标志位
- if(startflag)
- {
- if(irtime<53&&irtime>=32) //引导码 TC9012的头码,9ms+4.5ms
- i=0;
- irdata[i]=irtime; //存储每个电平的持续时间,用于以后判断是0还是1
- irtime=0;
- i++;
- if(i==33)
- {
- irok=1;
- i=0;
- }
- }
- else
- {
- irtime=0;
- startflag=1;
- }
- }
- void Uart_init() //中断初始化
- {
- TMOD |= 0X20; //T1方式2,8位自动重装
- TH1=0Xfd;
- TL1=0Xfd; // 9600波特率
- TR1=1; // 定时器1启动
- SM0=0; // 设置串口的工作模式
- SM1=1; // 方式1
- REN=1; // 允许串口接收数据
- ES=1; // 串口中断应许
- EA=1; // 开启中断
-
- TMOD |= 0X02;
- TH0=0x00; //重载值
- TL0=0x00; //初始化值
- ET0=1; //开中断
- TR0=1;
- IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
- EX0 = 1; //使能外部中断
- }
- void Ir_work(void) //红外键值散转程序
- {
- switch(IRcord[2]) //判断第三个数码值
- {
- case 0x15:key1=0,key2=1;break;//key1 开启 对应按键为+
- case 0x07:key2=0,key1=1;break;//key2 关闭 对应按键为-
- default:break;
- }
- }
- void Ircordpro(void)//红外码值处理函数
- {
- unsigned char i, j, k,cord,value;
- k=1;
- for(i=0;i<4;i++) //处理4个字节
- {
- for(j=1;j<=8;j++) //处理1个字节8位
- {
- cord=irdata[k];
- if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
- value=value|0x80;
- if(j<8)
- {
- value>>=1;
- }
- k++;
- }
- IRcord[i]=value;
- value=0;
- }
- irpro_ok=1;//处理完毕标志位置1
- }
- void SendASC(uchar d) //串口发送字符
- {
-
- SBUF=d; //数据赋值到缓冲区
- while(!TI); //发送完
- TI=0; //清零
- }
- void SendString(uchar *str) //串口发送字符串
- {
- while(*str) //判断是否发送完,不为\0时继续发送
- {
- SendASC(*str) ; //发送字符
- str++; //字符位置加
- delay(1);
- }
- }
- void TIME() //计时函数
- {
- if(flag==0) //布防计时模式
- {
- delay(50); //50ms
- TIME_50ms++; //50ms变量加1
- if(TIME_50ms%10==0) //每500ms(50ms*10)
- LED_B=!LED_B; //布防指示灯取反一次
- if(TIME_50ms>20) //加到20次,也就是50ms*20=5000ms=1s
- {
- TIME_50ms=0; //计时变量清零
- flag_BF=1; //进入布防状态
- LED_B=0; //布防指示灯长亮
- flag_time_start=0; //停止计时
- again=1; //关闭一分钟等待
- }
- }
- else //一分钟等待模式
- {
- delay(50); //50ms
- TIME_50ms++; //变量加
- if(TIME_50ms%10==0) //每加500ms
- {
- LED_B=!LED_B; //布防指示灯闪烁
- if(flag_alam==1) //报警
- {
- if(flag_continue==0) //进入报警时
- {
- flag_continue=1; //此标志位置一,防止报警时进入
- time_continue=TIME_50ms; //将进入报警时的计时数据暂存
- }
- BUZZ=!BUZZ; //蜂鸣器取反,也就是闪烁响
- LED_J=~LED_J;
- if(TIME_50ms>=time_continue+100)//当报警时间达到5s时
- {
- BUZZ=1;
- LED_J=1; //关闭蜂鸣器
- flag_continue=0; //标志位清零,等待下次报警
- flag_alam=0; //报警变量清零,停止报警
- time_continue=0; //暂存计时数据清零
- }
- }
- }
- if(TIME_50ms>=1200) //计时达到60秒
- {
- LED_B=0; //布防指示灯长亮,准备检测热释电信号
- TIME_50ms=0; //计时变量清零
- flag_time_start=0; //停止计时
- again=1; //关闭一分钟等待
- }
- }
- }
- void keyscan() //按键扫描函数
- {
- if(key1==0&&key2==1&&flag_BF==0) //在非布防状态时布防按键按下
- {
- delay(5); //延时去抖
- if(key1==0&&key2==1) //再次判断按键是否按下
- {
- LED_B=0; //点亮布防LED灯
- flag=0; //变量清零
- flag_time_start=1; //开始计时变量置一
- }
- }
- if(flag_time_start==1) //开始计时
- {
- TIME(); //调用计时函数
- }
- if(key1==1&&key2==0) //撤防按键按下
- {
- delay(5); //延时去抖
- if(key1==1&&key2==0) //再次判断按键是否按下
- {
- BUZZ=1; //关闭蜂鸣器
- LED_J=1;
- flag_alam=0; //报警变量清零
- flag_BF=0; //布防变量清零
- flag=0; //变量清零
- flag_time_start=0; //开始计时变量清零
- LED_S=1; //关闭发送短信指示灯
- LED_B=1; //关闭布防指示灯
- }
- }
- }
- void GSM_work() //发送GSM短信
- {
- unsigned char send_number; //定义发送手机号的变量
- if(shake==1&&flag_BF==1) //布防状态且热释电有信号时
- flag_alam=1; //报警变量置一
- if(shake==1&&flag_BF==1&&again==1) //布防状态且热释电有信号时且不在一分钟等待时间内 或者 手动按下紧急按键
- {
- LED_S=0; //打开发送短信指示灯
- BUZZ=0; //打开蜂鸣器
- LED_J=0;
- SendString("AT+CMGF=1\r\n"); //设置文本模式
- delay(1000); //延时,让GSM模块有一个反应时间
- SendString("AT+CSCS=\"UCS2\"\r\n"); //设置短信格式,发送汉字模式
- delay(1000); //延时
- SendString("AT+CSMP=17,167,0,25\r\n");
- delay(1000);
- SendString("AT+CMGS="); //信息发送指令 AT+CMGS=
- SendASC('"'); //引号
- for(send_number=0;send_number<11;send_number++) //在每位号码前加003
- {
- SendASC('0');
- SendASC('0');
- SendASC('3');
- SendASC(PhoneNO[send_number]); //接收手机号码
- }
- SendASC('"'); //引号
- SendASC('\r'); //发送回车指令
- SendASC('\n'); //发送换行指令
- delay(1000); //延时
- SendString(somebody); //发送短信内容
- delay(1000); //延时
- SendASC(0x1a); //确定发送短信
- again=0; //again清零,也就是进入一分钟等待,当计时到一分钟后,该变量重新置一
- flag_time_start=1; //开始计时
- flag_alam=1; //报警
- LED_S=1; //熄灭发送短信指示灯
- flag=1; //变量置一
- }
- }
- void main() //主函数
- {
- Uart_init(); //调用中断初始化函数
- while(1) //进入while循环
- {
- if(irok) //如果接收好了进行红外处理
- {
- Ircordpro(); //红外码值处理函数,处理完成irpro_ok=1
- irok=0;
- }
- if(irpro_ok) //如果处理好后进行工作处理
- {
- Ir_work();
- irpro_ok=0; //处理完成标志
- }
- keyscan(); //按键函数
- GSM_work(); //发送短信函数
- }
- }
复制代码
|