NMEA - Protokoll / UBLOX SAM - LS / ATMEGA 16

Gast #496659
Lesenswert?

Hallo Leute.

Ich hab gerade ein Problem mit einem Ublox SAM - LS GPS Receiver.
Ich will einfach die Daten über die serielle Schnittstelle einlesen 
(verwende einen ATMEGA 16). Besonders interresiert mich der GGA 
Datensatz des NMEA Protokolls. Hat irgendjemand schon einmal einen C 
Algorithmus geschrieben der das macht?
Ich glaube meiner ist falsch denn ich bekomme lauter wirre Zeichen, die 
nicht mal richtig nach ASCII ausschauen.

Hoffe ihr könnt mir helfen.

Danke Martin

PS: Anbei findet ihr noch die Schaltung und ein Datenblatt des Receivers
Angehängte Dateien:
Gast #497130
Lesenswert?

Wie wäre es, noch etwas Code mitzuliefern?
Das "Bild.gif" ist ja eher fürn Poschi, und im Datenblatt ist auch nicht 
wirklich viel beschrieben.
Hast du das Ding schon an einem PC betrieben?
An die Unterlagen, die im Datenblatt noch angesprochen werden, komme ich 
leider nicht ran (scheinbar irgendwelche Sicherheitseinstellungen...).
Gast #497136
Lesenswert?

wart ich schick einfach mal den source:

Das ist die Initialisierung des USART:

#include<avr/io.h>
#include<Standard_Basisstation_PA.h>

#define FOSZ 7372800
#define BAUD 9600


unsigned char MYUBRR;              //globale Variable für die Baudrate





/* ********************* Initialize_USART *********************
Autor: Worzfeld Martin
Klasse: 5AHELI
Datum: 12.2.2007

Übergabeparameter:   keine Übergabeparameter

Beschreibung:       Subroutine wird verwendet um die Serielle 
Schnittstelle des ATMEGA 16 zu initialisieren
          Dazu wird zunächst die Baudrate eingestellt und danach die 
einzelnen Empfangs und Senderegister
          freigegeben
***************************************************************/
void Initialize_USART()
{
  MYUBRR = (FOSZ/16/BAUD) -1;          //Errechnen der Baudrate
  UBRRH = (unsigned char)(MYUBRR>>8);      //Es wird die Baudrate 
eingestellt
  UBRRL = (unsigned char)MYUBRR;        //Es wird die Baudrate 
eingestellt


  SET_BIT(UCSRB, RXEN);            //Der Empfänger wird aktiviert
  //SET_BIT(UCSRB, TXEN);            //Der Sender wird aktiviert

  SET_BIT(UCSRC, URSEL);            //Es kann in das C Register 
geschrieben werdden

  CLEAR_BIT(UCSRC, UMSEL);
  CLEAR_BIT(UCSRC, UPM0);            //No Parity!
  CLEAR_BIT(UCSRC, UPM1);            //No Parity!
  SET_BIT(UCSRC, UCPOL);
  CLEAR_BIT(UCSRC, USBS);            //One Stopbit



  CLEAR_BIT(UCSRB, UCSZ2);          //8 Data Bit
  SET_BIT(UCSRC, UCSZ1);            //8 Data Bit
  SET_BIT(UCSRC, UCSZ0);            //8 Data Bit


  CLEAR_BIT(UCSRC, URSEL);


}
Gast #497138
Lesenswert?

und noch die Hauptroutine:

#include <avr/io.h>          //Allgemeine Include File
#include <USART_WM.h>        //Include File für die Funktionen der 
Seriellen Schnittstelle
#include <Standard_Basisstation_PA.h>  //Include für die Standard 
Bitfunktionen
#include <LCD_WM.h>
#include <stdint.h>


int main(void)
{
  DDRA = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;

  CLEAR_BIT(DDRD, 0);


  long i,j;

  char c[20];


  for(i=0; i<9000; i++){}

  Initialize_Display();
  Firstline();


  for(i=0; i<9000; i++){}

  Initialize_USART();


  TOGGLE_BIT(PORTD, 4);


while(1)
{
for(i=0; i<20; i++)
{

  while(!(UCSRA & (1<<RXC)));

  for(j=0; j<9000; j++){}
  c[i] = UDR;


}

for(i=0; i<20; i++)
{

  Fast_Write(c[i]);

}

}
Gast #497162
Lesenswert?

>  SET_BIT(UCSRB, RXEN);            //Der Empfänger wird aktiviert
>  //SET_BIT(UCSRB, TXEN);            //Der Sender wird aktiviert

>  SET_BIT(UCSRC, URSEL);            //Es kann in das C Register
geschrieben werdden

>  CLEAR_BIT(UCSRC, UMSEL);
>  CLEAR_BIT(UCSRC, UPM0);            //No Parity!
>  CLEAR_BIT(UCSRC, UPM1);            //No Parity!
>  SET_BIT(UCSRC, UCPOL);
>  CLEAR_BIT(UCSRC, USBS);            //One Stopbit



>  CLEAR_BIT(UCSRB, UCSZ2);          //8 Data Bit
>  SET_BIT(UCSRC, UCSZ1);            //8 Data Bit
>  SET_BIT(UCSRC, UCSZ0);            //8 Data Bit


>  CLEAR_BIT(UCSRC, URSEL);

Geht viel einfacher (, übersichtlicher und kürzer):
UCSRB = (1<<RXEN) | (1<<TXEN);
UCSRC = (1<<UCSZ0) | (1<<UCSZ0);

>Auch ja. Die Platine wird nicht an einen PC gehängt.
Das GPS-Modul funktioniert am PC, aber nicht am Mikrocontroller?
Funktioniert denn eine Kommunikation zwischen PC und Mikrocontroller?
So kann man zuindest ausprobieren, ob die Routine überhaupt 
funktioniert.

>  while(!(UCSRA & (1<<RXC)));

>  for(j=0; j<9000; j++){}
Warum wartest du hier?
>  c[i] = UDR;


>unsigned char MYUBRR;

Schade... (hatte ich völlig übersehen): Wenn dann müsste MYUBRR unsigned 
int sein. Normalerweise ist es ein Makro, dessen Wert der Compiler (oder 
der Präprozessor) berechnet und die Werte einträgt. Dafür braucht man 
keine Variable.

>  MYUBRR = (FOSZ/16/BAUD) -1;
Führt dann natürlich auch zu einem Fehler.
Mach das mal so:
#define MYUBRR (FOSZ/16L/BAUD) -1
Ohne MYUBBR irgendwo als Variable zu deklarieren.
Gast #497211
Lesenswert?

Hallo,

ok die Warteschleife war umsonst, aber auch mit der neuen 
initialisierung hat sich nicht gerade viel geändert.
Ich speicher ja immer 2 byte in array und schreib die dann auf ein 
Display hinaus. Aber am Display kommen echt nur die wildesten Zeichen.

Ach ja, ich hab nie gesagt das der GPS Receiver am PC getestet wurde. 
Der hat seine Anwendung nur auf einer Platine. Und auch die Platine wird 
nicht an den PC geschlossen.


Danke mal für eure bemühungen

Greets martin
Gast #497229
Lesenswert?

>Ach ja
>wollte noch erwähnen das die geschichte mit myubrr gut funktioniert hat
>kann wie auch händisch errechnet 2F heraus. Der Debugger sagt auch das
>2F dann im UbrrL drin steht
Bei 9600Baud ist UBRRH = 0. UBRRH wird erst bei kleineren Baudraten > 0.
Sofern du die Baudrate während des Programmes nicht ändern willst, sehe 
ich keinen Sinn darin, dafür eine Variable zu benutzen (ist aber deine 
und nicht meine Entscheidung).

Stimmt das Bild.gif mit deinem realen Aufbau überein?
Im Programm hast du eine Fosc von 7,xxx MHz und im Schaltplan 12,xxx 
MHz.
Eins davon passt auf keinen Fall.

>Ach ja, ich hab nie gesagt das der GPS Receiver am PC getestet wurde.
Ich weiß, deswegen habe ich ja gefragt. Nicht, dass das Ding einen an 
der Marmel hat.

>Der hat seine Anwendung nur auf einer Platine. Und auch die Platine wird
>nicht an den PC geschlossen.
Hast du denn schon mal eine Kommunkation über die serielle Schnittstelle 
zwischen PC und ATMega16 zum Laufen bekommen? (Vielleicht sogar mit 
diesem Aufbau + RS232-Pegelwandler?)
Gast #497233
Lesenswert?

>weis eigentlich irgendwer was beim start vom gps geschickt wird
>kommen da gleich die nmea daten?

Sowas steht in der Regel im entsprechenden Datenblatt, das man sich bei 
u-blox runterladen kann (scheinbar jeder ausser mir...).
Gast #497243
Lesenswert?

Nun ja. Ich verwende eine Fosc von 7 MHz. Ich hab mal das GPS auf einem 
GPS Steckbrett augebaut und mir den TXD am Oszi angeschaut. Schaut ganz 
super aus, sprich ich hab ein sauberes Signal. Das GPS müsste normal 
funktionieren ist noch neu und bis auf den Testaufbau noch nie in 
verwendung geweseen.

Zu deiner letzten frage:
Nein mit einem ATMega16 hab ich noch nie eine verbindung zum PC 
aufgebaut (brauch sie ja auch nicht). Weiters kann ich nur sagen das ich 
in einem alten projekt mit einem 8051 ein verbindung mit dem PC über USB 
(FTDI - Bautein) hergestellt hab.

Welches Datenblatt benötigts du? ich bin auf der ublox seite 
registriert. Schick mir einfach den link und lad es dir runter.

Danke für deine Hilfe

Greets martin
Gast #497245
Lesenswert?

>Weiters kann ich nur sagen das ich in einem alten projekt mit einem 8051 >ein 
verbindung mit dem PC über USB (FTDI - Bautein) hergestellt hab.
Falk oder scheibt dann gerne: "Apfelmus ist Mus aus Äpfeln"...

Vielleicht solltest du mal probieren, mit dem Mega16 Daten vom PC zu 
empfangen. Wenn das klappt, funktioniert wenigstens deine 
Empfangsroutine...
Gast #497257
Lesenswert?

ich hab jetzt den txd und rxd zusammengeschlossen und das gps gerät 
abgehängt. hab dann über txd zeichne hinausgeschrieben und diese 
erfolgreich am rxd empfangen und am display ausgegeben. Also die 
empfangsroutine funktioniert
Gast #497262
Lesenswert?

Vielleicht so:
while(1)
{
  while(!(UCSRA & (1<<RXC)));
  c[0] = UDR;
  Fast_Write(c[0]);
}

Wie funktioniert Fast_Write?
Schreibt es einfach das übergebene Zeichen auf die aktuelle Stelle des 
Display's? Nach 20 Zeichen springt er dann wieder auf die erste Stelle?

>Welches Datenblatt benötigts du? ich bin auf der ublox seite
>registriert. Schick mir einfach den link und lad es dir runter.

Im oben von dir geposteten Datenblatt stehen gaaanz unten zwei Quellen. 
Die kann man scheinbar bei u-blox runterladen...
Gast #497272
Lesenswert?

Also: Hier ist mal der source für das Display

Die Waitzeiten sind erforderlich da wir den Enable selber toogeln müssen
/*********************************************************************** 
********
**                                                        **
**  Datei:        lcd.c                                        **
**  Funktion:      Ausgabe eines Textes auf LCD 
**
**            Möglich in beiden Zeilen mittels Umschaltung          **
**                                                **
**  Version:       V 1.1                                      **
**                                                        **
**  Autor:         Martin Worzfeld                        **
**                                         **
**   Weitere Autoren:  Andreas Pendl                      **
**                                                         **
**  Date: 13.03.2006                                              **
**                                                        **
**  Eingangsparameter:  keine                                      **
**                                                        **
**  Ausgangsparameter:  keine                                       **
**                                                        **
**  Rückgabewert:    keine                                      **
**                                        **
************************************************************************ 
******/

#include <avr/io.h>


/* ************************************ KONSTANTE 
****************************/

#define CLEAR_DISPLAY 0x01        // Befehl löscht ganzes Display
#define RETURN_HOME 0x02          // Setzt Cursor an Anfangsposition
#define ENTRY_MODE_SET 0x06       // Increment Display-Position, no 
Shift
#define FUNCTION_SET 0x38         // 8Bit Interface, 2 Line Display, 5x7 
Matrix
#define DISPLAY_ON 0x0E           // Display ON, Cursor ON, Blink OFF
#define DISPLAY_OFF 0x0A          // Display OFF, Cursor ON, Blink OFF
#define CURSOR_DISPLAY_SHIFT 0x14     // Cursor Move, Shift Left (<--)


/* ************************************ Funktionsprototypen 
******************/



void LCD_Out(char , int );        // char = p4 , int = wert für register
void Firstline();            // Wechsel in die erste Zeile
void Secondline();            // Wechsel in die zweite Zeile
void Initialize_Display();        // Subroutine zum inititialisieren des 
Displays
void Clear_Display();          // Subroutine um das Display zu testen
unsigned char Spiegeln(unsigned char);  // Funktion zum Spiegeln eines 
unsigned chars


/* **************** Register-Zuweisung **************** */

#define REGSELECT 7   // 1= DatenReg, 0= InstructionReg
#define READWR 6    // 1= lesen   , 0= schreiben
#define ENABLE 5    // von 1 auf 0 = TAKT-Flanke



/* **************** Bit - Funktionen ****************** */

#define SET_BIT(PORT, BITNUM)    ((PORT) |=  (1<<(BITNUM)))    //Zum 
setzen von einzelnen Bits
#define CLEAR_BIT(PORT, BITNUM)  ((PORT) &= ~(1<<(BITNUM)))    //Zum 
loeschen von einzelnen Bits
#define TOGGLE_BIT(PORT, BITNUM) ((PORT) ^=  (1<<(BITNUM)))    //Zum 
toogeln von einzelnen Bits



/* ********************* Clear_Display *********************
Autor: Worzfeld Martin
Klasse: 5AHELI
Datum: 30.1.2007

Übergabeparameter:  keine Übergabeparameter

Beschreibung:       Funktion um den Display inhalt zu löschen
*******************************************************/
void Clear_Display()
{
  LCD_Out(CLEAR_DISPLAY, 0);
}



/* ********************* LCD_out *********************
Autor: Worzfeld Martin
Klasse: 5AHELI
Datum: 30.1.2007

Übergabeparameter: char out == Byte der an das Display gesendet wird
           int reg == Registerwahl
           reg = 1 ==> Es wird ins Datenregister geschrieben
           reg = 0 ==> Es wird ins Instructionregister geschrieben

Beschreibung:       Funktion wird verwendet um Bytes an das Display 
hinauszuschreiben.
*******************************************************/
void LCD_Out(char out, int reg)
{

  out = Spiegeln(out);    //Der zu sendende Charakter muss noch 
gespiegelt werden
    int i;

  CLEAR_BIT(PORTD, READWR);  //Es wird geschrieben nicht gelesen

  if(reg == 0)        //Abfrage ob ins Daten oder Instruction Register 
geschrieben wird
  {
    CLEAR_BIT(PORTD, REGSELECT);
  }
  else
  {
    SET_BIT(PORTD, REGSELECT);
  }


  SET_BIT(PORTD, ENABLE);    //Steigende Taktflanke

    for(i=0; i<1000;i++);      // wait...

    PORTC = out;            // Ausgabe des übergebenen ASCII-Werts!

  CLEAR_BIT(PORTD, ENABLE);   // Fallende Taktflanke! Werte werden 
Übernommen.
    for(i=0; i<1000;i++);      // wait...
}


/* ********************* Firstline *********************
Autor: Worzfeld Martin
Klasse: 5AHELI
Datum: 30.1.2007

Übergabeparameter:  keine Übergabeparameter
Beschreibung:       Subroutine wird verwendet um in die erste Zeile des 
Displays zu springen
*******************************************************/
void Firstline()
{
  LCD_Out(0x80, 0); // Write to Instruction Register
}



/* ********************* Secondline *********************
Autor: Worzfeld Martin
Klasse: 5AHELI
Datum: 30.1.2007

Übergabeparameter:  keine Übergabeparameter
Beschreibung:       Subroutine wird verwendet um in die zweite Zeile des 
Displays zu springen
*******************************************************/
void Secondline()
{
  LCD_Out(0xC0, 0); // Write to Instruction Register
}




/* ********************* Initialize_Display *********************
Autor: Worzfeld Martin
Klasse: 5AHELI
Datum: 30.1.2007

Übergabeparameter:  keine Übergabeparameter
Beschreibung:       Subroutine wird verwendet um das Display zu 
initialisieren
          Genaue Beschreibung siehe Kommenatere unterhalb
*******************************************************/
void Initialize_Display()
{
  int i;                  //Zaehlvariable

  CLEAR_BIT(PORTD, READWR);          // Es wird geschrieben
  SET_BIT(PORTD, REGSELECT);        // Es wird ins Instructions - 
Register geschrieben

  for(i=0;i<10000;i++);            // Wait

  LCD_Out(FUNCTION_SET, 0);          // Betriebsmodus wird festgelegt
  LCD_Out(DISPLAY_ON, 0);           // Display einschalten
  LCD_Out(ENTRY_MODE_SET, 0);        // Eingabemodus
  LCD_Out(CURSOR_DISPLAY_SHIFT, 0);        // Cursor springt automatisch 
weiter
  LCD_Out(CLEAR_DISPLAY, 0);        // Display wird gelöscht
  LCD_Out(RETURN_HOME, 0);

}


/* ********************* Spiegeln *********************
Autor: Pendl Andreas
Klasse: 5AHELI
Datum: 12.02.2007

Übergabeparameter:  ein zu spiegelnder unsigned char c
Beschreibung:       Subroutine wird verwendet um das Display zu 
initialisieren
          Genaue Beschreibung siehe Kommenatere unterhalb
*******************************************************/
unsigned char Spiegeln (unsigned char c)
{
  unsigned char i, back;          //i = Zaehlvariable   // back der 
gespiegelte unsigned char

  for (i =0; i < 8; i++)          //Algorithmus zum spiegeln eines 
unsigned chars
  {
    if (((c << i) & 0x80) == 0x00)
      CLEAR_BIT (back, i);
    else
      SET_BIT (back, i);

  }

  return(back);              //gespiegelter Datentyp wird zurückgegeben

}

void Fast_Write(unsigned char out)
{

  out = Spiegeln(out);    //Der zu sendende Charakter muss noch 
gespiegelt werden
    int i;

  CLEAR_BIT(PORTD, READWR);  //Es wird geschrieben nicht gelesen
  SET_BIT(PORTD, REGSELECT);



  SET_BIT(PORTD, ENABLE);    //Steigende Taktflanke

    for(i=0; i<1000;i++);      // wait...

    PORTC = out;            // Ausgabe des übergebenen ASCII-Werts!

  CLEAR_BIT(PORTD, ENABLE);   // Fallende Taktflanke! Werte werden 
Übernommen.
    for(i=0; i<1000;i++);      // wait...
}

Gast #497308
Lesenswert?

- zumindest die Beschriftung am Stecker X4 ist falsch. GND ist 1,3,5... 
nicht 2,4,6...; muß aber noch nix heißen

- du verwendest Pin 13 (eigentlich 14) RxD; vermutlich auf RxD vom Mega 
16?? Die Daten kommen aber auf TxD/Pin 12 (Pin 11 in deinem Schaltplan)
Gast #497463
Lesenswert?

Hallo,

ich glaub das ganze funktioniert nicht da die Initialisierung des USART 
nicht richtig durchgeführt wird.

Köntne mir bitte jemand posten wie man eine Serielle Schnittstelle für 
folgende Einstellungen richtig initialisert:

9600BAUD; 7372800 FOsc; 8 Datenbits, 1 Stopbit, no parity

Und was ist der genau unterschied zwischen asynchroner und synchroner 
übertragung?

Danke Martin
Gast #497469
Lesenswert?

>Und was ist der genau unterschied zwischen asynchroner und synchroner
>übertragung?

Das "a"...

Hast du dir mal meinen Vorschlag oben angeguckt?

#define FOSC 7372800
#define BAUD 9600
#define MYUBRR FOSC/16L/BAUD-1

UBRRH = (unsigned char) (MYUBRR>>8);
UBRRL = (unsigned char) MYUBRR;

UCSRB = (1<<RXEN) | (1<<TXEN);
UCSRC = (1<<UCSZ0) | (1<<UCSZ0);


Synchron bedeutet, dass ein Takt mitübertragen wird. Bei einer 
asynchronen Übertragung hat man sich auf eine Baudrate geeinigt. Als 
Startsignal wird dazu dann die fallende Flanke des Startbits benutzt.
Gast #497472
Lesenswert?

Hy Rahul,

sicherlich hab ich mir deine Initialisierung angeschaut, bringt aber 
genau das gleiche Ergebnis wie die meine. Ich bin so langsam echt am 
Verzweifeln. Hab so gar schon in der Schweiz angerufen um Support zu 
bekommen, aber die können mir auch nicht weiterhelfen. Ich bin mir 
ziemlich sicher das es an der Initialiserung liegt.

Hättest du sonst noch Ideen. Ich könnt sie echt brauchen ;-)

mfg Martin
Gast #497482
Lesenswert?

Hallo Rahul,

ich glaub deine letzte Init funktioniert. Ich hab in regelmäßigen 
abständen ein $ am display und dazwischen ein Sonderzeichen "|||" 
welches vermutlich ein Trennzeichen darstellt. Da ich in meinem Haus 
arbeite habe ich vermutlich nur schlechten bis gar keinen GPS Empfang. 
Glaubst du es ist reiner Zufall, das ich plötzlich das $ bekomme;

HINWEIS: laut NMEA stellt das $ den anfang eines neuen Datensatzes, zum 
beispiel gga da.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren