GPS.c
上传用户:orange__li
上传日期:2022-06-08
资源大小:5k
文件大小:15k
源码类别:

GPS编程

开发平台:

C/C++

  1. //**********************************标注定义********************************//
  2. //**********************************标注定义********************************//
  3. #include <reg52.h>     // 引用标准库的头文件
  4. #include <stdio.h>
  5. #include <absacc.h>
  6. #include <intrins.H>
  7. //****************************配置GPS函数声明*******************************//
  8. //GPS数据存储数组
  9. unsigned char JD[10]={"00000.0000"}; //经度
  10. unsigned char JD_a='*';                 //经度方向
  11. unsigned char WD[9]={"0000.0000"}; //纬度
  12. unsigned char WD_a='*';                 //纬度方向
  13. unsigned char time[6]={"000000"};                //时间
  14. unsigned char date[6]={"000000"};         //日期
  15. unsigned char speed[5]; //速度
  16. unsigned char high[6]; //高度
  17. unsigned char angle[5]; //方位角
  18. unsigned char use_sat[2]={"00"}; //使用的卫星数
  19. unsigned char total_sat[2]={"00"}; //天空中总卫星数
  20. //串口中断需要的变量
  21. unsigned char seg_count; //逗号计数器
  22. unsigned char dot_count; //小数点计数器
  23. unsigned char byte_count; //位数计数器
  24. unsigned char cmd_number; //命令类型
  25. unsigned char mode; //0:结束模式,1:命令模式,2:数据模式
  26. volatile unsigned char buf_full; //1:整句接收完成,相应数据有效。0:缓存数据无效。
  27. unsigned char cmd[5]; //命令类型存储数组
  28. //显示需要的变量
  29. unsigned char dsp_count; //刷新次数计数器
  30. unsigned char time_count;
  31. uchar code datas1[] = {"欢迎使用GPS"};
  32. uchar code datas2[] = {"白云学院电子系"};
  33. uchar code datas3[] = {"06电子信息本科班"};
  34. uchar code datas4[] = {"曾宪敏"};
  35. //**********************************初始化串口********************************//
  36. //**********************************初始化串口********************************//
  37. void UART_Init()
  38. {
  39. SCON=0x50; // UART工作于模式1, REN=1 
  40. TMOD=0x20 ; // Timer1 工业于模式2
  41. PCON |= 0x80; // SMOD1 = 1 
  42. TH1=0xF3; // 波特率9600 bps
  43. TL=0xF3; // 波特率9600 bps
  44.         EA=1
  45. ES= 1;  //串口中断使能
  46. TR1= 1;  // 启动Timer1 
  47. }
  48. //**********************************LCD模块********************************//
  49. //**********************************LCD模块********************************//
  50. #define uchar unsigned char
  51. #define uint unsigned int
  52. //延时约2us
  53. void delayUs()
  54.  {
  55.     _nop_();_nop_();
  56.  }
  57.  //延时a ms
  58.  void delayMs(uint a)
  59.   {
  60.      uint i, j;
  61.      for(i = a; i > 0; i--)
  62.          for(j = 100; j > 0; j--);
  63.  }
  64.  
  65.  //检测LCD是否处于忙状态, 若忙返回1, 空闲返回0
  66.  bit checkBusy()
  67.   {
  68.      bit busy;
  69.      RS = 0;
  70.      RW = 1;
  71.      E = 1;
  72.      delayUs();
  73.      busy = (bit)(LCD_DATA&0x80);
  74.      E = 0;
  75.      return busy;
  76.  }
  77.  
  78.  //等待LCD到空闲
  79.  void LCDwait()
  80.   {
  81.      while(checkBusy());
  82.  }
  83.  
  84.  //写命令
  85.  void LCDwriteCmd(uchar cmd)
  86.   {
  87.      LCDwait();
  88.      RS = 0;
  89.      RW = 0;
  90.      E = 0;
  91.      delayUs();
  92.      LCD_DATA = cmd;
  93.      delayUs();
  94.      E = 1;
  95.      delayUs();
  96.      E = 0;
  97.  }
  98.  
  99.  //写数据
  100.  void LCDwriteData(uchar dat)
  101.   {
  102.      LCDwait();
  103.      RS = 1;
  104.      RW = 0;
  105.      E = 0;
  106.      delayUs();
  107.      LCD_DATA = dat;
  108.      delayUs();
  109.      E = 1;
  110.      delayUs();
  111.      E = 0;
  112.  }
  113.  
  114.  //初始化LCD
  115.  void LCDinit()
  116.   {
  117.      PSB = 1; //并口方式
  118.      LCDwriteCmd(0x30); //基本指令, 扩充指令为34H
  119.      delayMs(10);
  120.      LCDwriteCmd(0x0c); //显示开, 关光标
  121.      delayMs(10);
  122.      LCDwriteCmd(0x01); //清屏
  123.      delayMs(10);
  124.  }
  125.  
  126.  void display(uchar x, uchar y,uchar *str)
  127.   {
  128.      uchar p;
  129.   uchar i = 0;
  130.      switch(x)
  131.       {
  132.          case 0: p = 0x80; break; //第一行开始地址
  133.          case 1: p = 0x90; break; //第二行
  134.          case 2: p = 0x88; break; //第三行
  135.          case 3: p = 0x98; break; //第四行
  136.      }
  137.      p += y;
  138.      LCDwriteCmd(p);     
  139.      while(str[i] != '')
  140.       {
  141.          LCDwriteData(str[i++]);
  142.      }
  143.  }
  144. /*--------------------------------------------------------- 
  145. GPS模块串口接收程序:串口函数 
  146. ---------------------------------------------------------*/ 
  147. void GPS_INT() //interrupt 4 
  148. uchar i; 
  149. RI=0; 
  150. if(SBUF=='$') //判断是否为$GPRMC语句 
  151.     { 
  152.   gpsnum=0; 
  153.       gpsres=1; //开始接收 
  154.       return; 
  155.     } 
  156. if(SBUF=='*' && gpsres==1) //接收完数据后的处理 
  157.     { 
  158.   gpsnum=0; //复位为第0个数据 
  159.       gpsres=0; //停止接收 
  160.       ////////修正时间数据为北京时间,24小时制 
  161.   if(gpstime[0] <0x32) 
  162.   i=gpstime[1]+0x08; //小时个位+8,转为北京时间 
  163.           if(i>=0x3a) 
  164.   { 
  165. i=i-0x0a; 
  166.             gpstime[0]=gpstime[0]+0x01; 
  167. if(gpstime[0]==0x32&&i>=0x34) 
  168.       {gpstime[0]=0x30;i=i-0x04;}                                  
  169.     } 
  170.   } 
  171.       else 
  172.       { 
  173.   i=gpstime[1]+0x04; 
  174.           gpstime[0]=0x30; 
  175.   }                                        
  176.       gpstime[1]=i; 
  177.       return; 
  178.   } 
  179.   ////////////////////////////////////////// 
  180. if(gpsres==1) 
  181. if(SBUF==',') //逗号后为下一个数据 
  182. {gpsnum++;return;} 
  183. switch(gpsnum)   //判断数据类型,然后存储起来 
  184.   case 0:{*gpsptime=SBUF;gpsptime++;}break; 
  185.   case 1:{*gpspstatus=SBUF;gpspstatus++;}break; 
  186.   case 2:{*gpspweidu=SBUF;gpspweidu++;}break; 
  187.   case 3:{*gpspnors=SBUF;gpspnors++;}break; 
  188.   case 4:{*gpspjingdu=SBUF;gpspjingdu++;}break; 
  189.   case 5:{*gpspeorw=SBUF;gpspeorw++;}break; 
  190.   case 6:{}break; 
  191.   case 7:{}break; 
  192.   case 8:{*gpspdate=SBUF;gpspdate++;}break; 
  193.   case 9:{}break; 
  194.   default: 
  195.   { 
  196.   *gpsptime=gpstime; //复位各数据指针 
  197.   *gpspstatus=gpsstatus; 
  198.   *gpspweidu=gpsweidu; 
  199.   *gpspnors=gpsnors; 
  200.   *gpspjingdu=gpsjingdu; 
  201.   *gpspeorw=gpseorw; 
  202.   *gpspdate=gpsdate; 
  203.         }break;          
  204.   } 
  205. //USART 初始化
  206. void init_USART(void)
  207. {
  208.     UCSRC = (1<<URSEL) | 0x06;     //异步,8位数据,无奇偶校验,一个停止位,无倍速
  209.     UBRRL= (F_CPU/9600/16-1)%256;     //UBRR= (F_CPU/(BAUDRATE*16))-1;
  210.     UBRRH= (F_CPU/9600/16-1)/256;
  211.     UCSRA = 0x00;     //使能接收中断,使能接收,使能发送
  212.     UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN)
  213. sei(); //总中断允许
  214. volatile unsigned char high_num,a_num,s_num;
  215. void init_set(void);
  216. void sys_init(void);
  217. unsigned char week(unsigned char year, unsigned char mon, unsigned char day);
  218. int main(void)
  219. {
  220. unsigned char i;
  221. unsigned char Bhour=0,Bday=0,Bmonth=0;
  222. unsigned int Byear=0;
  223. sys_init();
  224. while(1){
  225. if(buf_full==0) //无GPS信号时
  226. {
  227. dsp_count++;
  228. _delay_ms(10);
  229. if(dsp_count>=200){
  230. CLEAN_SCREEN(); //清屏
  231. display(0,0,PSTR("No GPS CONNECT.."),0);
  232. while(buf_full==0);
  233. CLEAN_SCREEN();
  234. dsp_count=0;
  235. }
  236. }
  237. else{ //有GPS信号时
  238. if(buf_full|0x01){ //GGA语句
  239. display(0,0,JD_a,0); //显示经度
  240. for(i=0;i<3;i++){
  241. display(0,(i+1)*6,JD[i],0);
  242. }
  243. display(0,24,'.',0);
  244. for(i=3;i<10;i++){
  245. display(0,(i+2)*6,JD[i],0);
  246. }
  247. display(1,0,WD_a,0); //显示纬度
  248. for(i=0;i<2;i++){
  249. display(1,(i+2)*6,WD[i],0);
  250. }
  251. display(1,24,'.',0);
  252. for(i=2;i<9;i++){
  253. display(1,(i+3)*6,WD[i],0);
  254. }
  255. display(2,96,use_sat[0],0); //显示接收卫星数
  256. display(2,102,use_sat[1],0);
  257. display(2,108,'/',0);
  258. display(2,0,PSTR("HI:"),0);
  259. if(high_num<6)   //高度显示
  260. {
  261. for(i=0;i<(6-high_num);i++)
  262. {
  263. display(2,(3+i)*6,0x20,0);
  264. }
  265. }
  266. for(i=0;i<high_num;i++)
  267. {
  268. display(2,(9-high_num+i)*6,high[i],0);
  269. }
  270. display(2,54,PSTR("m  U/T:"),0);
  271. buf_full&=~0x01;
  272. dsp_count=0;
  273. }
  274. if(buf_full|0x02){ //GSV语句
  275. display(2,114,total_sat[0],0);
  276. display(2,120,total_sat[1],0);
  277. buf_full&=~0x02;
  278. dsp_count=0;
  279. }
  280. if(buf_full|0x04)
  281. {
  282. display(0,78,PSTR("AG:"),0);//方位角显示
  283. if(a_num<5)
  284. {
  285. for(i=0;i<(5-a_num);i++)
  286. {
  287. display(0,(16+i)*6,0x20,0);
  288. }
  289. }
  290. for(i=0;i<a_num;i++)
  291. {
  292. display(0,(21-a_num+i)*6,angle[i],0);
  293. }
  294. display(1,78,PSTR("SP:"),0); //速度显示
  295. if(s_num<5)
  296. {
  297. for(i=0;i<(5-s_num);i++)
  298. {
  299. display(1,(16+i)*6,0x20,0);
  300. }
  301. }
  302. for(i=0;i<s_num;i++)
  303. {
  304. display(1,(21-s_num+i)*6,speed[i],0);
  305. }
  306. buf_full&=~0x04;
  307. dsp_count=0;
  308. }
  309. if(buf_full|0x08){
  310. if(Bhour!=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA){
  311. Bhour=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA; //北京时间转换
  312. Bday=(date[0]-0x30)*10+date[1]-0x30;
  313. Bmonth=(date[2]-0x30)*10+date[3]-0x30;
  314. Byear=(date[4]-0x30)*10+date[5]-0x30+2000;
  315. if(Bhour>=24){    //如果小时数大于24
  316. Bhour-=24;    //小时数减24
  317. Bday++;      //日期数加1
  318. switch(Bday //判断日期
  319. case 29: //普通年的2月份
  320. if((!((Byear%400==0)||((Byear%4==0)&&(Byear%100!=0)))&&(Bmonth==2))){
  321. Bday=1;
  322. Bmonth++;
  323. }
  324. break
  325. case 30:      //如果是闰年的2月
  326. if(((Byear%400==0)||((Byear%4==0)&&(Byear%100!=0)))&&(Bmonth==2)){
  327. Bday=1;
  328. Bmonth++;
  329. }
  330. break;
  331. case 31:
  332. if((Bmonth==4)||(Bmonth==6)||(Bmonth==9)||(Bmonth==11)){
  333. Bday=1;
  334. Bmonth++;
  335. }
  336. break;
  337. case 32:
  338. Bday=1;
  339. Bmonth++;
  340. if(Bmonth>=13){
  341. Byear++;
  342. Bmonth=1;
  343. }
  344. break;
  345. }
  346. }
  347. }
  348. display(3,0,'2',0);
  349. display(3,6,'0',0);
  350. display(3,12,(Byear%100)/10+0x30,0);
  351. display(3,18,Byear%10+0x30,0);
  352. display(3,24,'/',0);
  353. display(3,30,Bmonth/10+0x30,0);
  354. display(3,36,Bmonth%10+0x30,0);
  355. display(3,42,'/',0);
  356. display(3,48,Bday/10+0x30,0);
  357. display(3,54,Bday%10+0x30,0);
  358. switch(week(Byear%100,Bmonth,Bday)){
  359. case 0:
  360. display(3,120,PSTR("7"),0);
  361. break;
  362. case 1:
  363. display(3,120,PSTR("1"),0);
  364. break;
  365. case 2:
  366. display(3,120,PSTR("2"),0);
  367. break;
  368. case 3:
  369. display(3,120,PSTR("3"),0);
  370. break;
  371. case 4:
  372. display(3,120,PSTR("4"),0);
  373. break;
  374. case 5:
  375. display(3,120,PSTR("5"),0);
  376. break;
  377. case 6:
  378. display(3,120,PSTR("6"),0);
  379. break;
  380. }
  381. if(Bhour/10!=0)
  382. {
  383. display(3,66,Bhour/10+0x30,0);
  384. NUM1632_DISP(4,0,Bhour/10,0);
  385. }
  386. else
  387. {
  388. display(3,66,0x20,0);
  389. NUM1632_DISP(4,0,11,0);
  390. }
  391. display(3,72,Bhour%10+0x30,0);
  392. display(3,78,':',0);
  393. display(3,84,time[2],0);
  394. display(3,90,time[3],0);
  395. display(3,96,':',0);
  396. display(3,102,time[4],0);
  397. display(3,108,time[5],0);
  398. NUM1632_DISP(4,1,Bhour%10,0);
  399. NUM1632_DISP(4,2,10,0);
  400. NUM1632_DISP(4,3,time[2]-0x30,0);
  401. NUM1632_DISP(4,4,time[3]-0x30,0);
  402. NUM1632_DISP(4,5,10,0);
  403. NUM1632_DISP(4,6,time[4]-0x30,0);
  404. NUM1632_DISP(4,7,time[5]-0x30,0);
  405. buf_full&=~0x08;
  406. dsp_count=0;
  407. }
  408. }
  409. }
  410. }
  411. //计算星期 
  412. unsigned char week(unsigned char year, unsigned char mon, unsigned char day) 
  413.     const prog_uchar Weekdays[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; 
  414.                                          // 31 28 31 30 31 30 31 31 30 31 30 
  415.     return (6-1 + (year>>2) + year + Weekdays[mon-1] + day + (((year & 3) || mon > 2)? 1 : 0)) % 7; 
  416.     //完整的计算星期的公式: 
  417.     //(year>>2) - (year / 100) + (year/400) + year + 
  418.     //    Weekdays[mon-1] + day + ((!isLeap(year) || mon > 2)? 1 : 0)) % 7; 
  419. }
  420. //串口接收中断
  421. SIGNAL(SIG_UART_RECV) //串口接收中断服务程序
  422. {
  423. unsigned char tmp;
  424. tmp=UDR;
  425. switch(tmp){
  426. case '$':
  427. cmd_number=0; //命令类型清空
  428. mode=1; //接收命令模式
  429. byte_count=0; //接收位数清空
  430. break;
  431. case ',':
  432. seg_count++; //逗号计数加1
  433. byte_count=0;
  434. break;
  435. case '*':
  436. switch(cmd_number){
  437. case 1:
  438. buf_full|=0x01;
  439. break;
  440. case 2:
  441. buf_full|=0x02;
  442. break;
  443. case 3:
  444. buf_full|=0x04;
  445. break;
  446. case 4:
  447. buf_full|=0x08;
  448. break;
  449. }
  450. mode=0;
  451. break;
  452. default:
  453. if(mode==1){
  454. //命令种类判断
  455. cmd[byte_count]=tmp; //接收字符放入类型缓存
  456. if(byte_count>=4  //如果类型数据接收完毕,判断类型
  457. if(cmd[0]=='G'){
  458. if(cmd[1]=='P'){
  459. if(cmd[2]=='G'){
  460. if(cmd[3]=='G'){
  461. if(cmd[4]=='A'){
  462. cmd_number=1;
  463. mode=2;
  464. seg_count=0;
  465. byte_count=0;
  466. high_num=0;
  467. }
  468. }
  469. else if(cmd[3]=='S'){
  470. if(cmd[4]=='V'){
  471. cmd_number=2;
  472. mode=2;
  473. seg_count=0;
  474. byte_count=0;
  475. }
  476. }
  477. }
  478. else if(cmd[2]=='R'){
  479. if(cmd[3]=='M'){
  480. if(cmd[4]=='C'){
  481. cmd_number=3;
  482. mode=2;
  483. seg_count=0;
  484. byte_count=0;
  485. a_num=0;
  486. s_num=0;
  487. }
  488. }
  489. }
  490. else if(cmd[2]=='Z'){
  491. if(cmd[3]=='D'){
  492. if(cmd[4]=='A'){
  493. cmd_number=4;
  494. mode=2;
  495. seg_count=0;
  496. byte_count=0;
  497. }
  498. }
  499. }
  500. }
  501. }
  502. }
  503. }
  504. else if(mode==2){
  505. //接收数据处理
  506. switch (cmd_number){
  507. case 1: //类型1数据接收GPGGA
  508. switch(seg_count){
  509. case 2: //纬度处理
  510. if(byte_count<9){
  511. WD[byte_count]=tmp;
  512. }
  513. break;
  514. case 3: //纬度方向处理
  515. if(byte_count<1){
  516. WD_a=tmp;
  517. }
  518. break;
  519. case 4: //经度处理
  520. if(byte_count<10){
  521. JD[byte_count]=tmp;
  522. }
  523. break;
  524. case 5: //经度方向处理
  525. if(byte_count<1){
  526. JD_a=tmp;
  527. }
  528. break;
  529. case 7: //定位使用的卫星数
  530. if(byte_count<2){
  531. use_sat[byte_count=tmp;
  532. }
  533. break;
  534. case 9: //高度处理
  535. if(byte_count<6){
  536. high[byte_count]=tmp;
  537. high_num++;
  538. }
  539. break;
  540. }
  541. break;
  542. case 2: //类型2数据接收。GPGSV
  543. switch(seg_count){
  544. case 3: //天空中的卫星总数
  545. if(byte_count<2){
  546. total_sat[byte_count]=tmp;
  547. }
  548. break;
  549. }
  550. break;
  551. case 3: //类型3数据接收GPRMC
  552. switch(seg_count){
  553. case 7: //速度处理
  554. if(byte_count<5){
  555. speed[byte_count]=tmp;
  556. s_num++;
  557. }
  558. break;
  559. case 8: //方位角处理
  560. if(byte_count<5){
  561. angle[byte_count]=tmp;
  562. a_num++;
  563. }
  564. break;
  565. }
  566. break;
  567. case 4: //类型4数据接收.GPZDA
  568. switch(seg_count){
  569. case 1:
  570. if(byte_count<6){ //时间处理
  571. time[byte_count]=tmp;
  572. }
  573. break;
  574. case 2:
  575. if(byte_count<2){
  576. date[byte_count]=tmp;
  577. }
  578. break;
  579. case 3:
  580. if(byte_count<2){
  581. date[byte_count+2]=tmp;
  582. }
  583. break;
  584. case 4:
  585. if((byte_count<4)&&(byte_count>1)){
  586. date[byte_count+2]=tmp;
  587. }
  588. break;
  589. }
  590. break;
  591. }
  592. }
  593. byte_count++; //接收数位加1
  594. break;
  595. }
  596. }
  597. /**********************************主函数模块********************************/
  598. //**********************************主函数模块********************************//
  599. void main()
  600. {
  601.      LCDinit();     //初始化LCD
  602.      LCDwriteCmd(0x01);
  603.      //显示开始信息
  604.      display(0, 1,datas1);     
  605.      display(1, 0,datas2);
  606.      display(2, 0,datas3);
  607.      display(3, 3,datas4);
  608.      delayMs(1000);
  609.      LCDwriteCmd(0x01);
  610.      display(1,0,"GPS定位中。。。");
  611.      delayMs(1000);
  612.      
  613.        UART_Init();    // 初始化串口 
  614.        EA = 1;
  615.         
  616.       DisableAllOut();
  617.    EnableGPRMC();
  618.         LCDwriteCmd(0x01);
  619.         GPS_INT() ;
  620.         display(0,0,gpsdate);
  621.         display(1,0,gpstime);
  622.         display(2,0,gpsjingdu);
  623.         display(3,0,gpsweidu);
  624.       delayMs(1000); // 延时1s
  625. //REN = 1; // REN = 1,开始接收数据
  626. //while(1);
  627. }