要完成的功能是每分鐘發送一次短信,除了發短信的時候,其他時候能夠通過遙控器控制電機。現在出現問題:GSM第一次發短信之前遙控器正常使用,發過短信之后紅外不能使用或者出現亂碼等異常情況
有沒有人能幫我看看代碼!!!(╥╯^╰╥)
- #include<reg51.h>
- #include <reg51.h> //調用單片機頭文件
- #define uchar unsigned char //無符號字符型 宏定義 變量范圍0~255
- #define uint unsigned int //無符號整型 宏定義 變量范圍0~65535
- #include <intrins.h> //包含_nop_()函數定義的頭文件
- #define FOSC_110592M //單片機的晶振大小
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- typedef unsigned int u16; //對數據類型進行聲明定義
- typedef unsigned char u8;
- sbit beep=P3^3;
- sbit dianji=P1^6;
- uint8 irtime; //接收時間
- uint8 startflag; //開始檢測
- uint8 bitnum; //bit位數
- uint8 irdata[33]; //寄存沒有個bit的時間
- uint8 irreceok; //接收完成標志位
- uint8 ircode[4]; //將接收的四個字節數據保存
- uint8 irprosok; //接收數據處理標志位
- sbit rs=P1^0; //1602數據/命令選擇引腳 H:數據 L:命令
- sbit rw=P1^1; //1602讀寫引腳 H:數據寄存器 L:指令寄存器
- sbit e =P1^2; //1602使能引腳 下降沿觸發
- //GSM發送短信
- uchar text[9]="shidu:00%";
- uchar SIM_text[];//GSM接線:5VT==P3.0 5VR==P3.1
- /********************************************************************
- * 名稱 : Delay_uint()
- * 功能 : 小延時。
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void Delay_uint(uint q)
- {
- while(q--);
- }
- /***********************1ms延時函數*****************************/
- void Delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<120;j++);
- }
- /***********************LCD1602程序*****************************/
- /********************************************************************
- * 名稱 : LCD_write_com(uchar com)
- * 功能 : 1602命令函數
- * 輸入 : 輸入的命令值
- * 輸出 : 無
- ***********************************************************************/
- void LCD_write_com(uchar com)
- {
- e=0;
- rs=0;
- rw=0;
- P0=com;
- Delay_uint(3);
- e=1;
- Delay_uint(25);
- e=0;
- }
- /********************************************************************
- * 名稱 : LCD_write_data(uchar dat)
- * 功能 : 1602寫數據函數
- * 輸入 : 需要寫入1602的數據
- * 輸出 : 無
- ***********************************************************************/
- void LCD_write_data(uchar dat)
- {
- e=0;
- rs=1;
- rw=0;
- P0=dat;
- Delay_uint(3);
- e=1;
- Delay_uint(25);
- e=0;
- }
- /********************************************************************
- * 名稱 : LCD_string(uchar hang,uchar add,uchar *p)
- * 功能 : 改變液晶中某位的值,如果要讓第一行,第五個字符開始顯示"ab cd ef" ,調用該函數如下
- LCD_string(1,5,"ab cd ef;")
- * 輸入 : 行,列,需要輸入1602的數據
- * 輸出 : 無
- ***********************************************************************/
- void LCD_string(uchar hang,uchar add,uchar *d)
- {
- if(hang==1)
- LCD_write_com(0x80+add);
- else
- LCD_write_com(0x80+0x40+add);
- while(1)
- {
- if(*d == '\0')
- break;
- LCD_write_data(*d);
- d++;
- }
- }
- /********************************************************************
- * 名稱 : init_1602()
- * 功能 : 初始化1602液晶
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void init_1602()
- {
- LCD_write_com(0x38); //初始化
- LCD_write_com(0x0c);
- LCD_write_com(0x06);
- LCD_write_com(0x01);
- Delay_uint(100); //延時
- }
- void int0init()
- {
- EA=1;
- EX0=1;
- IT0=1;
- }
- void time0init()
- {
- TMOD=0X02; //設置定時器0模式2.該模式為自動裝載模式
- TH0=0X00;
- TL0=0X00;//設定計數初值,每當TL0計數到255時,TH0將把自己的數據給TL0,又重新計數
- TR0=1;
- ET0=1;
- EA=1;
- }
- void irpros() //紅外接收數據處理 ,區分是數據0還是1
- {
- uint8 i,j,value;
- uint8 k=1; //引導碼去掉,所以令k=1;
- for(j=0;j<4;j++) //取出了一幀數據中的四個字節數據
- {
- for(i=0;i<8;i++) //取出了一個字節的數據
- {
- value>>=1;
- if(irdata[k]>6)
- {
- value=value|0x80;
- }
- k++;
- }
- ircode[j]=value;
- }
- irprosok=1;
- }
- void motopros()
- {
- if(ircode[2]==0x0c) //按下第一次按鍵開電機
- {
- beep=~beep;
- dianji=0;
- Delay_1ms(100);
- }
- else if(ircode[2]==0x18) //按下第二次此按鍵時關閉電機
- {
- beep=1;
- dianji=1;
- }
- if(ircode[2]==0x5e)
- {
- //Gsm_send(2);
- }
- }
- /*******************GSM*************************/
- //注意,無論接收到信號還是發送完信號,都會進中斷服務程序的
- /*初始化程序(必須使用,否則無法收發),次程序將會使用定時器1*/
- void GSM_inti()//初始化程序(必須使用,否則無法收發)
- {
- TMOD=0x20;//定時器1操作模式2:8位自動重載定時器
- #ifdef FOSC_12M //在這里根據晶振大小設置不同的數值初始化串口
- TH1=0xf3;//裝入初值,波特率2400
- TL1=0xf3;
- #else
- TH1=0xfd;//裝入初值,波特率9600
- TL1=0xfd;
- #endif //end of SOC_12M
-
- TR1=1;//打開定時器
- SM0=0;//設置串行通訊工作模式,(10為一部發送,波特率可變,由定時器1的溢出率控制)
- SM1=1;//(同上)在此模式下,定時器溢出一次就發送一個位的數據
- REN=1;//串行接收允許位(要先設置sm0sm1再開串行允許)
- EA=1;//開總中斷
- ES=1;//開串行口中斷
- }
- /*串行通訊中斷,收發完成將進入該中斷*/
- void Serial_interrupt() interrupt 4
- {
- // a=SBUF;
- P2=SBUF;
- RI=0;//接收中斷信號清零,表示將繼續接收
- // flag=1;//進入中斷的標志符號
- }
- void Uart1Send(uchar c)
- {
- SBUF=c;
- while(!TI);//等待發送完成信號(TI=1)出現
- TI=0;
- }
- //串行口連續發送char型數組,遇到終止號/0將停止
- void Uart1Sends(uchar *str)
- {
- while(*str!='\0')
- {
- SBUF=*str;
- while(!TI);//等待發送完成信號(TI=1)出現
- TI=0;
- str++;
- }
- }
- //延時函數大概是1s鐘,不過延時大的話不準...
- void DelaySec(int sec)
- {
- uint i , j= 0;
- for(i=0; i<sec; i++)
- {
- for(j=0; j<65535; j++)
- {
- }
- }
- }
- void Gsm_send()
- {
- Uart1Sends("AT+CSCS=\"GSM\"\r\n");
- DelaySec(3);//延時3秒
- Uart1Sends("AT+CMGF=1\r\n");
- DelaySec(3);//延時3秒
- Uart1Sends("AT+CMGS=\"17338711000\"\r\n");//此處修改為對方的電話號
- DelaySec(5);//延時3秒
- Uart1Sends(text);//修改短信內容
- Uart1Send(0x1a);
- //DelaySec(13);//延時20秒
- }
- void main()
- {
- int k;
- init_1602();
- int0init();
- time0init();
- while(1)
- {
- irpros();
- motopros();
- if(k==12000)
- {
- LCD_string(1,12,"ing");
- GSM_inti();
- Gsm_send();
- beep=~beep;
- Delay_1ms(100);
- k=0;
- }
- else
- {
- LCD_string(1,12,"no ");
- k++;
- }
-
- }
- }
- void time0() interrupt 1
- {
- irtime++;//每進來一次就說明定時時間為256us;
- }
- void init0() interrupt 0
- {
- if(startflag)
- {
- if(irtime>32)//檢測引導碼,求法是用引導碼時間除以一次計數時間,看看要多少次
- {
- bitnum=0;
- }
- irdata[bitnum]=irtime;
- irtime=0;
- bitnum++;
- if(bitnum==33)
- {
- bitnum=0;
- irreceok=1;//一幀紅外數據接收完成標志
- }
- }
- else
- {
- startflag=1;//將開始標志位置1,等到下次進入中斷即可進入if語句
- irtime=0;//將開始之前的計數器時間清零。等到下次進入中斷的時候才是引導碼真正的時間
- }
- }
復制代碼
|