|
本帖最後由 antlu 於 2013-11-11 10:27 PM 編輯
最近想要把機車的超速作一個警報以避免"超速罰單",老婆建議說用一個感應器裝在面板上,檢測指針位置,我又不想動到車子!!
於是想到 GPS 速度參數的地方,查了一下 $GPRMC 有一個參數有提到速度,就把他拿來用,沒想到這參數是 船的速度"節" 1節=1852公尺/小時,機車超速的限制 50公里約 27節,就將就的用吧!!
把原先的 GPS時鐘拿來改寫程式,慢慢的把想要用的功能寫出來,期間遇到了一些問題如 速度(節) 7.21 這樣三位數 17.21 這樣四位數,位數不定要抓出來作數值比較就要作調整... 我的GPS收訊又不佳,定位要老半天,而且要等到 三顆星(衛星)才能顯示速度,光是驗證功能就要等半死,還有"超速"實地驗證,更是危險!! 終於把 "實驗版"給搞出來(搞是大陸用語),接下來要"移植"到簡易電路,這樣才好用!! 於是改成 LED 7段顯示版,突發奇想,可否使用 串口大師 取代GPS送信號給玩具,結果可行ㄟ!! 好棒!! 這樣就不用 在外面等 衛星,改程式驗證也方便多了!(這期間還發現許多小問題,感謝 LEGION大師提供的軟體),除了顯示速度(節)之外,順便顯示時間,之所以沒有使用"公里/時"是因為小數點的運算怕會出問題,所以就將就的用吧!! 這程式希望可以用在 89C2051上面,因為這樣一來可以省下更多的空間....
時間 20:59
速度15.00 節
程式還沒有完備,有許多過去的包袱,大家參考就好!! 線路圖等成品出來再 PO
//20131111 完成 GPS顯示時間 與速度節 超速50公里(27節)ALARM
#include<reg52.h>
#define DataPort P1 // display LED segment
//#define DrivePort P3 //display LED digit
//sbit Gok_LED =P1^2;// 收到"$GPRMC,"送出LED
bit disp_flag;
bit dispt_flag;//切換顯示
bit rec; // receive rs232 OK_flag
void DelayUs2x(unsigned char t);//us级延时函数声明
void DelayMs(unsigned char t); //ms级延时
void Display(unsigned char Num);// 把七段顯示出去
unsigned char code segment[10]={ 0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};//bit 7(a)~bit1(g) bit0 沒接
unsigned char code grid[4]={ 0xfb,0xf7,0xef,0xdf };
// 10H H 10m m, 位碼3>>分, 位碼2>>10分,位碼1>>時, 位碼0>>10時, bit3^2(10時),bit3^3(時),bit3^4(10分), bit3^5
unsigned char TempData[4];
//,把段碼的資料存到要顯示的緩衝器上面,利用類似查表的對應方式,送出至顯示器. TempData[ ] 是放置要顯示的7段資料
unsigned char CLCK[6];
unsigned char count;
//--------------------------------
unsigned char GPS_AV;//GPS 信號 A強 V弱
unsigned char CLCK[6];//GPS hr min sec store
unsigned char SPED[6];//速度 000.00
unsigned char RSPED[4];//實際速度 00.xx 節---20131106
unsigned char ALRMSPEED;//實際數度---節
unsigned char disp_tcount;//切換時間計數器
sbit BOT2=P3^2;
sbit BOT3=P3^3;
sbit BOT4=P3^4;
sbit BOT5=P3^5;
bit alrm_flag;
sbit BZ=P3^7;
//---------------------------------
void Display_Data_Operation(void)//以時間分秒為共同語言, 數字轉換成7段顯示
{
TempData[0]= segment[RSPED[0]-'0'];//10節
TempData[1]= segment[RSPED[1]-'0'];//1節
TempData[2]= segment[RSPED[2]-'0']; //.1節
TempData[3]= segment[RSPED[3]-'0'];//.01節
}
void Display_tData_Operation(void)//以時間分秒為共同語言, 數字轉換成7段顯示
{
TempData[0]= segment[CLCK[0]];//时segment[CLCK[1]];
TempData[1]= segment[CLCK[1]];//
TempData[2]= segment[CLCK[2]]; //分
TempData[3]= segment[CLCK[3]];//
}
//--------------------------------------------------------------------------------------------
/*void Display(unsigned char Num)// 把七段顯示出去
{
unsigned char i;
for(i=0;i<Num;i++)
{
DataPort= TempData; // segment;//
// DrivePort= DrivePort & grid;
DrivePort= grid;
DelayMs(5); //0908 update 因閃爍把20改成10 >>5>>2
}
}*/
void Display(unsigned char Num)// 把七段顯示出去
{
unsigned char i;
for(i=0;i<Num;i++)
{
}
DataPort= TempData[0]; // segment;
BOT2=0;
DelayMs(5);
BOT2=1;
DataPort= TempData[1]; // segment;
BOT3=0;
DelayMs(5);
BOT3=1;
DataPort= TempData[2]; // segment;
BOT4=0;
DelayMs(5);
BOT4=1;
DataPort= TempData[3]; // segment;
BOT5=0;
DelayMs(5);
BOT5=1;
}
void DelayUs2x(unsigned char t)
{
while(--t);
}
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
// ///////////////FROM GPS ///////////////////////////////////////////////////
unsigned char Gok;// "$GPRMC," 確認完成
unsigned char REV_DATA;//儲存RS232緩衝區的暫存變數
void Init_Timer0(void);//定时器初始化
//----- FROM GPS PROG -----
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
void Timer0_isr(void) interrupt 1
{
// static unsigned int count;
TH0=(65536-2010)/256; //重新赋值 2ms
TL0=(65536-2010)%256;
count++;
if (count==10)
{
count=0;
disp_flag=1;
disp_tcount++;
if(disp_tcount>100)
{
disp_tcount=0;
dispt_flag=(~dispt_flag);
}
}
}
void UART_Init(void)
{
SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装
TH1 = 0xFA; // TH1: 重装值 4800 11.0592MHz
TR1 = 1; // TR1: timer 1 打开
EA = 1; //打开总中断
ES = 1; //打开串口中断
}
void UART_SER (void) interrupt 4 //來自串口時鐘 1602 程式
{
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
REV_DATA =SBUF; //读入缓冲区的值
rec=1;
// rec_led=1;
}
if(TI) //如果是发送标志位,清零
TI=0;
}
//--20131110--------------------------------
//-------------檢查出小數點 以前的位數-------------2013 11106
unsigned char NUMSPED(void)
{
unsigned char yt=0;
while(SPED[yt]!='.')//內容不得為"," 一但是逗號就跳出
{
yt++;
}
return yt;
}
//------ 把顯示質變成計算值---- 2013 11106
void TRNUM(void)
{
unsigned char aa;
aa=NUMSPED();
switch(aa)
{
case 1:
RSPED[0]='0';
RSPED[1]=SPED[0];
RSPED[2]=SPED[2];
RSPED[3]=SPED[3];
ALRMSPEED=(RSPED[1]-'0');
break;
case 2:
RSPED[0]=SPED[0];
RSPED[1]=SPED[1];
RSPED[2]=SPED[3];
RSPED[3]=SPED[4];
ALRMSPEED=(RSPED[0]-'0')*10+(RSPED[1]-'0');
break;
}
}
void CLCKFL(unsigned char CLCKCT)//填入6個時 分 秒資料
{
unsigned char ct=0;
rec=0;//必要的
while(CLCKCT>ct)//儲存數量
{
while(rec==0);
if(rec==1)
{
CLCK[ct]=REV_DATA-0x30;
rec=0;
ct++;
}
}
}
//填入6個速度資料
void SPEDFL(unsigned char SPEDCT)
{
unsigned char yt=0;
rec=0;//必要的
while(SPEDCT >yt)//儲存數量
{
while(rec==0);
if(rec==1)
{
// SPED[yt]=REV_DATA-0x30;
SPED[yt]=REV_DATA;
rec=0;
yt++;
}
}
}
//0819 跳過幾個逗號
void JPDM(unsigned char DM)
{
rec=0;
while(DM)//>dmt
{
while(rec==0);
// if (rec==1)
{
if(REV_DATA == ',')
{
rec=0;
DM--;//dmt++
}
}
}
}
unsigned char Get_Gps(void)//改寫 gps 讀取程式 把 Gok=GPRMC_K() 取消
{
unsigned char TT;
if(rec==1)
{
if(REV_DATA == '$')
{
rec=0;
}
}
else
{
return 0;
}
while(rec==0);
if(REV_DATA == 'G')
{
rec=0;
}
while(rec==0);
if(REV_DATA == 'P')
{
rec=0;
}
while(rec==0);
if(REV_DATA == 'R')//一路比較下去全部要相同 "GPVTG,"
{
rec=0;
}
else
{
return 0;
}
while(rec==0);
if(REV_DATA == 'M')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
while(rec==0);
if(REV_DATA == 'C')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
while(rec==0);
if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
{
rec=0;
}
else
{
return 0;
}
CLCKFL(6);//取 時分秒
JPDM(1);
while(rec==0);
{
GPS_AV = REV_DATA;
}
JPDM(5);//跳過5個逗號取速度000.00km
SPEDFL(6);//取 速度000.00km
TRNUM();
TT=CLCK[0]*10+CLCK[1]+8;//時間補差格林威治對中原標準
if(TT>23)
TT-=24;
CLCK[0]=TT/10;
CLCK[1]=TT%10;
return 1;
}
//--------------------------------------------------------
// --------- GPS MAIN PROGRAM -------------
void main(void)
{
unsigned char STR_DIS=5;
Init_Timer0();
UART_Init();
CLCK[0]=1;
CLCK[1]=2;
CLCK[2]=0;
CLCK[3]=0;
while(1)
{
Get_Gps();
Gok=1;//----------------------------test
if(Gok==1)
{
if(dispt_flag)
{
Display_tData_Operation ();
}
else
{
Display_Data_Operation ();//轉換相關值到顯示
}
}
if(ALRMSPEED>26)
{
alrm_flag=0;//-
BZ=0;
}
else
{
alrm_flag=1;//*
BZ=1;
}
if(disp_flag==1)
{
disp_flag=0;
Display(4);
}
Display(4);
}
}
//$GPRMC,115900.000,A,,N,,E,00.38,, test pattern
|
評分
-
12
查看全部評分
-
|