痞酷網_PIGOO

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

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

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

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

謝謝!
查看: 9293|回復: 32

求助; 讀取gps 信號 gprmc 內容可否放在中断服務程式內

  [複製鏈接]
發表於 2012-9-9 01:02:48 | 顯示全部樓層 |閱讀模式
本帖最後由 antlu 於 2012-9-9 11:14 AM 編輯

先進大大們:
  我的主程式
    while(1)
{
   Get_Gps();//讀取GPS信號

   cd_pr();//轉換成 四位顯示值
   Dis_tr();//轉換成 20排8BIT資料
    Display();//把它顯示出來
  }

卻產生一個大問題,讀取GPS資料大都漏掉,所以無法顯示出來,除非我使用

    while(1)
{
   while(Gok==0)
     {
       Get_GPS();
     }
   cd_pr();//轉換成 四位顯示值
   Dis_tr();//轉換成 20排8BIT資料
    Display();//把它顯示出來
  }
但是這樣卻發生嚴重的'閃動'現象 !!!


  

   我的 GPS 信號讀取副程式

unsigned char GPRMC_K(void)//比較 $GPRMC
{
unsigned char TT;//轉換用
          while(rec==0);
        if(rec==1)
              if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
                    rec=0;
                   else
                 return 0;
          while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'P')           
                        rec=0;   
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'R')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;         
                  else
                    return 0;                       
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'M')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;  
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'C')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;
          while(rec==0);     
        if(rec==1)     
          if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
                   rec=0;
                  else
                    return 0;

    CLCKFL(6);//取 時分秒

  TT=CLCK[0]*10+CLCK[1]+8;//中原標準時間
  if(TT>23)
     TT-=24;
         CLCK[0]=TT/10;
         CLCK[1]=TT%10;

  return 1;
  }

void Get_Gps(void)
{
if(rec==1)
  {
    rec=0;//清除授信旗標
    if(REV_DATA == '$')
     {
          Gok=GPRMC_K();//確認收到 "GPRMC," 字元
      }
    }
  }

請問這樣的GPS 讀取副程式,可以放在中断裡面嗎?
請問他總共會用掉多少時間?(BAUD RATE 4800)
還有其他解決的辦法嗎?

感謝!!
  
發表於 2012-9-9 09:04:08 | 顯示全部樓層
本帖最後由 ew75035 於 2012-9-9 09:36 AM 編輯

while迴圈的Gok我不知道是如何產生的 我猜是由Get_GPS所產生
當Gok等於0的時候表示讀取失敗 繼續執行Get_GPS來讀取資料
不過這個時候問題就來了 如果一直讀取失敗 那它就會一直在迴圈執行
而無法跳出迴圈 時間一久或許這就是造成閃動的原因

如果是這個問題造成的話 把 while 換成 if 試試
if (Gok == 0)
     Get_GPS();
另外 不知讀取的資料在處理的過程中 是否會被清除
會的話也要把下面的程式也放進來
發表於 2012-9-9 09:22:59 | 顯示全部樓層
不好意思 剛沒看仔細就回文了 沒注意到Get_GPS就在最底下

不知道你的GPS時鐘是一直抓信號來顯示 還是只抓來校時而已 其它的由程式來處理
如果是前者的話 那就要先處理為什麼會抓不到信號的問題了
 樓主| 發表於 2012-9-9 11:23:19 | 顯示全部樓層
ew75035 發表於 2012-9-9 09:22 AM static/image/common/back.gif
不好意思 剛沒看仔細就回文了 沒注意到Get_GPS就在最底下

不知道你的GPS時鐘是一直抓信號來顯示 還是只抓 ...

ew75035大;
  感謝回覆!!! 我目前就是抓 GPS的時間來顯示,先前使用 1602 或是使用 LATCH 七段顯示都沒發生問題,掃描式7段顯示也OK,但是這次踢到鐵板了,一旦用點陣掃描之後就經常發生讀不到 RS232的資料,我的Gok是讀取每秒一次的 $GPRMC 的資料 一旦讀不到就不行,所以每隔1~2分鐘才會成功讀取一次資料,..
發表於 2012-9-9 12:33:51 | 顯示全部樓層
阿乾大,您要配buffer出來。
因為您跑中斷時,會把它蓋掉,所以會丟包。
 樓主| 發表於 2012-9-9 13:50:25 | 顯示全部樓層
晴兒 發表於 2012-9-9 12:33 PM static/image/common/back.gif
阿乾大,您要配buffer出來。
因為您跑中斷時,會把它蓋掉,所以會丟包。

晴兒:
      這技巧我不太懂ㄟ!! 我把原程式 PO出來好了!! CLCK[7] 是 時 分 秒 的儲存區!! 這算是BUFFER ?


/* 20120731  變數名稱 dc 不可以,會亂跑,原因不明 改成 dca dcb 就可以11  0801 改成顯示 23時 59分 調整計時  20120816開始改寫給gps使用 要增加GPS 讀取部分+GPS port  平常顯示 "TIME  by GPS  之後顯示*/
/* 20120731  變數名稱 dc 不可以,會亂跑,原因不明 改成 dca dcb 就可以11  0801 改成顯示 23時 59分 調整計時 */
/* 20120824  一直搞不出來 先放一邊 最大問題 LED 無法從第一排顯示出來
20120906 scan ok 原因是595 scan 先前抄人家的不完全了解問題,本來是共陽極現在 5*8是共陰極所以輸出相反 於是用 j=0 把第一個值為零 送出給ser_b 之後j=1~23 都不是0 所以 ser都會是1 這樣就不會有問題了 */
#include<reg52.h>   
#include <intrins.h> //use nop  
//#include <delay.h>

sbit LATCH = P2^4; //byte 1 green Byte 2 RED
sbit SRCLK= P2^5;
sbit SER  = P2^3;// Lo active pull down LED cathode to ground  


sbit LATCH_B = P2^1;//P2^1;LED commond Lo active
sbit SRCLK_B= P2^2;//P2^2;
sbit SER_B= P2^0;// P2^0; LED commond Lo active to supply 5V to LED
sbit Gok_LED = P1^0;
//sbit ch_color=P1^2;
unsigned char cd,color,ms2,ms3;
unsigned char dca,dcb,dcc;
unsigned int ms4;
unsigned char disp[24];
unsigned char dispbf[4];
bit ch_flag;//need flash count display

void DelayMs(unsigned char t);
void DelayUs2x(unsigned char t);
//-------GPS相關資料區---------
unsigned char REV_DATA,Gok,GPS_ST;//GPS_ST 存放 a v 狀態
bit rec;
unsigned char CLCK[7];//GPS 時1,2 分3,4 秒5,6  & A V 值7
unsigned char YMD[6];//年月日存放


//-------GPS相關資料區---------

/*  使用相對的位置來顯示出相對的自來 14:00
需要 相對的顯示如 WD[1] WD[2] WD[3] WD[4] 6*8
DISWD(x,y) x:位置 y:內容*/
// unsigned char DISPWD[4,6]//四個字每個字6BYTE
unsigned char code DP[10][5]={
{0x7e,0x81,0x81,0x81,0x7e},//0
{0x80,0x82,0xff,0x80,0x80},//1
{0xc2,0xa1,0x91,0x89,0x86},//2
{0x62,0x81,0x89,0x89,0x76},//3
{0x38,0x24,0x22,0xff,0x20},//4
{0x86,0x89,0x89,0x89,0x71},//5
{0x7e,0x89,0x89,0x89,0x70},//6
{0x01,0xf1,0x09,0x05,0x03},//7
{0x76,0x89,0x89,0x89,0x76},//8
{0x0e,0x91,0x91,0x91,0x7e}};//9


unsigned char code font6x11[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, //SP
0x00, 0x00, 0x00, 0x00, 0x00, //SP
0x00,0x1c,0x22,0x41,0x49,0x79,0x00,//G
0x00,0x7f,0x11,0x11,0x11,0x0e,0x00,//P
0x00,0x26,0x49,0X49,0x49,0x4a,0x30,//S
0x00, 0x00, //SP
0x00,0x1c,0x22,0x41,0x41,0x22,0x00,//C
0x7f,0x40,0x40,0x40,0x40,0x00,//L
0x00,0x3e,0x41,0x41,0x41,0x3e,//O
0x00,0x1c,0x22,0x41,0x41,0x22,0x00,//C
0x7f,0x08,0x14,0x22,0x41,0x00,//K
0x00, 0x00, //SP
0x00,0x1c,0x22,0x41,0x49,0x79,0x00,//G
0x00,0x7f,0x11,0x11,0x11,0x0e,0x00,//P
0x00,0x26,0x49,0X49,0x49,0x4a,0x30,//S
0x00, 0x00, //SP




                                                  };

void Display (void);
void Get_Gps(void);
/*------------------------------------------------
                    timer initial
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01;          //mode 1,16bit timer                     

EA=1;            //interrupt enable
ET0=1;           //et0
TR0=1;           //tr0
}
/*------------------------------------------------
                 service sub
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-4010)/256;                  //reset 4ms
TL0=(65536-4010)%256;
ms2++;// 2ms setflag
ms4++;
// Display();
   if(ms2>7)//2*74*5=1000ms
    {
     ms2=0;
     ms3++;
         if(ch_flag==1)
   Display();

         }
     if(ms3>44)
     {
      ms3=0;
          dca++;//dc=1sec count
     }
         if(dca>59)//內部自己計數 時 分秒
         {
      dcb++;
          dca=0;
         }
/*
  if(dcb>59)
     {
      dcb=0;
      dcc++;
     }
     if(dcc>23)
     {
      dcc=0;
     }
         */
   }




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

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

*/
void SendByte(unsigned char dat,bit direction)
{   
  unsigned char i,temp;
   if(direction==0)
     temp=0x80;//要比較第7bit
   else
     temp=0x01;//要比較第0bit
   for(i=0;i<8;i++)
        {
         SRCLK=0;
         SER=dat&temp;//不是0就是1
         if(direction==0)
         dat<<=1;
         else
             dat>>=1;
         SRCLK=1;
         }
}



void Out595(void)
{
        LATCH=0;
        _nop_();
        LATCH=1;
}



void cd_pr (void)
{
dispbf[0]=CLCK[2];//dcb/10;//10 min
dispbf[1]=CLCK[3];//dcb%10;//1 min
dispbf[2]=CLCK[4];//dca/10;//10 sec
dispbf[3]=CLCK[5];//1 sec
}

void Dis_tr(void)
//程式 把資料送到 DISPWD[4,5]裡面資料顯示出來
{
unsigned char dp,d6p;
for(dp=0;dp<4;dp++)
  {
    for(d6p=0;d6p<5;d6p++)
       {
              disp[d6p+dp*5]=DP[dispbf[dp]][d6p];// DP內部放著0~9的字库 對應1~4位數的dp,以及每一位數的5個byte的點陣 DP[dispbf[dp],d6p];
       }
   }
}



void Display (void)
{
  unsigned char l,j;
// for(l=0;l<25;l++)//顯示5次
  {
   for(j=0;j<24;j++) //  字型會反轉 (正 24>>0)   
      {      
           SRCLK_B=0;//----- sendseg start
           SER_B=j;
                        SRCLK_B=1;
            LATCH_B=0;    //
             _nop_();
             LATCH_B=1;                     
             SendByte(disp[j],0);//"~" 明暗反轉 紅色         
             Out595();
             DelayUs2x(150);
                         SendByte(0x00,0);// 0 字正 1 字顛倒
             Out595();
        }
      }//for l  
   }


void normal_disp(void)
{
  unsigned char i,l;
  unsigned int k;

for(k=0;k<65;k++) //流動方向 由左到右 88>>0
    {                  
     for(l=0;l<5;l++)
      {   
       for(i=0;i<24;i++) //  字型會反轉 (正 24>>0)      
         {
           SRCLK_B=0;//----- sendseg start
           SER_B=i;
                SRCLK_B=1;
            LATCH_B=0;    //
            _nop_();
            LATCH_B=1;           
              SendByte(font6x11[i+k+8],0);//"~" 明暗反轉紅色   
         
             Out595();
             DelayUs2x(250);
                         SendByte(0x00,0);// 0 字正 1 字顛倒
             Out595();
          }//for i
         }//for l              
         }//for k       
}




/*------------------------------------------------
              串口通讯初始化
------------------------------------------------*/

void UART_Init(void)
{
    SCON  = 0x50;                        // SCON: 模式 1, 8-bit UART, 使能接收  
//    TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
//    TH1   = 0xfa;               // TH1:  重装值 GPS 4800 波特率 晶振 11.0592MHz  
    T2CON = 0x34;  // timer2 parameter set
    RCAP2H = 0xff; //set uart baud rate 38400
        RCAP2L = 0xf7;
    ET2 = 1;// enable timer2 overflow flag
        TR2 = 1;// timer2 enable
//   TR1   = 1;                  // TR1:  timer 1 打开                        
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
}





void UART_SER (void) interrupt 4 //來自GPS 程式
{
     if(RI)                        //判断是接收中断产生
     {
          RI=0;                      //标志位清零
          REV_DATA =SBUF;                 //读入缓冲区的值
      rec=1;
         }
   if(TI)  //如果是发送标志位,清零
     TI=0;
}

void CLCKFL(unsigned char CLCKCT)//存入時 分 秒
{
  unsigned char ct=0;
  rec=0;//必要的
   while(CLCKCT>ct)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
          CLCK[ct]=REV_DATA-0x30;
      rec=0;
          ct++;
          }
        }
}




//0819 填入6個年月日資料
void YMDFL(unsigned char YMDCT)
{
  unsigned char yt=0;
  rec=0;//必要的
   while(YMDCT>yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
          YMD[yt]=REV_DATA-0x30;
      rec=0;
          yt++;
          }
        }
}


//0819 跳過幾個逗號

void JPDM(unsigned char DM)
{
// unsigned char dmt=0;
  rec=0;
  while(DM)//>dmt
   {
    while(rec==0);
        if (rec==1)
         {
     if(REV_DATA == ',')
         {
         rec=0;
         DM--;//dmt++
         }
         }
   }
}





unsigned char GPRMC_K(void)//比較 $GPRMC
{
unsigned char TT;//轉換用
          while(rec==0);
        if(rec==1)
              if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
                    rec=0;
                   else
                 return 0;
          while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'P')           
                        rec=0;   
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'R')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;         
                  else
                    return 0;                       
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'M')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;  
                     while(rec==0);        
        if(rec==1)             
          if(REV_DATA == 'C')//一路比較下去全部要相同 "GPRMC,"           
                        rec=0;
          while(rec==0);     
        if(rec==1)     
          if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
                   rec=0;
                  else
                    return 0;

    CLCKFL(6);//取 時分秒
/*    JPDM(1);
        while(rec==0);
        if(rec==1)
        {
    CLCK[6]=REV_DATA;//取A(正常)或是 V(搜尋中)
        }
   
    JPDM(7);//跳過8個逗號
        YMDFL(6);//取 年月日
*/
  TT=CLCK[0]*10+CLCK[1]+8;//中原標準時間
  if(TT>23)
     TT-=24;
         CLCK[0]=TT/10;
         CLCK[1]=TT%10;

  return 1;
  }

void Get_Gps(void)
{
if(rec==1)
  {
    rec=0;//清除授信旗標
    if(REV_DATA == '$')
     {
          Gok=GPRMC_K();//確認收到 "GPRMC," 字元
      }
    }
  }


main()
{
Init_Timer0();
UART_Init();
    cd_pr();
   Dis_tr();

while(1)
{

    while(Gok==0)
    {
    Get_Gps();//取GPS信號
        }       
   cd_pr();
   Dis_tr();
     Gok=0;
  
  


if(dca>30)
  {
    ch_flag=0;
   normal_disp();
  }
  ch_flag=1;
  }
}//main



發表於 2012-9-9 15:30:16 | 顯示全部樓層
你的副程式GPRMC_K(void)有一些Bugs, 例如

unsigned char TT;//轉換用
          while(rec==0);
        if(rec==1)
              if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
                    rec=0;
                   else
                 return 0;
          while(rec==0);


以上的 "else return 0" 是屬於 "if(rec==1)" 所使用的, 因此
當REV_DATA=='G'時,會跑 (1)rec=0  (2)while(rec==0);
當REV_DATA不=='G'時,會跑 (1)while(rec==0);

因此可知當資料接收錯誤時反而繼續向下執行,你可以加括號 如下

unsigned char TT;//轉換用
          while(rec==0);
        if(rec==1)
           {
              if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
                    rec=0;
                   else
                 return 0;
           }
          while(rec==0);        


你必須一一修正此副程式這些的BUGs
 樓主| 發表於 2012-9-9 17:32:52 | 顯示全部樓層
yesjarmail 發表於 2012-9-9 03:30 PM static/image/common/back.gif
你的副程式GPRMC_K(void)有一些Bugs, 例如

unsigned char TT;//轉換用

yesjarmail 大:
   感謝提醒!! 我已經改了,還是有問題!! 繼續努力中!!
   
發表於 2012-9-9 18:32:20 | 顯示全部樓層
antlu 發表於 2012-9-9 01:50 PM static/image/common/back.gif
晴兒:
      這技巧我不太懂ㄟ!! 我把原程式 PO出來好了!! CLCK[7] 是 時 分 秒 的儲存區!! 這算是BUFFER ...

阿乾大,換小妹我看得頭昏眼花了。呵!
不是的,小妹我的意思是,您從232收GPS字串進來,是需要配置一小段buffer來存。小妹我看到的,您好像是只有配一個char來放,怕很容易在您判斷是在跑的時候,會被232中斷重新賦值而蓋掉。
看您的程式碼,小妹我有想到一個地方,改了之後不知道有沒有用。
就是232中斷內的 rec=1,rec好像只是用來判斷232有沒有收到?然後再比對GPRMC_K(void)這個副程式內,有些可以稍微修剪一下。

  1. unsigned char GPRMC_K(void)//比較 $GPRMC
  2. {
  3.    unsigned char TT;//轉換用
  4.    while(rec==0);
  5.    if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
  6.    {
  7.        rec=0;
  8.    }
  9.    else
  10.    {
  11.       return 0;
  12.    }
  13.    while(rec==0);                  
  14.    if(REV_DATA == 'P')
  15.    {
  16.        rec=0;
  17.    }
  18.    else
  19.    {
  20.        return 0;
  21.    }           
  22.    while(rec==0);        
  23.    if(REV_DATA == 'R')//一路比較下去全部要相同 "GPRMC,"  
  24.    {         
  25.        rec=0;         
  26.    }
  27.                                           
  28.    while(rec==0);
  29.    if(REV_DATA == 'M')//一路比較下去全部要相同 "GPRMC,"           
  30.    {
  31.        rec=0;
  32.    }
  33.                         
  34.    while(rec==0);        
  35.    if(REV_DATA == 'C')//一路比較下去全部要相同 "GPRMC,"
  36.    {           
  37.        rec=0;
  38.    }
  39.    else
  40.    {
  41.        return 0;
  42.    }  
  43.    while(rec==0);
  44.    if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
  45.    {
  46.        rec=0;
  47.    }
  48.    else
  49.    {
  50.        return 0;
  51.    }
  52.     CLCKFL(6);//取 時分秒
  53. /*    JPDM(1);
  54.         while(rec==0);
  55.         if(rec==1)
  56.         {
  57.     CLCK[6]=REV_DATA;//取A(正常)或是 V(搜尋中)
  58.         }
  59.    
  60.     JPDM(7);//跳過8個逗號
  61.         YMDFL(6);//取 年月日
  62. */
  63.   TT=CLCK[0]*10+CLCK[1]+8;//中原標準時間
  64.   if(TT>23)
  65.      TT-=24;
  66.          CLCK[0]=TT/10;
  67.          CLCK[1]=TT%10;

  68.   return 1;
  69.   }
複製代碼
發表於 2012-9-9 20:09:15 | 顯示全部樓層
本帖最後由 胸脯啞謎 於 2012-9-9 08:14 PM 編輯

   while(1)
{
   Get_Gps();//讀取GPS信號

   cd_pr();//轉換成 四位顯示值
   Dis_tr();//轉換成 20排8BIT資料
    Display();//把它顯示出來
  }

卻產生一個大問題,讀取GPS資料大都漏掉,所以無法顯示出來,除非我使用

這裡會漏接是正常的,程式檢查不到'$',便往下執行其他,只有從新回到 Get_Gps(); ,才又再一次檢查'$',若你的其他程式執行太久,那就可能rs232收到'$',程式還在執行其他項,沒執行Get_Gps();,也就沒檢查'$',這時rs232可能又收到'G',這時才又回到Get_Gps();,但已經沒了'$','G'來了也沒用,只好放棄,這次應該收到的值,就漏接了。還有,中斷沒設優先權,也會造成要接收,但time0先中斷,串口中斷就無法執行了

    while(1)
{
   while(Gok==0)
     {
       Get_GPS();
     }
   cd_pr();//轉換成 四位顯示值
   Dis_tr();//轉換成 20排8BIT資料
    Display();//把它顯示出來
  }
但是這樣卻發生嚴重的'閃動'現象 !!!

改成這樣,變成程式一直再檢查收到的值,只有全都收到(收到$GPRMC,跟時間值),才會跳出迴圈,執行下面的程式,所以不會漏接,但mcu幾乎都在等待接收,沒去處理顯示,所以會閃動。

所以晴兒大的意思是,接收時,先收到buffer裡,收齊了,再去判斷,這樣就不會浪費mcu的時間
 樓主| 發表於 2012-9-9 23:38:58 | 顯示全部樓層
本帖最後由 antlu 於 2012-9-9 11:50 PM 編輯
胸脯啞謎 發表於 2012-9-9 08:09 PM static/image/common/back.gif
while(1)
{
   Get_Gps();//讀取GPS信號


胸脯啞謎大:
      中断優先順序!! 還沒學到!! 我把 YESJAMAIL大 和 晴兒大 的建議都改了,但是還是沒辦法完全抓到問題,後來我把顯示掃描縮短之後, RS232的擷取率提高了,

void Display (void)
{
  unsigned char j;
// for(l=0;l<5;l++)//取消使得 rs232讀取成功率提高
  {
   for(j=0;j<24;j++) //  字型會反轉 (正 24>>0)   
      {      
           SRCLK_B=0;//----- sendseg start
           SER_B=j;//這最重要因為共陰極只有一列要低電位,所以把第一次設為零 0~23 只有除0以外其他都"非0"
                        SRCLK_B=1;
            LATCH_B=0;    //
             _nop_();
             LATCH_B=1;                     
             SendByte(disp[j],0);//"~" 明暗反轉 紅色         
             Out595();
             DelayUs2x(150);
                         SendByte(0x00,0);// 0 字正 1 字顛倒
             Out595();
        }
      }//for l  
   }

加上一個偷吃步 就是我只顯示 時 & 分 並且不是每秒鐘都更新資料 所以幾乎就沒有閃爍!!

main()
{
Init_Timer0();
UART_Init();
    cd_pr();
    Dis_tr();
while(1)
{
    Display();   
    Get_Gps();//取GPS信號       
        if(ms3==0)//約每秒更新一次時間減少閃動
        {
     cd_pr();
     Dis_tr();
      Gok=0;//???
    }
if(dca>55)//第55秒
    {
      normal_disp();//顯示 gps clock
     }
       
  }
}//main

這次的經驗 我發現 對於外界發送過來的資料 要不漏掉, "時間掌握"非常重要!! 我的顯示掃描把外部送來的訊息檔掉,而機會稍縱即逝 (向全天下的程式師致敬!!! Orz.....) 後續還要做的事情 學習"緩衝區的技巧" "中断優先順序使用技巧"

全部程式如下,請不吝指教!!  
DOTGPS06.JPG

DOTGPS02.JPG

DOTGPS01.JPG

DOTGPS07.JPG


/* 20120731  變數名稱 dc 不可以,會亂跑,原因不明 改成 dca dcb 就可以 20120816開始改寫給gps使用 顯示 "GPS CLOCK GPS  */
/* 20120824  一直搞不出來 無法從第一排顯示出來 直到20120906 scan ok 原因是595 scan 先前抄人家的不完全了解問題,本來是共陽極現在 5*8是共陰極所以輸出相反 於是用 j=0 把第一個值為零 送出給ser_b 之後j=1~23 都不是0 所以 ser都會是1 這樣就不會有問題了,
引進gps程式之後,發生 $GPRMC 讀取的成功率一值很低,最後發現點陣掃描的動作打斷了 RS232的讀取動作,使用 while(Gok) 卻會導致系統停留阻擋掃描而'閃動',嚐試著中断程式中作顯示掃描但是閃爍嚴重
最後把 掃描 // for(l=0;l<5;l++)//顯示5次 取消 程式上面就會比較順利的讀取 rs232信號 成功率 10次有7次成功 不需要while(Gok) */
#include<reg52.h>   
#include <intrins.h> //use nop  
sbit LATCH = P2^4; //8點1列提供hi輸出給共陰led
sbit SRCLK= P2^5;
sbit SER  = P2^3;//  


sbit LATCH_B = P2^1;//20|給共陰極led 拉下接地動作,不能接uln2003
sbit SRCLK_B= P2^2;//
sbit SER_B= P2^0;//
//sbit Gok_LED = P1^0;

unsigned char ms2,ms3,ms4;//中断計時
unsigned char dca,dcb;//計秒,計分,計時

unsigned char disp[24];//顯示 點陣位置
unsigned char dispbf[4];//時間轉換放置
bit ch_flag;//變化顯示用

void DelayMs(unsigned char t);
void DelayUs2x(unsigned char t);

unsigned char REV_DATA,Gok;//rs232讀入緩衝,$GPRMC 讀取的成功記號.
bit rec;//rs232讀入中緞旗標
unsigned char CLCK[7];//GPS 時1,2 分3,4 秒5,6  & A V 值7
unsigned char YMD[6];//年月日存放

/*  使用相對的位置來顯示出相對的自來 14:00
需要 相對的顯示如 WD[1] WD[2] WD[3] WD[4] 6*8
DISWD(x,y) x:位置 y:內容*/
// unsigned char DISPWD[4,6]//四個字每個字6BYTE
unsigned char code DP[10][5]={
{0x7e,0x81,0x81,0x81,0x7e},//0
{0x80,0x82,0xff,0x80,0x80},//1
{0xc2,0xa1,0x91,0x89,0x86},//2
{0x62,0x81,0x89,0x89,0x76},//3
{0x38,0x24,0x22,0xff,0x20},//4
{0x86,0x89,0x89,0x89,0x71},//5
{0x7e,0x89,0x89,0x89,0x70},//6
{0x01,0xf1,0x09,0x05,0x03},//7
{0x76,0x89,0x89,0x89,0x76},//8
{0x0e,0x91,0x91,0x91,0x7e}};//9


unsigned char code font6x11[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, //SP
0x00, 0x00, 0x00, 0x00, 0x00, //SP
0x00,0x1c,0x22,0x41,0x49,0x79,0x00,//G
0x00,0x7f,0x11,0x11,0x11,0x0e,0x00,//P
0x00,0x26,0x49,0X49,0x49,0x4a,0x30,//S
0x00, 0x00, //SP
0x00,0x1c,0x22,0x41,0x41,0x22,0x00,//C
0x7f,0x40,0x40,0x40,0x40,0x00,//L
0x00,0x3e,0x41,0x41,0x41,0x3e,//O
0x00,0x1c,0x22,0x41,0x41,0x22,0x00,//C
0x7f,0x08,0x14,0x22,0x41,0x00,//K
0x00, 0x00, //SP
                                                  };

void Display (void);
void Get_Gps(void);
/*------------------------------------------------
                    timer initial 一般計時
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01;          //mode 1,16bit timer                     

EA=1;            //interrupt enable
ET0=1;           //et0
TR0=1;           //tr0
}
/*------------------------------------------------
                 service sub
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-2010)/256;                  //reset 2ms
TL0=(65536-2010)%256;
ms2++;
ms4++;

   if(ms2>75)//2*74~~150ms
    {
     ms2=0;
     ms3++;
         }
     if(ms3>5)
     {
      ms3=0;
          dca++;//dc=1sec count
     }
         if(dca>59)//內部自己計數 時 分秒
         {
      dcb++;
          dca=0;
         }
   }




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

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

*/
void SendByte(unsigned char dat,bit direction)
{    //送出1列的程式 來自對岸的程式
  unsigned char i,temp;
   if(direction==0)
     temp=0x80;//要比較第7bit
   else
     temp=0x01;//要比較第0bit
   for(i=0;i<8;i++)
        {
         SRCLK=0;
         SER=dat&temp;//不是0就是1
         if(direction==0)
         dat<<=1;
         else
             dat>>=1;
         SRCLK=1;
         }
}



void Out595(void)
{//鎖定輸出
        LATCH=0;
        _nop_();
        LATCH=1;
}



void cd_pr (void)
{//把 GPS讀到的時 分 數值放到緩衝區待轉換
dispbf[0]=CLCK[0];//10 Hr
dispbf[1]=CLCK[1];//1 Hr
dispbf[2]=CLCK[2];//10 min
dispbf[3]=CLCK[3];//1 min
}

void Dis_tr(void)
//程式 把資料送到 DISPWD[4,5]裡面資料顯示出來
{
unsigned char dp,d6p;
for(dp=0;dp<4;dp++)
  {
    for(d6p=0;d6p<5;d6p++)
       {
              disp[d6p+dp*5]=DP[dispbf[dp]][d6p];// DP內部放著0~9的字库 對應1~4位數的dp,以及每一位數的5個byte的點陣 DP[dispbf[dp],d6p];
       }
   }
}



void Display (void)
{
  unsigned char j;
// for(l=0;l<5;l++)//取消使得 rs232讀取成功率提高
  {
   for(j=0;j<24;j++) //  字型會反轉 (正 24>>0)   
      {      
           SRCLK_B=0;//----- sendseg start
           SER_B=j;//這最重要因為共陰極只有一列要低電位,所以把第一次設為零 0~23 只有除0以外其他都"非0"
                        SRCLK_B=1;
            LATCH_B=0;    //
             _nop_();
             LATCH_B=1;                     
             SendByte(disp[j],0);//"~" 明暗反轉 紅色         
             Out595();
             DelayUs2x(150);
                         SendByte(0x00,0);// 0 字正 1 字顛倒
             Out595();
        }
      }//for l  
   }


void normal_disp(void)
{
  unsigned char i,l;
  unsigned int k;

for(k=0;k<40;k++) //流動方向 由左到右 88>>0
    {                  
     for(l=0;l<5;l++)
      {   
       for(i=0;i<24;i++) //  字型會反轉 (正 24>>0)      
         {
           SRCLK_B=0;//----- sendseg start
           SER_B=i;//這最重要因為共陰極只有一列要低電位,所以把第一次設為零 0~23 只有除0以外其他都"非0"
                SRCLK_B=1;
            LATCH_B=0;
            _nop_();
            LATCH_B=1;           
              SendByte(font6x11[i+k+8],0);//"~" 明暗反轉紅色   
         
             Out595();
             DelayUs2x(250);
                         SendByte(0x00,0);// 0 字正 1 字顛倒
             Out595();
          }//for i
         }//for l              
           }//for k       
}




/*------------------------------------------------
              串口通讯初始化
------------------------------------------------*/
void UART_Init(void)
{
    SCON  = 0x50;                        // SCON: 模式 1, 8-bit UART, 使能接收  
    TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
    TH1   = 0xfa;               // TH1:  重装值 GPS 4800 波特率 晶振 11.0592MHz   
    TR1   = 1;                  // TR1:  timer 1 打开                        
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
}
/*
void UART_Init(void)
{
    SCON  = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收  
    T2CON = 0x34; // timer2 parameter set
    RCAP2H = 0xff;//set uart baud rate 38400
        RCAP2L = 0xf7;
    ET2 = 1;// enable timer2 overflow flag
        TR2 = 1;// timer2 enable
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
}

*/



void UART_SER (void) interrupt 4 //來自GPS 程式
{
     if(RI)                        //判断是接收中断产生
     {
          RI=0;                      //标志位清零
          REV_DATA =SBUF;                 //读入缓冲区的值
      rec=1;
         }
   if(TI)  //如果是发送标志位,清零
     TI=0;
}

void CLCKFL(unsigned char CLCKCT)//存入時 分 秒
{
  unsigned char ct=0;
  rec=0;//必要的
   while(CLCKCT>ct)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
          CLCK[ct]=REV_DATA-0x30;
      rec=0;
          ct++;
          }
        }
}




//0819 填入6個年月日資料
/*
void YMDFL(unsigned char YMDCT)
{
  unsigned char yt=0;
  rec=0;//必要的
   while(YMDCT>yt)//儲存數量
   {
    while(rec==0);
        if(rec==1)
         {
          YMD[yt]=REV_DATA-0x30;
      rec=0;
          yt++;
          }
        }
}
*/

//0819 跳過幾個逗號
/*
void JPDM(unsigned char DM)
{
// unsigned char dmt=0;
  rec=0;
  while(DM)//>dmt
   {
    while(rec==0);
        if (rec==1)
         {
     if(REV_DATA == ',')
         {
         rec=0;
         DM--;//dmt++
         }
         }
   }
}

*/



unsigned char GPRMC_K(void)//比較 $GPRMC
{
unsigned char TT;//轉換用
          while(rec==0);
              if(REV_DATA == 'G')//一路比較下去全部要相同 "GPRMC,"
                  {
              rec=0;
                  }
                   else
                   {
                 return 0;
                        }
          while(rec==0);        
          if(REV_DATA == 'P')      
               {
                        rec=0;   
                     }
           while(rec==0);
          if(REV_DATA == 'R')//一路比較下去全部要相同 "GPRMC,"           
                        {
                        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;
                        }
                        else
                        {
                        return 0;
                        }
          while(rec==0);     
          if(REV_DATA == ',')//一路比較下去全部要相同 "GPRMC,"
           {
                           rec=0;
                  }
                  else
                   {  
                   return 0;
                   }

    CLCKFL(6);//取 時分秒
/*    JPDM(1);
        while(rec==0);
        if(rec==1)
        {
    CLCK[6]=REV_DATA;//取A(正常)或是 V(搜尋中)
        }
   
    JPDM(7);//跳過8個逗號
        YMDFL(6);//取 年月日
*/
  TT=CLCK[0]*10+CLCK[1]+8;//中原標準時間
  if(TT>23)
     TT-=24;
         CLCK[0]=TT/10;
         CLCK[1]=TT%10;
  return 1;
  }

void Get_Gps(void)
{
if(rec==1)
  {
    rec=0;//清除授信旗標
    if(REV_DATA == '$')
     {
          Gok=GPRMC_K();//確認收到 "GPRMC," 字元
      }
    }
  }


main()
{
Init_Timer0();
UART_Init();
    cd_pr();
    Dis_tr();
while(1)
{
    Display();   
    Get_Gps();//取GPS信號       
        if(ms3==0)//約每秒更新一次時間減少閃動
        {
     cd_pr();
     Dis_tr();
      Gok=0;//???
    }
  


if(dca>55)//第55秒
    {
      normal_disp();//顯示 gps clock
     }
       
  }
}//main




發表於 2012-9-10 00:51:36 | 顯示全部樓層
antlu大
其實整個程式的問題單純只是mcu在顯示+收碼上"跑不動"而己
顧了顯示要順就顧不上GPS收碼,順了GPS就卡了顯示
加上c本身的編譯讓整個程式碼變的更大而己,效能較差當然跑不動
至於怎麼解決,方法也有很多種
如果你用的是12T的mcu那麼就換成1T的,而最耗效能的就會被拖在GPS接收端
如果用1T的MCU了還跑不動,那麼就把XTAL由11.0592換成22.1184MHZ
除了GPS會拖效能外,全部含顯示部份速度就拉上快1倍
其實看了半天還是出在GPS接收端的問題
如果可以就算看看,正常跑完一次GPS收碼花了多久時間,顯示一次花多久
UART和TIME的中斷各花多久,結果都是卡在動作時間的問題上
十次成功7次那還是不對的,因為RS232端的這種情形是算不正常的
至於BUFFER的模式可能換成用兩棵MCU作同步動作還來的順一點
一棵作接收GPS信號還作運算,另一棵就忙著顯示部份和第一棵作資料交換
如此一來陣列作的多大也沒太大問題的,
只能說一個問題有很多方法解決,就看怎麼去運用了
這星期要交一台機器,這兩天還在忙噴漆,也是在作一台時鐘定時,
不過在定時的一些條件上就比較複雜多了,也是用GPS作校時,
所以同是一個東西就看怎麼去運用而己
發表於 2012-9-10 01:20:30 | 顯示全部樓層
你想通了一些,但還是沒完全想通。外來的信號,是要完全一字不漏的接收,不是碰運氣的,所以才要使用buffer,將收到的信號,通通放進去,這樣就不會lose。你用的是點陣led顯示,掃瞄模式,使用74595串列轉並列驅動,這會花費mcu很多的時間,而mcu又要計數自己的時間,這麼多的時間花費,你卻只使用順序方式,所以才有上述問題。要解決這些問題,多想想如何利用時間中斷、串列中斷,中斷優先權設定是一定要的,等你想通了,你玩單晶片的功力也大增了
發表於 2012-9-10 12:32:51 | 顯示全部樓層
但是又會有一個問題,要配buffer,前提下,MCU的ram要夠用(這樣的前提下,還可以偷懶些,用一些比較笨的方法來做)。不然只能夠像胸脯啞謎大和legion大說的,需要蠻多特殊技巧來處理這些問題。
發表於 2012-9-10 16:06:57 | 顯示全部樓層
本帖最後由 ysc 於 2012-9-10 04:51 PM 編輯
antlu 發表於 2012-9-9 05:32 PM static/image/common/back.gif
yesjarmail 大:
   感謝提醒!! 我已經改了,還是有問題!! 繼續努力中!!


問題的根源在於Delay Loop.......記得以前跟您說過儘量不要用這種「殺CPU時間」方式來計時:
-------------------------------------------------------------------------------------------------------------------
void DelayUs2x(unsigned char t)
{   
while(--t);
}

/*
void DelayMs(unsigned char t)
{   
while(t--)
{     
     DelayUs2x(245);
         DelayUs2x(245);
-----------------------------------------------------------------------------------------------------------
當程式在「殺CPU時間」(延時)時甚麼事也不能做,若延時超過串列介面傳送1 BYTE時間,在接收暫存器裡的字元會來不及收取,當然會遭下一個字元覆蓋掉,如此一來接收的字串不完整當然會有問題。

若是一直顧著接收字元,則會忽略掉顯示器掃描,因此而產生顯示閃動.......

解決的方法其實很簡單,原則就是不要「殺CPU時間」,也就是不要讓程式在迴圈裡空等待,說起來是很簡單,實際上必須改變程式結構,掃描顯示器用計時中斷,接收也要用中斷+RAM BUFFER,也就是採用多工式程式結構,這樣程式效率才會高,以51系列來說即使以C語言編寫,要實現這樣的功能並不困難。

GPS時鐘最好也內建RTC,顯示以RTC時間為主,GPS只用來校正時間,可以設定為若干小時或若干分鐘校時一次,這樣在接收不到GPS訊號時也能正常顯示時間。

看阿乾大非科班出身,短時間內可以練到這等功力深感敬佩,若能再突破「殺CPU時間」障礙,那功力必定又上層樓........
發表於 2012-9-10 16:15:43 | 顯示全部樓層
本帖最後由 ysc 於 2012-9-10 04:21 PM 編輯
晴兒 發表於 2012-9-10 12:32 PM static/image/common/back.gif
但是又會有一個問題,要配buffer,前提下,MCU的ram要夠用(這樣的前提下,還可以偷懶些,用一些比較笨的方 ...


用中斷方式來接收串列字元也不一定要將每個字元存起來(尤其在51系列RAM有限之下),可以在接收中斷程式裡判斷是否接收到字串起頭識別字元,找到起頭字元然後計算接下來第幾個字開始才是需要的資料欄位,從需要的資料欄位才開始放到BUFFER裡,不是需要的字元一律丟棄,這樣就不會用到很多RAM當BUFFER,不過接收中斷程式的寫法就需要有點技巧,但並不會很困難......

不管如何......串列接收必須做到1個字元也不能掉,這樣程式跑起來才可靠,
發表於 2012-9-10 16:19:06 | 顯示全部樓層
本帖最後由 fatzeros 於 2012-9-10 04:22 PM 編輯

雖然有點事後諸葛,
但是一直以來,看程設的書上,
一直都是要大家不要使用cpu計算的延時作法,
而是要使用中斷和優先次序的作法來編寫,
才能得到高效率的執行。

我也覺得,在8051應用上,gps應該只能校時,而無法作成RTC(實時時鐘)啦!

阿乾兄,去數碼之家的這一篇:通俗话教你单片机看看中斷的教程好了!
雖然我也是看得模模糊糊的。

如果想要1T的MCU,我這裡有STC 15F204EA可以用喔!雖然只有28腳!
發表於 2012-9-10 16:25:56 | 顯示全部樓層
fatzeros 發表於 2012-9-10 04:19 PM static/image/common/back.gif
雖然有點事後諸葛,
但是一直以來,看程設的書上,
一直都是要大家不要使用cpu計算的延時作法,


用軟體程式延時方法也不是不能用,做實驗時就是個方便的好方法,
但整合成一個系統......CPU時間不夠用的問題就浮現了,更冤枉的是並不是CPU指令執行來不及,
而是大部分時間CPU忙於「空繞圈子」,無暇兼顧更重要的事件..............
發表於 2012-9-10 18:01:16 | 顯示全部樓層
晴兒 發表於 2012-9-10 12:32 PM static/image/common/back.gif
但是又會有一個問題,要配buffer,前提下,MCU的ram要夠用(這樣的前提下,還可以偷懶些,用一些比較笨的方 ...

在這個例子,buffer需要並不多,約"$GPRMC,"再加上時分秒,約12bytes算13bytes,再乘2,也才26bytes,只多花RAM26bytes,卻能讓mcu不再將時間都花在檢查"$GPRMC,"上,划算啊
 樓主| 發表於 2012-9-10 19:27:47 | 顯示全部樓層
胸脯啞謎 發表於 2012-9-10 06:01 PM static/image/common/back.gif
在這個例子,buffer需要並不多,約"$GPRMC,"再加上時分秒,約12bytes算13bytes,再乘2,也才26bytes,只 ...

胸脯啞謎大:
      我的程式小,不會在乎 RAM 啦!! 只是 這些技巧都沒用過!! 感覺上就是把資料先讀進來(再說!!) 然後用空檔進行判斷!! 如果不對就丟棄!! 這樣就不需要while ...   慢慢琢磨,再來改程式!!  感謝!!
 樓主| 發表於 2012-9-10 19:34:21 | 顯示全部樓層
fatzeros 發表於 2012-9-10 04:19 PM static/image/common/back.gif
雖然有點事後諸葛,
但是一直以來,看程設的書上,
一直都是要大家不要使用cpu計算的延時作法,

FATZEROS大:
   您的 接收器還擱在那裡!!(不好意思!!) ,我有在看(鑽研)!! 只是有兩極的現象,RS232 時間很快,每秒鐘4800 BIT!! 所以會手忙腳亂!! 而電波時鐘則是反過來(一秒鐘一個信號,慢到可以!!) 還在想辦法解決這樣的問題!! 其實我用延遲的機會還不大!! 只是 中断優先還沒懂!!
發表於 2012-9-11 00:43:43 | 顯示全部樓層
一併回覆胸脯啞謎大和ysc大,呵!這倒是,小妹之前寫的,沒有善用技巧,一口氣配了將近128bytes的buffer,反正,不管是GPGGA、GPRMC,或是其他的,至少會塞一段進去...........結果,判斷式,依然只是拿GPRMC來用,有夠浪費的,還好MCU的ram夠大可以讓小妹這樣惡搞。
 樓主| 發表於 2012-9-11 11:18:16 | 顯示全部樓層
晴兒 發表於 2012-9-11 12:43 AM static/image/common/back.gif
一併回覆胸脯啞謎大和ysc大,呵!這倒是,小妹之前寫的,沒有善用技巧,一口氣配了將近128bytes的buffer, ...

晴兒大:
      你的意思是 把"$GPR" 判斷之後就把他全吃下來是不是啊!! 然後在慢慢比對....
     還有中斷優先順序,一般來說 UART 都被百在後面(低優先) 需要把他放前頭嗎?
     感謝指導!!
發表於 2012-9-11 13:37:30 | 顯示全部樓層
antlu 發表於 2012-9-11 11:18 AM static/image/common/back.gif
晴兒大:
      你的意思是 把"$GPR" 判斷之後就把他全吃下來是不是啊!! 然後在慢慢比對....
     還有中 ...


照胸脯啞謎大和ysc大提供的建議,小妹我理解到的是如您說的這樣沒錯。
判斷$GPRMC之後,就一口氣一直讀進來,然後處理。
小妹那時候給您的參考程式,裡面的寫法,是有判斷$GPRMC後就一直收進來,只是還是有點殺時間,畢竟一直等(不斷從buffer內拿資料,資料拿完了還沒拿到所需要的,所以一直等,且不斷撈buffer),等資料都拿齊後,就把UART的中斷給關了,專心去處理資料,處理完才又把中斷打開,跑去執行其他任務,讓buffer塞滿,因為有跑去做其他task。
發表於 2012-9-11 14:54:53 | 顯示全部樓層
晴兒 發表於 2012-9-11 01:37 PM static/image/common/back.gif
照胸脯啞謎大和ysc大提供的建議,小妹我理解到的是如您說的這樣沒錯。
判斷$GPRMC之後,就一口氣一直讀進 ...

個人建議每讀一個字元中斷一次,也就是字元與字元之間的等待時間要讓cpu去做其他的事,在那邊空等待太浪費了。
至於接收中斷程式必須靠記憶體、旗號等來做記號,下次進入接收中斷程式時才知道如何繼續接下去。

寫些通訊界面程式,不只傳送、接收需要用到中斷,有時還要跟計時中斷、主程式等互相接力搭配,這樣才會靈活。

多工式程式架構就是做該做的事,遇到等待就跳開,善用記憶體做記號,原則就是這麼簡單.......
發表於 2012-9-11 19:11:42 | 顯示全部樓層
antlu 發表於 2012-9-9 11:38 PM static/image/common/back.gif
胸脯啞謎大:
      中断優先順序!! 還沒學到!! 我把 YESJAMAIL大 和 晴兒大 的建議都改了,但是還是沒辦法 ...

看了一下你的程式 我有幾點建議(我沒寫過單晶片程式 如有錯 請見諒)
1.如果要讓output 不閃動 只要比對displat上的時間與新時間是否一樣就可以 不用timer
2.建立一個buffer 儲存從gps接收到的字(須要建立一個指標指示目前的位置)
3.不要使用while 去做等待的動作
4.程式一開始做完init後只要起動timer 一切都由timer去作動
 樓主| 發表於 2012-9-11 19:13:43 | 顯示全部樓層
ysc 發表於 2012-9-11 02:54 PM static/image/common/back.gif
個人建議每讀一個字元中斷一次,也就是字元與字元之間的等待時間要讓cpu去做其他的事,在那邊空等待太浪 ...

ysc大:
     感謝!! 若是以 BAUD RATE 4800 =208 uS /bit 每一個字元 10bit 就是 2.8mS ,這樣算一下還真的應該用 中斷來處裡其他的事情!!
 樓主| 發表於 2012-9-11 19:26:00 | 顯示全部樓層
晴兒 發表於 2012-9-11 01:37 PM static/image/common/back.gif
照胸脯啞謎大和ysc大提供的建議,小妹我理解到的是如您說的這樣沒錯。
判斷$GPRMC之後,就一口氣一直讀進 ...

晴兒大:
    你給我的程式"太高深了"大部分看不太懂,所以我採用 LEGION大的 組合語言來改寫!!
   我再把你的程式研讀一下!! 你的軌跡紀錄器強啊!!  中斷要開就開要關就關,會白了不少頭髮喔!!
發表於 2012-9-11 20:25:52 | 顯示全部樓層
這個東西應該不會弄的這麼複雜才是
同一時期的東西我把他給作成這樣如下圖
gps接收作個外殼
DSC_1550.jpg
整個完成品組合,一個奇怪的時鐘定時器
DSC_1542.jpg
t0,t1,t2都用上了,弄的有點麻煩
antlu大,你的所有的東西都是被gps端給拉下,算看看陣列顯示的時間
加上gps本身要收多少次的$xxx才能有一次是你要的,
大概你收了0.5s左右的uart信號才會來到一次你要的地方
不管怎麼算只要時序一個沒拿準,閃或頓都是正常的
這並不是在gps端換成組合語言就能解決的,.
 樓主| 發表於 2012-9-11 21:03:52 | 顯示全部樓層
本帖最後由 antlu 於 2012-9-11 09:07 PM 編輯
legion 發表於 2012-9-11 08:25 PM static/image/common/back.gif
這個東西應該不會弄的這麼複雜才是
同一時期的東西我把他給作成這樣如下圖
gps接收作個外殼


LEGION大:
   您終於現身了!! 您的大作 這兩張照片怎麼夠呢? 多PO一些照片和經驗與大家分享吧!!
   GPS 資料送出0.5秒 還有 $GPRMC,... $GPGGA,... $GPGSA,... 一輪 要 136 byte ,1360 bit 約0.4秒...而$GPRMC,... 58 byte ~ 120ms  ... 難怪會一直跳動,閃動!! 也難怪 我用 LCM 就比較沒問題(偶而會"跳秒") 一但 點陣LED 就不行了!!
您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

關閉

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

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

GMT+8, 2024-11-22 05:53 PM , Processed in 0.186238 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.