系统硬件电路主要有GPS、液晶显示器、STC12C5A60S2、LED状态指示单片机上电复位和电源等部分组成。GPS发送的串行数据送至单片机串行口经处理后通过键盘选择要显示的信息,送至LCD液晶显示器。LCD液晶显示器会定时更新,更新周期约为1 s。上电复位电路为单片机上电提供上电复位。电源电路为各个电路提供稳定的电源。
电路图用AD画的
STC12C5A60S2单片机源程序如下:
- #include "STC12C5A.H"
- #include "stdio.h"
- #include "stdlib.h"
- #include "string.h"
- #include "uart.h"
- #include "timer0.h"
- #include "key.h"
- #include "lcd12864.h"
- #include "GPS.h"
- #include "GPS_PacketQueue.h"
- extern unsigned long Timer0_Count; // 系统时基
- unsigned char Display_Flag = 0; // 显示界面(0 - 时间经纬度,1 - 速度等)
- unsigned char xdata DateTime[7] = {0}; // 时间和日期缓冲:秒,时,分,日,月,星期,年
- /*-------------GPS相关变量-------- --------------------*/
- GPS_INFO xdata GPS;
- unsigned char GPS_Flag = 0; // GPS数据有效标志
- // 函数声明
- void LCD_Display_DateTime(unsigned char *pDataTime); // LCD显示时间,日期
- void LCD_Display_Longitude_Latitude(GPS_INFO *GPS); // LCD显示经纬度
- void LCD_Display_Speed(GPS_INFO *GPS); // LCD显示速度,航向等
- /****************************************
- 主函数
- /****************************************/
- void main(void)
- {
- char key_value = 0;
- struct timer Display_Time;
- struct timer Flag_Time;
- struct timer Error_Time;
- GPS_PACKET *Packet = NULL;
- memset(&GPS,0,sizeof(GPS)); // 一定要清0
-
- timer_set(&Display_Time, CLOCK_SECOND/5); // 200ms
- timer_set(&Error_Time, CLOCK_SECOND*2); // 2S
- timer_set(&Flag_Time, CLOCK_SECOND*5); // 3S
- LCD_Init();
- GPS_PacketInit(); // 接收缓冲区初始化
-
- UART_Init(); // 初始化UART
- Timer0_Init(); // 启动定时器
- while(1)
- {
- /* 处理GPS信号 */
- Packet = NULL;
- Packet = (GPS_PACKET *)GPS_GetPacket();
- if( Packet ){
- timer_restart(&Error_Time); // 接收正确更新时间
- if(Packet->DataType == 1){
- if(GPS_RMC_Parse(Packet->DataBuffer, &GPS)) // 解析GPRMC
- {
- memset(Packet,0,sizeof(GPS_PACKET));
- DateTime[6] = GPS.D.year;
- DateTime[4] = GPS.D.month;
- DateTime[3] = GPS.D.day;
- DateTime[2] = GPS.D.hour;
- DateTime[1] = GPS.D.minute;
- DateTime[0] = GPS.D.second;
- GPS_Flag = 1;
- }
- else{ // 解析错误要清空缓冲区
- memset(Packet,0,sizeof(GPS_PACKET));
- }
- }
- else if(Packet->DataType == 2){
- if(GPS_GGA_Parse(Packet->DataBuffer, &GPS)){
- memset(Packet,0,sizeof(GPS_PACKET));
- GPS_Flag = 1;
- }
- else{ // 解析错误要清空缓冲区
- memset(Packet,0,sizeof(GPS_PACKET));
- }
- }
- }
- else{
- // 接收错误,且时长超过100*20ms = 2S,复位硬件
- if( timer_expired(&Error_Time) )
- {
- UART_Init();
- GPS_PacketInit();
- timer_restart(&Error_Time);
- GPS_Flag = 0;
- }
- }
-
-
- if( timer_expired(&Flag_Time) ) // 切换画面
- {
- Display_Flag = ++Display_Flag % 2;
- LCD_Clear();
- timer_reset(&Flag_Time);
- }
-
- if( timer_expired(&Display_Time) )
- {
- timer_reset(&Display_Time);
-
- if(GPS_Flag == 0)
- {
- memset(DateTime,0,sizeof(DateTime));
- memset(&GPS,0,sizeof(GPS));
- }
- if(Display_Flag == 0)
- {
- LCD_Display_DateTime(DateTime); // 时间显示
- LCD_Display_Longitude_Latitude(&GPS);
- }
- else
- {
- LCD_Display_Speed(&GPS);
- }
- }
- }
- }
- /*
- 日期和时间显示
- */
- void LCD_Display_DateTime(unsigned char *pDataTime)
- {
- unsigned char temp_buffer[9] = {0};
-
- // 显示年,月,日
- temp_buffer[0] = pDataTime[6]/10+0x30;
- temp_buffer[1] = pDataTime[6]%10+0x30;
- Display_String(1,1,"20");
- Display_String(2,1,temp_buffer);
- Display_String(3,1,"年");
- temp_buffer[0] = pDataTime[4]/10+0x30;
- temp_buffer[1] = pDataTime[4]%10+0x30;
- Display_String(4,1,temp_buffer);
- Display_String(5,1,"月");
- temp_buffer[0] = pDataTime[3]/10+0x30;
- temp_buffer[1] = pDataTime[3]%10+0x30;
- Display_String(6,1,temp_buffer);
- temp_buffer[8] = '\0';
- Display_String(7,1,"日");
-
- // 显示时,分,秒
- temp_buffer[0] = pDataTime[2]/10+0x30;
- temp_buffer[1] = pDataTime[2]%10+0x30;
- temp_buffer[2] = ':';
- temp_buffer[3] = pDataTime[1]/10+0x30;
- temp_buffer[4] = pDataTime[1]%10+0x30;
- temp_buffer[5] = ':';
- temp_buffer[6] = pDataTime[0]/10+0x30;
- temp_buffer[7] = pDataTime[0]%10+0x30;
- temp_buffer[8] = '\0';
- Display_String(1,2,temp_buffer);
-
- // 显示星期
- switch(DateTime[5]%10 -1)
- {
- case 0: Display_String(6,2,"星期日\0");break;
- case 1: Display_String(6,2,"星期一\0");break;
- case 2: Display_String(6,2,"星期二\0");break;
- case 3: Display_String(6,2,"星期三\0");break;
- case 4: Display_String(6,2,"星期四\0");break;
- case 5: Display_String(6,2,"星期五\0");break;
- case 6: Display_String(6,2,"星期六\0");break;
- default: break;
- }
- }
- /*
- 显示纬度和经度
- */
- void LCD_Display_Longitude_Latitude(GPS_INFO *GPS)
- {
- unsigned char ch, i;
- char info[20];
-
- if (GPS->NS == 'N') //判断是北纬还是南纬
- {
- Display_String(1,3,"北纬");
- }
- else if (GPS->NS == 'S')
- {
- Display_String(1,3,"南纬");
- }
- if (GPS->EW == 'E') //判断是东经还是西经
- {
- Display_String(1,4,"东经");
- }
- else if (GPS->EW == 'W')
- {
- Display_String(1,4,"西经");
- }
- sprintf(info,":%3d\0",GPS->latitude_Degree);
- LCD_XY(3, 3);
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- LCD_Write_Data(ch);
- }
- LCD_Write_Data(0xA1);
- LCD_Write_Data(0xE3);
- Int_To_Str(GPS->latitude_Cent, info);
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- LCD_Write_Data(ch);
- }
- LCD_Write_Data(0xA1);
- LCD_Write_Data(0xE4);
- Int_To_Str(GPS->latitude_Second, info);
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- LCD_Write_Data(ch);
- }
- sprintf(info,":%3d\0",GPS->longitude_Degree);
- LCD_XY(3, 4);
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- LCD_Write_Data(ch);
- }
- LCD_Write_Data(0xA1);
- LCD_Write_Data(0xE3);
- Int_To_Str(GPS->longitude_Cent, info);
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- LCD_Write_Data(ch);
- }
- LCD_Write_Data(0xA1);
- LCD_Write_Data(0xE4);
- Int_To_Str(GPS->longitude_Second, info);
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- LCD_Write_Data(ch);
- }
- }
- /*
- 把浮点数fla显示在LCD的坐标(x,y)位置
- */
- void Show_Float(float fla, unsigned char x, unsigned char y)
- {
- int integar;
- char Info[10],ch;
- unsigned char i;
-
- LCD_XY(x, y);
- integar = (int)fla; // 得到浮点数的整数部分
- Int_To_Str(fla, Info);
- i = 0;
- while(Info[i] !='\0')
- {
- ch=Info[i++];
- LCD_Write_Data(ch);
- }
- LCD_Write_Data('.');
- fla = fla - integar; // 得到浮点数的小数部分
-
- fla = fla * 10; // 小数位第一位
- integar = (int)fla;
- fla = fla - integar;
- ch = integar + 0x30;
- LCD_Write_Data(ch);
-
- fla = fla*10; // 小数位第二位
- integar = (int)fla;
- fla = fla - integar;
- ch = integar + 0x30 ;
- LCD_Write_Data(ch);
- }
- /*
- 显示速度,航向,海拔
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
1. DXP版本原理图 & PCB.rar
(478.27 KB, 下载次数: 291)
3. 程序.rar
(172.8 KB, 下载次数: 310)
|