痞酷網_PIGOO

 找回密碼
 立即註冊
!!! [系統偵測到廣告阻擋軟體] !!!

如果您覺得痞酷網對您有些許幫助,或者您認同痞酷網的理想,

那麼希望您將痞酷網設定為白名單.

並請在上論壇的時候,動動您的手指,用行動支持我們.

謝謝!
查看: 4543|回復: 13

求助: LCM 2402 顯示不全的問題

[複製鏈接]
發表於 2014-1-5 00:49:05 | 顯示全部樓層 |閱讀模式
  請有相關經驗的大大提示一下,感恩!!

手頭有 LCM 2402 想要顯示 經緯度 日期 時間 速度 卻發現 第一排的前幾個字母都顯示出問題,假如把他改成 16字問題就不會發生, 不知道這是什麼原因造成的!! 不知道應該如何解決!!

DSC07706.JPG

DSC07707.JPG

顯示異常的程式部分
void Display(void)
{

//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
DisplayWord[0]='2';
DisplayWord[1]='0';
DisplayWord[2]=DATE[4];// mm dd yy
DisplayWord[3]=DATE[5];//  mm dd
DisplayWord[4]='/';
DisplayWord[5]=DATE[0];//  mm dd
DisplayWord[6]=DATE[1];//  mm dd
DisplayWord[7]= '/';
DisplayWord[8]=DATE[2];//  mm dd
DisplayWord[9]= DATE[3];// mm dd
DisplayWord[10]=' ';
DisplayWord[11]=CLCK[0]+'0';//GPS hr min sec store
DisplayWord[12]=CLCK[1]+'0';//GPS hr min sec store
DisplayWord[13]=':';
DisplayWord[14]=CLCK[2]+'0';//GPS hr min sec store
DisplayWord[15]=CLCK[3]+'0';//GPS hr min sec store
DisplayWord[16]=':';
DisplayWord[17]=CLCK[4]+'0';//GPS hr min sec store
DisplayWord[18]=CLCK[5]+'0';//GPS hr min sec store
DisplayWord[19]=' ';
DisplayWord[20]=RSPED[0];
DisplayWord[21]=RSPED[1];
DisplayWord[22]='.';
DisplayWord[23]=RSPED[2];
LCD_Write_String(0,0,DisplayWord);//显示第2行  

DisplayWord[0]='N';
DisplayWord[1]=':';
DisplayWord[2]=LATI[0];
DisplayWord[3]=LATI[1];
DisplayWord[4]=LATI[2];
DisplayWord[5]=LATI[3];
DisplayWord[6]= LATI[4];
DisplayWord[7]= LATI[5];
DisplayWord[8]= LATI[6];
DisplayWord[9]= LATI[7];
DisplayWord[10]=LATI[8];
DisplayWord[11]=' ';
DisplayWord[12]='E';
DisplayWord[13]=':';
DisplayWord[14]=LONGI[0];
DisplayWord[15]=LONGI[1];
DisplayWord[16]=LONGI[2];
DisplayWord[17]=LONGI[3];
DisplayWord[18]=LONGI[4];
DisplayWord[19]=LONGI[5];
DisplayWord[20]=LONGI[6];
DisplayWord[21]=LONGI[7];
DisplayWord[22]=LONGI[8];
DisplayWord[23]=LONGI[9];
LCD_Write_String(0,1,DisplayWord);//显示第一行

}

若是改成
LCD_Write_String(0,0,"123456789ABCDEFGHIJKLMNOPQ");//显示第一行
LCD_Write_String(0,1,"!@#$%^&*()1234567890ASDFGH");//显示第二行
就正常!!

我曾經試著把他分兩次顯示,或是把 GPS的訊號分開來讀都沒辦法解決!! 顯示更新時間 0.2秒 或是 1秒 好像也沒辦法改善!!
發表於 2014-1-5 09:46:03 | 顯示全部樓層
既然用常數字串會正常,那就可以排除是硬體問題,很可能是記憶體宣告太多導致52記憶體不足互相覆蓋?
將不正常的程式字串陣列指定值全部以常數替代,如:
DisplayWord[0]='2';
DisplayWord[1]='0';
DisplayWord[2]='1';
DisplayWord[3]='4';

再觀察看看....
 樓主| 發表於 2014-1-5 10:46:03 | 顯示全部樓層
ysc 發表於 2014-1-5 09:46 AM static/image/common/back.gif
既然用常數字串會正常,那就可以排除是硬體問題,很可能是記憶體宣告太多導致52記憶體不足互相覆蓋?
將不 ...

YSC大:
   
    問題暫時解決 ,感謝幫忙!
        Display();//        longitude
        Display_WFL();// time & date         
        DelayMs(20);//--------- 延遲時間增加為 20MS
//顯示寫字串把判斷句去除 原先判斷寫第一行或是第二行就直接設定
LCD_Write_String0(0,0,DisplayWord1);//显示第一行        longitude        

LCD_Write_String1(0,1,DisplayWord);//显示第一行 time & date       

//先顯示時間不成功 先顯示經緯度成功,問題待查...       
       
發表於 2014-1-5 11:30:15 | 顯示全部樓層
本帖最後由 xiaolaba 於 2014-1-5 11:32 AM 編輯

大大厲害.
又有新用途.
雖然沒經驗, 不一定能幫上忙, 不過猜想是動態記憶體用多了, 但是沒有動到 STACK 也是奇怪
你看看整個流程是否還有其他BUG. 最好用 DEBUGGER 設斷點看, 不然沒法除錯的
 樓主| 發表於 2014-1-5 12:53:10 | 顯示全部樓層
xiaolaba 發表於 2014-1-5 11:30 AM static/image/common/back.gif
大大厲害.
又有新用途.
雖然沒經驗, 不一定能幫上忙, 不過猜想是動態記憶體用多了, 但是沒有動到 STACK 也 ...

xiaolaba 大:
   我是半路出家的!! 不知道 瞎咪是 STACK? 我也不會設 DEBUGGER 設斷點,我都是東猜西想 用串口大師 傳送模擬信號以判斷程式是否有問題!! 還不錯STC 的 MCU 可以非常方便的"下載"要是使用 TEXTOOL 那會瘋掉喔!!
發表於 2014-1-5 16:59:54 | 顯示全部樓層
antlu 發表於 2014-1-5 12:53 PM static/image/common/back.gif
xiaolaba 大:
   我是半路出家的!! 不知道 瞎咪是 STACK? 我也不會設 DEBUGGER 設斷點,我都是東猜西想 用 ...

DisplayWord[], 這個在你的定義檔應該是把它設成陣列, 並且是 RAM 中的 [一串變數], 所以會用到 RAM

一般, CPU 要呼叫 附程式前, 先要把 PC / IP 和其他寄存器的值保存起來, 也會用到 RAM, 這些位置就是 STACK.

所以你的問題 很可能是 這些臨時使用的 RAM 引起的, 不用DEBUGGER 很難查的 ,特別是寫 C 然後有選優化選項的話.

所以你要看的是, 呼叫一次 LCD_WRITE 到底佔用了多少 RAM, 或是有沒有其他副程搶進來占用更多的RAM.

而這些都必須要 用DEBUGGE 幫助, 除非你是很熟悉這樣的MCU. 或者自己寫一段程式, 插入到有懷疑的地方, 從 RS232 輸出看寄存器的值
發表於 2014-1-5 17:59:34 | 顯示全部樓層
因為mcu本身資源就不是很大,所以用c來寫時是沒辦法像組合語言一樣能完全控製好mcu資源
加上編譯後的情形都不是使用者能完全掌控的
如果只有初期的陣列顯示不正常,應該是編譯後在對暫存器先放入堆疊記憶體有衝突
LCD_Write_String(0,1,DisplayWord);//显示第一行

LCD_Write_String(0,0,"123456789ABCDEFGHIJKLMNOPQ");//显示第一行
有時確實會有不一樣,因為一個是傳入字串陣列,另一個是直接傳入字串
要看陣列的型態和LCD_Write_String()本身的型態有沒有相同
編譯後的mcu在處理字串陣列和己設定好內容的字串處理方式不同
而陣列在mcu本身被分配到那也不知道,24字元時的2014確實有送出到lcm
因為游標有跟著跑也正確,所以只是送出的數值與實际數值不對而己
即然都會固定出現在字首錯誤,應該可以在初期顯示作偵錯方式
多加幾行實际顯示出來作debug,和顯示更新時間 0.2秒 或是 1秒 是沒什麼關係
看不到全部程式所以也都只能用推測的,
和硬體沒什麼關係,單純程式問題,
 樓主| 發表於 2014-1-5 22:34:12 | 顯示全部樓層
legion 發表於 2014-1-5 05:59 PM static/image/common/back.gif
因為mcu本身資源就不是很大,所以用c來寫時是沒辦法像組合語言一樣能完全控製好mcu資源
加上編譯後的情形都 ...

LEGION大:
   這是相關的程式 請參考!!



void DelayUs2x(unsigned char t)
{   
while(--t);
}

void DelayMs(unsigned char t)
{
     
while(t--)
{
     DelayUs2x(245);
         DelayUs2x(245);
}
}

//---------------------------------
/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
//nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{  
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
//_nop_();
EN_CLR;
}
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();//---------------2014 add
EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/

void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{     
if (y == 0)
        {     
         LCD_Write_Com(0x80 + x);     //表示第一行
        }
else
        {      
        LCD_Write_Com(0xC0 + x);      //表示第二行
        }        
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}

// write string line 1
void LCD_Write_String0(unsigned char x,unsigned char *s)
{     
         LCD_Write_Com(0x80 + x);     //表示第一行
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}

//write string line 2
void LCD_Write_String1(unsigned char x,unsigned char *s)
{     
        LCD_Write_Com(0xC0 + x);      //表示第二行
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}


---------------顯示第二行 把要顯示的資料放入 DisplayWord[24]內 -----

void Display_WFL(void)
{
//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
DisplayWord[0]='2';
DisplayWord[1]='0';
DisplayWord[2]=DATE[4];// mm dd yy
DisplayWord[3]=DATE[5];//  mm dd
DisplayWord[4]='/';
DisplayWord[5]=DATE[0];//  mm dd
DisplayWord[6]=DATE[1];//  mm dd
DisplayWord[7]= '/';
DisplayWord[8]=DATE[2];//  mm dd
DisplayWord[9]= DATE[3];// mm dd
DisplayWord[10]=' ';
DisplayWord[11]=CLCK[0]+'0';//GPS hr min sec store
DisplayWord[12]=CLCK[1]+'0';//GPS hr min sec store
DisplayWord[13]=':';
DisplayWord[14]=CLCK[2]+'0';//GPS hr min sec store
DisplayWord[15]=CLCK[3]+'0';//GPS hr min sec store
DisplayWord[16]=':';
DisplayWord[17]=CLCK[4]+'0';//GPS hr min sec store
DisplayWord[18]=CLCK[5]+'0';//GPS hr min sec store
DisplayWord[19]=' ';
DisplayWord[20]=RSPED[0];
DisplayWord[21]=RSPED[1];
DisplayWord[22]='.';
DisplayWord[23]=RSPED[2];

}
---------------顯示第一行 把要顯示的資料放入 DisplayWord1[24]內 -----
void Display(void)
{
DisplayWord1[0]='N';
DisplayWord1[1]=':';
DisplayWord1[2]=LATI[0];
DisplayWord1[3]=LATI[1];
DisplayWord1[4]=LATI[2];
DisplayWord1[5]=LATI[3];
DisplayWord1[6]= LATI[4];
DisplayWord1[7]= LATI[5];
DisplayWord1[8]= LATI[6];
DisplayWord1[9]= LATI[7];
DisplayWord1[10]=LATI[8];
DisplayWord1[11]=' ';
DisplayWord1[12]='E';
DisplayWord1[13]=':';
DisplayWord1[14]=LONGI[0];
DisplayWord1[15]=LONGI[1];
DisplayWord1[16]=LONGI[2];
DisplayWord1[17]=LONGI[3];
DisplayWord1[18]=LONGI[4];
DisplayWord1[19]=LONGI[5];
DisplayWord1[20]=LONGI[6];
DisplayWord1[21]=LONGI[7];
DisplayWord1[22]=LONGI[8];
DisplayWord1[23]=LONGI[9];
}

-----------------------------


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(1);
LATIFL(9);//get latitude data
JPDM(2);
LONGIFL(10);//get longitude data
JPDM(2);
SPEDFL(6);//取 速度000.00km
//***********************************************
JPDM(1);
DATEFL(6);
TT=CLCK[0]*10+CLCK[1]+8;//時間補差格林威治對中原標準
if(TT>23)
TT-=24;
CLCK[0]=TT/10;
CLCK[1]=TT%10;
TRNUM();
Display();//        longitude MOVE FROM MAIN
Display_WFL();// time & date         
  return 1;
  //$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
  }





//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
// ---------  GPS MAIN PROGRAM -------------
/*
        起始設定 中斷定時器 UART LCM  (串聯式LCM 的 74595)
        迴圈 取 GPS 得到 時間 經緯度 方向 高度 速度 等資料
        送到顯示區處理
        比較速度資料 進行判斷警報
       
        */
void main(void)
{
LCD_Init();              //初始化液晶
DelayMs(20);          //延时有助于稳定
LCD_Clear();          //清屏
Init_Timer0();        //定时器0初始化
UART_Init();


while(1)
{
Get_Gps();                
DelayMs(20);
LCD_Write_String0(0,DisplayWord1);//显示第一行        longitude        
LCD_Write_String1(0,DisplayWord);//显示第一行 time & date               
disp_flag=0;
                }
  
  }
}
發表於 2014-1-6 00:14:26 | 顯示全部樓層
antlu 發表於 2014-1-5 10:34 PM static/image/common/back.gif
LEGION大:
   這是相關的程式 請參考!!

這個不完整吧,所有的參數宣告都沒有
想看的應該是可以直接編譯的完整程式,
想看一下編譯後轉成的組合語言語法,
大概才能看出為何初期顯示時為何數值會變是堆疊重疊
還是有變數相同,如果16字元時不會有誤,那20字元時呢
如果是自己在測試的話,應該會先停止gps動作
而直接在字串陣列一個字一個字填入再顯示來看,看是否初始字元異常
DisplayWord[0]='2';
DisplayWord[1]='0';
DisplayWord[2]='1';
DisplayWord[3]="4';
DisplayWord[4]='/';
 樓主| 發表於 2014-1-6 01:36:24 | 顯示全部樓層
legion 發表於 2014-1-6 12:14 AM static/image/common/back.gif
這個不完整吧,所有的參數宣告都沒有
想看的應該是可以直接編譯的完整程式,
想看一下編譯後轉成的組合語言 ...

legion大:
  驗證結果如下
void Display_WFL(void)
{
         
//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
DisplayWord[0]='2';
DisplayWord[1]='0';//
DisplayWord[2]='0';//DATE[4];// mm dd yy
DisplayWord[3]='0';//DATE[5];//  mm dd
DisplayWord[4]='/';
DisplayWord[5]='0';//DATE[0];//  mm dd
DisplayWord[6]='0';//DATE[1];//  mm dd
DisplayWord[7]= '/';
DisplayWord[8]='0';//DATE[2];//  mm dd
DisplayWord[9]= '0';//DATE[3];// mm dd
DisplayWord[10]=' ';
DisplayWord[11]='0';//CLCK[0]+'0';//GPS hr min sec store
DisplayWord[12]='0';//CLCK[1]+'0';//GPS hr min sec store
DisplayWord[13]=':';
DisplayWord[14]='0';//CLCK[2]+'0';//GPS hr min sec store
DisplayWord[15]='0';//CLCK[3]+'0';//GPS hr min sec store
DisplayWord[16]=':';
DisplayWord[17]='0';//CLCK[4]+'0';//GPS hr min sec store
DisplayWord[18]='0';//CLCK[5]+'0';//GPS hr min sec store
DisplayWord[19]=' ';
DisplayWord[20]=' ';//RSPED[0];
DisplayWord[21]=(Gok/100)+'0';//RSPED[1];
DisplayWord[22]=(Gok%100)/10+'0';//'.';
DisplayWord[23]=(Gok%10)+'0';//RSPED[2];
        DelayMs(20);
LCD_Write_String1(0,DisplayWord);//显示第一行 time & date                               
}

void Display(void)
{
DisplayWord1[0]='N';
DisplayWord1[1]=':';
DisplayWord1[2]='0';//LATI[0];
DisplayWord1[3]='0';//LATI[1];
DisplayWord1[4]='0';//LATI[2];
DisplayWord1[5]='0';//LATI[3];
DisplayWord1[6]='0';// LATI[4];
DisplayWord1[7]='0';// LATI[5];
DisplayWord1[8]= '0';//LATI[6];
DisplayWord1[9]= '0';//LATI[7];
DisplayWord1[10]='0';//LATI[8];
DisplayWord1[11]=' ';
DisplayWord1[12]='E';
DisplayWord1[13]=':';
DisplayWord1[14]='0';//LONGI[0];
DisplayWord1[15]='0';//LONGI[1];
DisplayWord1[16]='0';//LONGI[2];
DisplayWord1[17]='0';//LONGI[3];
DisplayWord1[18]='0';//LONGI[4];
DisplayWord1[19]='0';//LONGI[5];
DisplayWord1[20]='0';//LONGI[6];
DisplayWord1[21]='0';//LONGI[7];
DisplayWord1[22]='0';//LONGI[8];
DisplayWord1[23]='0';//LONGI[9];
                DelayMs(5);
         LCD_Write_String0(0,DisplayWord1);//显示第一行        longitude                  
}


1.取消 GPS讀取動作顯示正常.
2.加上 GPS 讀取動作之後 第一個字 N 不顯示,偶而 N: 會變亂碼(機率很小)
3. GPS讀取+第二行顯示 相關變數如下,則 N: 會變亂碼 (機率更高一些)

void Display_WFL(void)
{
         
//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
DisplayWord[0]='2';
DisplayWord[1]='0';//
DisplayWord[2]=DATE[4];// mm dd yy
DisplayWord[3]=DATE[5];//  mm dd
DisplayWord[4]='/';
DisplayWord[5]=DATE[0];//  mm dd
DisplayWord[6]=DATE[1];//  mm dd
DisplayWord[7]= '/';
DisplayWord[8]=DATE[2];//  mm dd
DisplayWord[9]= DATE[3];// mm dd
DisplayWord[10]=' ';
DisplayWord[11]=CLCK[0]+'0';//GPS hr min sec store
DisplayWord[12]=CLCK[1]+'0';//GPS hr min sec store
DisplayWord[13]=':';
DisplayWord[14]=CLCK[2]+'0';//GPS hr min sec store
DisplayWord[15]=CLCK[3]+'0';//GPS hr min sec store
DisplayWord[16]=':';
DisplayWord[17]=CLCK[4]+'0';//GPS hr min sec store
DisplayWord[18]=CLCK[5]+'0';//GPS hr min sec store
DisplayWord[19]=' ';
DisplayWord[20]=' ';//RSPED[0];
DisplayWord[21]=(Gok/100)+'0';//RSPED[1];
DisplayWord[22]=(Gok%100)/10+'0';//'.';
DisplayWord[23]=(Gok%10)+'0';//RSPED[2];
        DelayMs(20);
LCD_Write_String1(0,DisplayWord);//显示第一行 time & date                               
}

void Display(void)
{
DisplayWord1[0]='N';
DisplayWord1[1]=':';
DisplayWord1[2]='0';//LATI[0];
DisplayWord1[3]='0';//LATI[1];
DisplayWord1[4]='0';//LATI[2];
DisplayWord1[5]='0';//LATI[3];
DisplayWord1[6]='0';// LATI[4];
DisplayWord1[7]='0';// LATI[5];
DisplayWord1[8]= '0';//LATI[6];
DisplayWord1[9]= '0';//LATI[7];
DisplayWord1[10]='0';//LATI[8];
DisplayWord1[11]=' ';
DisplayWord1[12]='E';
DisplayWord1[13]=':';
DisplayWord1[14]='0';//LONGI[0];
DisplayWord1[15]='0';//LONGI[1];
DisplayWord1[16]='0';//LONGI[2];
DisplayWord1[17]='0';//LONGI[3];
DisplayWord1[18]='0';//LONGI[4];
DisplayWord1[19]='0';//LONGI[5];
DisplayWord1[20]='0';//LONGI[6];
DisplayWord1[21]='0';//LONGI[7];
DisplayWord1[22]='0';//LONGI[8];
DisplayWord1[23]='0';//LONGI[9];
                DelayMs(5);
         LCD_Write_String0(0,DisplayWord1);//显示第一行        longitude                  
}
 樓主| 發表於 2014-1-6 01:37:32 | 顯示全部樓層
完整程式如下:

/*20131120  完成 GPS顯示時間 與速度節 超速50公里(27節)ALARM
40公里以上 選擇性 警報 50公里以上一定警報 60公里以上警報停止  
$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,,    test pattern


*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
#include<intrins.h>
bit disp_flag;
bit dispt_flag;//切換顯示
bit rec;  // receive rs232 OK_flag
bit alrm_flag;
bit Gok_flag;
sbit AL40=P3^1;//alarm 40/50Km selection
sbit BZ=P3^7;// buzzer output
sbit RS = P2^4;   // LCM 2402 pin i/o
sbit RW = P2^5;
sbit EN = P2^6;
#define DataPort P0
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1


unsigned char DisplayWord[24];
unsigned char DisplayWord1[24];
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 DATE[6];// yy mm dd
unsigned char LATI[9];//latitude
unsigned char LONGI[10];//longitude
unsigned char SPED[6];//速度 000.00
unsigned char RSPED[4];//實際速度 00.xx 節---20131106
unsigned char ALRMSPEED;//實際數度---節
unsigned char Gok;// "$GPRMC," 確認完成
unsigned char REV_DATA;//儲存RS232緩衝區的暫存變數
//unsigned char disp_tcount;//切換時間計數器
//----------------------------------------------
void DelayUs2x(unsigned char t);
void DelayMs(unsigned char t);
bit LCD_Check_Busy(void) ;//忙線檢查
void LCD_Write_Com(unsigned char com) ;//lcm寫命令
void LCD_Write_Data(unsigned char Data) ;//lcm寫資料
void LCD_Clear(void) ;//清除 lcm
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) ;//寫字串
void LCD_Init(void) ;//lcm 參數重設
void Display(void);//顯示lcm資料
void Init_Timer0(void);//定时器初始化
void Timer0_isr(void);// interrupt 1 ;
void UART_Init(void);
void UART_SER (void);// interrupt 4 //來自串口時鐘 1602 程式;
unsigned char NUMSPED(void);//小數點檢查
void TRNUM(void);//轉換顯示位置
void CLCKFL(unsigned char CLCKCT);//填入6個時 分 秒資料
void LATIFL(unsigned char LATICT);//LATICT: Latitude count
void LONGIFL(unsigned char LONGICT);//LONGICT: Longitude count
void SPEDFL(unsigned char SPEDCT);//SPEDCT: speed count
void DATEFL(unsigned char DATECT);//填入6個時 分 秒資料
void JPDM(unsigned char DM);
unsigned char  Get_Gps(void);//改寫 gps 讀取程式 把 Gok=GPRMC_K() 取消


//------------------------------------------------






void DelayUs2x(unsigned char t)
{   
while(--t);
}

void DelayMs(unsigned char t)
{
     
while(t--)
{
     DelayUs2x(245);
         DelayUs2x(245);
}
}

//---------------------------------
/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
//nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{  
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
//_nop_();
EN_CLR;
}
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();//---------------2014 add
EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
/*
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{     
if (y == 0)
        {     
         LCD_Write_Com(0x80 + x);     //表示第一行
        }
else
        {      
        LCD_Write_Com(0xC0 + x);      //表示第二行
        }        
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}
*/
// write string line 1
void LCD_Write_String0(unsigned char x,unsigned char *s)
{     
         LCD_Write_Com(0x80 + x);     //表示第一行
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}

//write string line 2
void LCD_Write_String1(unsigned char x,unsigned char *s)
{     
        LCD_Write_Com(0xC0 + x);      //表示第二行
while (*s)
        {     
LCD_Write_Data( *s);     
s ++;     
        }
}

/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
/*
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{     
if (y == 0)
        {     
        LCD_Write_Com(0x80 + x);     
        }   
else
        {     
        LCD_Write_Com(0xC0 + x);     
        }        
LCD_Write_Data( Data);  
}
*/
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
   LCD_Write_Com(0x38);    /*显示模式设置*/
   DelayMs(5);
   LCD_Write_Com(0x38);
   DelayMs(5);
   LCD_Write_Com(0x38);
   DelayMs(5);
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/
   LCD_Write_Com(0x01);    /*显示清屏*/
   LCD_Write_Com(0x06);    /*显示光标移动设置*/
   DelayMs(5);
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }





//--------------------------------------------------------------------------------------------

void Display_WFL(void)
{
         
//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
DisplayWord[0]='2';
DisplayWord[1]='0';//
DisplayWord[2]=DATE[4];// mm dd yy
DisplayWord[3]=DATE[5];//  mm dd
DisplayWord[4]='/';
DisplayWord[5]=DATE[0];//  mm dd
DisplayWord[6]=DATE[1];//  mm dd
DisplayWord[7]= '/';
DisplayWord[8]=DATE[2];//  mm dd
DisplayWord[9]= DATE[3];// mm dd
DisplayWord[10]=' ';
DisplayWord[11]=CLCK[0]+'0';//GPS hr min sec store
DisplayWord[12]=CLCK[1]+'0';//GPS hr min sec store
DisplayWord[13]=':';
DisplayWord[14]=CLCK[2]+'0';//GPS hr min sec store
DisplayWord[15]=CLCK[3]+'0';//GPS hr min sec store
DisplayWord[16]=':';
DisplayWord[17]=CLCK[4]+'0';//GPS hr min sec store
DisplayWord[18]=CLCK[5]+'0';//GPS hr min sec store
DisplayWord[19]=' ';
DisplayWord[20]=' ';//RSPED[0];
DisplayWord[21]=(Gok/100)+'0';//RSPED[1];
DisplayWord[22]=(Gok%100)/10+'0';//'.';
DisplayWord[23]=(Gok%10)+'0';//RSPED[2];
        DelayMs(20);
LCD_Write_String1(0,DisplayWord);//显示第一行 time & date                               
}

void Display(void)
{
DisplayWord1[0]='N';
DisplayWord1[1]=':';
DisplayWord1[2]='0';//LATI[0];
DisplayWord1[3]='0';//LATI[1];
DisplayWord1[4]='0';//LATI[2];
DisplayWord1[5]='0';//LATI[3];
DisplayWord1[6]='0';// LATI[4];
DisplayWord1[7]='0';// LATI[5];
DisplayWord1[8]= '0';//LATI[6];
DisplayWord1[9]= '0';//LATI[7];
DisplayWord1[10]='0';//LATI[8];
DisplayWord1[11]=' ';
DisplayWord1[12]='E';
DisplayWord1[13]=':';
DisplayWord1[14]='0';//LONGI[0];
DisplayWord1[15]='0';//LONGI[1];
DisplayWord1[16]='0';//LONGI[2];
DisplayWord1[17]='0';//LONGI[3];
DisplayWord1[18]='0';//LONGI[4];
DisplayWord1[19]='0';//LONGI[5];
DisplayWord1[20]='0';//LONGI[6];
DisplayWord1[21]='0';//LONGI[7];
DisplayWord1[22]='0';//LONGI[8];
DisplayWord1[23]='0';//LONGI[9];
                DelayMs(5);
         LCD_Write_String0(0,DisplayWord1);//显示第一行        longitude                  
}


//  ///////////////FROM GPS ///////////////////////////////////////////////////

//----- 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-20000)/256;                  //重新赋值 20ms
TL0=(65536-20000)%256;

count++;//顯示用 20ms*30=600ms
if (count==30)
  {
   count=0;//
   disp_flag=1;
        //        Gok++;
   }
}

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++;
          }
        }
}

void LATIFL(unsigned char LATICT)//LATICT: Latitude count
{
  unsigned char yt=0;
  rec=0;//必要的
   while(LATICT >yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
                         LATI[yt]=REV_DATA;
      rec=0;
          yt++;
          }
        }
}

void LONGIFL(unsigned char LONGICT)//LONGICT: Longitude count
{
  unsigned char yt=0;
  rec=0;//必要的
   while(LONGICT >yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
                         LONGI[yt]=REV_DATA;
      rec=0;
          yt++;
          }
        }
}

//填入6個速度資料
void SPEDFL(unsigned char SPEDCT)//SPEDCT: speed count
{
  unsigned char yt=0;
  rec=0;//必要的
   while(SPEDCT >yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
                 SPED[yt]=REV_DATA;
      rec=0;
          yt++;
          }
        }
}

void DATEFL(unsigned char DATECT)//SPEDCT: speed count
{
  unsigned char yt=0;
  rec=0;//必要的
   while(DATECT >yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
                 DATE[yt]=REV_DATA;
      rec=0;
          yt++;
          }
        }
}


//0819 跳過幾個逗號

void JPDM(unsigned char DM)
{
  rec=0;
  while(DM)//>dmt
   {
    while(rec==0);
         {
     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(1);
  LATIFL(9);//get latitude data
    JPDM(2);
        LONGIFL(10);//get longitude data
    JPDM(2);
        SPEDFL(6);//取 速度000.00km
//***********************************************
  JPDM(1);
        DATEFL(6);

TT=CLCK[0]*10+CLCK[1]+8;//時間補差格林威治對中原標準
  if(TT>23)
     TT-=24;
         CLCK[0]=TT/10;
         CLCK[1]=TT%10;
TRNUM();
        //--------------
Gok++;
        Gok_flag=1;
       
        //----------------
  return 1;
  //$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
  }


/*
void GokTR(void)
        {
               
        }
*/
//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
// ---------  GPS MAIN PROGRAM -------------
/*
        起始設定 中斷定時器 UART LCM  (串聯式LCM 的 74595)
        迴圈 取 GPS 得到 時間 經緯度 方向 高度 速度 等資料
        送到顯示區處理
        比較速度資料 進行判斷警報
       
        */
void main(void)
{
LCD_Init();              //初始化液晶
DelayMs(20);          //延时有助于稳定
LCD_Clear();          //清屏
Init_Timer0();        //定时器0初始化
UART_Init();
Gok=0;

while(1)
{
Get_Gps();         


//Gok_flag=1;//----------------------------test
                  /*
  if(Gok==1)
      {
                                if(dispt_flag && alrm_flag )
                                {
                                        Display_tData_Operation ();       
                                }
                                else
                                {
       Display_Data_Operation ();//轉換相關值到顯示
           }
         }

         
                         if(ALRMSPEED>26 && ALRMSPEED<30)//時速在 50~60之間警報
                {
                        alrm_flag=0;//-
                        BZ=0;
                }
                                else
                {
                        alrm_flag=1;//*
            BZ=1;
                }               

                                 if(AL40==0)
                                {
                         if(ALRMSPEED>21 && ALRMSPEED<30)//時速在 40~60之間警報
                {
                        alrm_flag=0;//-
                        BZ=0;
                }
                else
                                {
                        alrm_flag=1;//*
            BZ=1;
                }
        }
         
         */


if(disp_flag && Gok_flag)//==1)
   {
   
                 /*
                 if(dispt_flag)
                 {
     Display();
                 }
                 else
                 {
                  Display2();
    }
                 */
        DelayMs(5);
                Display();//        longitude MOVE FROM MAIN
        //        DelayMs(5);
        // LCD_Write_String0(0,DisplayWord1);//显示第一行        longitude                  
                        DelayMs(20);
    Display_WFL();// time & date               


                 
//        DelayMs(20);
//LCD_Write_String1(0,DisplayWord);//显示第一行 time & date                                 
                   disp_flag=0;
                         Gok_flag=0;
                }
  
  }
}
//$GPRMC,115900.000,A,,N,,E,00.38,,    test pattern
//problem is get character from word-matrix
發表於 2014-1-6 12:57:44 | 顯示全部樓層
unsigned char CLCK[6];
unsigned char CLCK[6];//GPS hr min sec store
這兩行請先去掉1個,重覆定義,
另在顯示時是否應該將UART的中斷先停止
如果關閉GPS就正常,有可能是要進入顯示前被UART給中斷
加上每次要顯示前你又對字串陣列重作一次輸入,
可以考慮陣列變成static模式,加上初始便定義便能在後面不用多作重覆
差不多51本身的RAM區都快被陣列吃光了,
這是用那一棵MCU去作的,不是都在用204EA在玩嗎,有硬體UART應該不是吧
 樓主| 發表於 2014-1-6 22:08:31 | 顯示全部樓層
legion 發表於 2014-1-6 12:57 PM static/image/common/back.gif
unsigned char CLCK[6];
unsigned char CLCK[6];//GPS hr min sec store
這兩行請先去掉1個,重覆定義,

LEGION大:
   我用的是 STC89C52RD 40PIN 12T 的 MCU  同 89S52
  因為 GPS 的時間 座標 速度隨時都會有變化 所以我的做法是 每次作GPS渠取資料後就塞到 陣列裡 要顯示的時候再把他放到顯示區裡面! 你的建議要把他直接放到顯示區裡面這我想想應該怎麼改!!
另外 陣列變成 STATIC 模式,這一點我就不明白了,因為以記得 STATIC 和 全域變數(Global variable) 功能相像不是嗎?
 樓主| 發表於 2014-1-6 22:37:31 | 顯示全部樓層
legion 發表於 2014-1-6 12:57 PM static/image/common/back.gif
unsigned char CLCK[6];
unsigned char CLCK[6];//GPS hr min sec store
這兩行請先去掉1個,重覆定義,

LEGION大:
   感謝教導!! 目前顯示的問題已經解決!! 我把經緯度的變數省略直接就寫到 顯示的變數裡!! 省下了19個變數空間,最初(也是一般的做法)先寫到經緯度陣列裡再把他送到顯示陣列中,然後決定要顯示在第幾行這樣 1602只要 16個空間,我目前把 經緯度 日期 時間 ..等一一分開好處可以直接寫入,缺點是 總共要 48個空間(2402 24*2=48),目前都沒問題我再把以前為了解決問題所增加的 延遲等動作程式去掉試看看!!

這一段沒有改變
void Display_WFL(void)
{
       
//$GPRMC,115900.000,A,3723.2475,N,12158.3416,E,00.38,123.56,010414,,
DisplayWord[0]='2';
DisplayWord[1]='0';//
DisplayWord[2]=DATE[4];// mm dd yy
DisplayWord[3]=DATE[5];//  mm dd
DisplayWord[4]='/';
DisplayWord[5]=DATE[0];//  mm dd
DisplayWord[6]=DATE[1];//  mm dd
DisplayWord[7]= '/';
DisplayWord[8]=DATE[2];//  mm dd
DisplayWord[9]= DATE[3];// mm dd
DisplayWord[10]=' ';
DisplayWord[11]=CLCK[0]+'0';//GPS hr min sec store
DisplayWord[12]=CLCK[1]+'0';//GPS hr min sec store
DisplayWord[13]=':';
DisplayWord[14]=CLCK[2]+'0';//GPS hr min sec store
DisplayWord[15]=CLCK[3]+'0';//GPS hr min sec store
DisplayWord[16]=':';
DisplayWord[17]=CLCK[4]+'0';//GPS hr min sec store
DisplayWord[18]=CLCK[5]+'0';//GPS hr min sec store
DisplayWord[19]=' ';
DisplayWord[20]=' ';//RSPED[0];
DisplayWord[21]=(Gok/100)+'0';//RSPED[1];
DisplayWord[22]=(Gok%100)/10+'0';//'.';
DisplayWord[23]=(Gok%10)+'0';//RSPED[2];
        DelayMs(20);
LCD_Write_String1(0,DisplayWord);//显示第一行 time & date                               
}

void Display(void)
{ 這一段有改變
DisplayWord1[0]='N';
DisplayWord1[1]=':';
//DisplayWord1[2]=LATI[0];
//DisplayWord1[3]=LATI[1];
//DisplayWord1[4]=LATI[2];
//DisplayWord1[5]=LATI[3];
//DisplayWord1[6]=LATI[4];
//DisplayWord1[7]=LATI[5];
//DisplayWord1[8]= LATI[6];
//DisplayWord1[9]= LATI[7];
//DisplayWord1[10]=LATI[8];
DisplayWord1[11]=' ';
DisplayWord1[12]='E';
DisplayWord1[13]=':';
//DisplayWord1[14]=LONGI[0];
//DisplayWord1[15]=LONGI[1];
//DisplayWord1[16]=LONGI[2];
//DisplayWord1[17]=LONGI[3];
//DisplayWord1[18]=LONGI[4];
//DisplayWord1[19]=LONGI[5];
//DisplayWord1[20]=LONGI[6];
//DisplayWord1[21]=LONGI[7];
//DisplayWord1[22]=LONGI[8];
//DisplayWord1[23]=LONGI[9];
                DelayMs(5);
         LCD_Write_String0(0,DisplayWord1);//显示第一行        longitude                  
}


void LATIFL(unsigned char LATICT)//LATICT: Latitude count
{
  unsigned char yt=0;
  rec=0;//必要的
   while(LATICT >yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
        //                 LATI[yt]=REV_DATA;
                 DisplayWord1[2+yt]=REV_DATA;//改在這裡
      rec=0;
          yt++;
          }
        }
}

void LONGIFL(unsigned char LONGICT)//LONGICT: Longitude count
{
  unsigned char yt=0;
  rec=0;//必要的
   while(LONGICT >yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
                //         LONGI[yt]=REV_DATA;
                 DisplayWord1[14+yt]=REV_DATA;//改在這裡
      rec=0;
          yt++;
          }
        }
}
您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

關閉

站長小叮嚀上一條 /1 下一條

禁閉室|手機版|連繫我們|痞酷網電子技術論壇

GMT+8, 2024-11-22 11:27 PM , Processed in 0.180529 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.