通過GSM模塊發送經緯度求救信息。

  • 2020 年 4 月 17 日
  • 筆記

本博客作為實驗筆記,僅供學習交流。(轉載請註明出處)

本實驗通過GSM模塊:SIM900a,實現向特定手機發送sos求救信號,並且利用GPS模塊:微科VK2828U7G5LF,將經緯度信息同時發送到手機中。目前已經實現通過串口2發送短訊到手機,通過串口3實現接受gps數據並解析至單片機(串口1已預留其他功能)。

本實驗的不足之處:由於接收的衛星數越多,GPS信號越精確,定位誤差越小,下一步打算通過一些算法實現gps經緯度定位的高精確度。

  1 #include <stc15wxx.h>
  2 #include <string.H>
  3 #include <intrins.h>
  4 #define uchar unsigned char
  5 #define uint unsigned int
  6 
  7 
  8 void Uart2Init();
  9 void Uart2Sends(uchar *str);
 10 void Uart2BYTE(uchar temp);
 11 uchar hand(uchar *ptr);
 12 void clear_rec_data();
 13 void DelaySec(int sec);
 14 uchar rec_data[40];//GSM模塊返回數據數組
 15 uchar rec_num;
 16 void Uart3Init();
 17 uchar rec_gpsdata[51]={0};//Gps模塊返回數據數組
 18 uchar rec_gpsnum=0;
 19 uchar ok[]=",A,";
 20 uchar gpsdata[17]={0};
 21 uchar tn,p,gps_ok=0;
 22 long tm;
 23 
 24 void Init ()
 25 {
 26         P0M1 = 0x00;   P0M0 = 0x00;           //設置為準雙向口
 27     P1M1 = 0x00;   P1M0 = 0x00;           //設置為準雙向口
 28     P3M1 = 0x00;   P3M0 = 0x00;           //設置為準雙向口
 29 }
 30 //串行口連續發送char型數組,遇到終止號/0將停止
 31     void Uart1Init(void)        //[email protected]
 32 {
 33     SCON = 0x50;        //8位數據,可變波特率
 34     AUXR |= 0x01;        //串口1選擇定時器2為波特率發生器
 35     AUXR |= 0x04;        //定時器2時鐘為Fosc,即1T
 36     T2L = 0xE0;        //設定定時初值
 37     T2H = 0xFE;        //設定定時初值
 38     AUXR |= 0x10;        //啟動定時器2
 39     EA=1;//開總中斷
 40     ES=1;//開串行口中斷
 41 }
 42 
 43 void Uart1Sends(uchar *str)
 44 {
 45     while(*str!='\0')
 46     {
 47         SBUF=*str;
 48         while(!(SCON & 0x02));//等待發送完成信號(TI=1)出現
 49         SCON &= ~0x02;         // 清中斷標誌
 50         str++;
 51     }
 52 }
 53 
 54 void main()
 55 {
 56     uchar i=0;
 57     Init();
 58     Uart1Init();
 59     Uart2Init();
 60     Uart3Init();
 61     gps_ok=0;
 62     
 63     while(1) 
 64     {
 65         if(strstr(rec_gpsdata,ok)>0)//串口3GPS數據解析********************************************************************************************************
 66         {
 67                 gpsdata[0]=rec_gpsdata[7];    //緯度解析
 68                 gpsdata[1]=rec_gpsdata[8];
 69                 gpsdata[2]='.';
 70                 tm=(10000*(rec_gpsdata[9]-0x30)+1000*(rec_gpsdata[10]-0x30)+100*(rec_gpsdata[12]-0x30)+10*(rec_gpsdata[13]-0x30)+(rec_gpsdata[14]-0x30))/6;
 71                 gpsdata[3]=tm/1000+0x30;    //更新數據接口數據
 72                 gpsdata[4]=(tm%1000)/100+0x30;
 73                 gpsdata[5]=(tm%100)/10+0x30;
 74             if(tm%10==9)
 75                 gpsdata[6]=tm%10+0x30;
 76             else gpsdata[6]=tm%10+0x31;
 77                 gpsdata[7]=',';
 78                 tn=20;
 79                 gpsdata[8]=rec_gpsdata[tn];    //經度解析
 80                 gpsdata[9]=rec_gpsdata[tn+1];
 81                 gpsdata[10]=rec_gpsdata[tn+2];
 82                 gpsdata[11]='.';
 83                 tm=(10000*(rec_gpsdata[tn+3]-0x30)+1000*(rec_gpsdata[tn+4]-0x30)+100*(rec_gpsdata[tn+6]-0x30)+10*(rec_gpsdata[tn+7]-0x30)+(rec_gpsdata[tn+8]-0x30))/6;
 84                 gpsdata[12]=tm/1000+0x30;
 85                 gpsdata[13]=(tm%1000)/100+0x30;
 86                 gpsdata[14]=(tm%100)/10+0x30;
 87                 gpsdata[15]=tm%10+0x31;
 88                 gpsdata[16]='\n';
 89                 gps_ok=1;
 90                 break;
 91     }
 92         else gps_ok=0;
 93     } 
 94         if(gps_ok==1)
 95         {
 96             Uart2Sends("AT\r\n"); //同步波特率,如果將模塊配置固定波特率,此條指令就不需要發了
 97             while(!hand("OK")) 
 98             {
 99                 clear_rec_data();
100                 i++;
101                 Uart2Sends("AT\r\n");//
102                 DelaySec(1);//延時
103                 if(i>=5)
104                 {
105                     break;
106                 }
107             }
108             clear_rec_data();//刪除存儲的GSM模塊返回的數據,以便於以後繼續判斷
109             DelaySec(1);//延時
110             P0=0x00;//初始化和檢驗完畢,led燈產生信號。
111             Uart2Sends("AT+CSCS=\"GSM\"\r\n"); //
112             DelaySec(1);//延時
113             Uart2Sends("AT+CSCA?\r\n"); //短訊中心號碼
114             DelaySec(1);//延時
115             Uart2Sends("AT+CMGF=1\r\n");  //方式1
116             DelaySec(1);//延時
117             Uart2Sends("AT+CMGS=\"156-------\"\r\n");  //此處修改短訊接收方電話號
118             DelaySec(1);//延時
119             Uart2Sends("SOS:I need help! My position is https;//mo.amap.com/?q=");  //此處修改短訊內容
120             Uart2Sends(gpsdata);
121             DelaySec(1);//延時
122             Uart2BYTE(0X1A);
123             DelaySec(1);//延時
124         //撥打電話代碼
125             Uart2Sends("ATD156--------;\r\n");  //撥打電話
126         }    
127 }
128 /*
129 串口2,sim900a通信串口
130 */
131 
132 void Uart2Init()        //[email protected]
133 {
134     
135     S2CON = 0x50;        //8位數據,可變波特率
136     AUXR |= 0x04;        //定時器2時鐘為Fosc,即1T
137     T2L = 0xE0;        //設定定時初值
138     T2H = 0xFE;        //設定定時初值
139     AUXR |= 0x10;        //啟動定時器2
140     EA=1;//開總中斷
141     ES=1;//開串行口中斷    
142     IE2=0x01;
143 }
144 /**
145 interrupt 8 interrupt 17 interrupt 18:串口2 3 4的串口號
146 **/
147 void Serial_interrupt() interrupt 8 using 1
148 {
149     uchar temp;
150     if(S2CON & 0x01)           // 接收中斷標誌判斷
151         {
152          S2CON &= ~0x01;//等價於RI=0 
153 
154         temp=S2BUF;
155         rec_data[rec_num++]=temp;
156         if(rec_num>=50)
157             rec_num=0;
158         else
159             ;
160         //RI=0;//接收中斷信號清零,表示將繼續接收
161         }
162     
163  
164 }
165  
166 //串行口連續發送char型數組,遇到終止號/0將停止
167 void Uart2Sends(uchar *str)
168 {
169     while(*str!='\0')
170     {
171         S2BUF=*str;
172         while(!(S2CON & 0x02));//等待發送完成信號(TI=1)出現
173         S2CON &= ~0x02;         // 清中斷標誌
174         str++;
175     }
176 }
177 void Uart2BYTE(uchar temp)
178 {
179         S2BUF=temp;
180     while(!(S2CON & 0x02));//等待發送完成信號(TI=1)出現
181         S2CON &= ~0x02;         // 清中斷標誌
182  
183 }
184  
185 uchar hand(uchar *ptr)
186 {
187     if(strstr(rec_data,ptr)!=NULL)
188         return 1;
189     else
190         return 0;
191 }
192  
193 void clear_rec_data()
194 {
195     uchar i;
196     for(i=0;i<strlen(rec_data);i++)
197     {
198         rec_data[i]='0';
199     }
200     rec_num=0;
201 }
202 //延時函數1s鍾
203 void DelaySec(int sec)
204 {
205     unsigned char i, j, k,m;
206  
207     for(m=0; m<sec; m++)
208     {
209         _nop_();
210     _nop_();
211     i = 43;
212     j = 6;
213     k = 203;
214     do
215     {
216         do
217         {
218             while (--k);
219         } while (--j);
220     } while (--i);
221     }
222 }
223 /*
224 GPS 模塊,串口3通信
225 */
226 // $GPGLL,2236.91284,N,11403.24705,E,060826.00,A,D*66,gps返回數據的示例
227 void Uart3Init()        //[email protected]
228 {
229     S3CON = 0x10;        //8位數據,可變波特率
230     S3CON &= 0xBF;        //串口3選擇定時器2為波特率發生器
231     AUXR |= 0x04;        //定時器2時鐘為Fosc,即1T
232     T2L = 0xE0;        //設定定時初值
233     T2H = 0xFE;        //設定定時初值
234     AUXR |= 0x10;        //啟動定時器2
235     EA=1;//開總中斷
236     IE2 |= 0x08;         // 串口3中斷打開
237 }
238 void GPSreturn(void) interrupt 17
239 {
240         uint temp;
241     if (S3CON & 0x01)           // 接收中斷標誌位
242     {
243         S3CON &= ~0x01;         // 清中斷標誌
244                 temp=S3BUF;
245             if(rec_gpsnum<=50)
246                 rec_gpsdata[rec_gpsnum++]=temp;
247             if(rec_gpsnum>50)
248                 rec_gpsnum=0;
249     }
250 }
251 
252 
253  
254