根據論壇里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(); //發送短信函數
- }
- }
復制代碼
|