Forum: Mikrocontroller und Digitale Elektronik MSP430 GPS-Daten von UART0 Probleme


von reflection (Gast)


Lesenswert?

Hallo zusammen

Ich habe hier ein Problem mit dem abholen der Daten am UART0. Hier mal 
der Code. Ich programmiere mit mspgcc und eclipse. Der Code läuft durch 
aber das Array nmeabuffer bleibt stehts leeeeeer :o)

unsigned char nmeabuffer[1024];// Empfangsbuffer GPS Daten (NMEA Format)

void init_uart_0(void)
{
  WDTCTL = WDTPW + WDTHOLD;       // Watchdog aus
  P3SEL |= 0x30;                  // P3.4 und 3.5 als USART0 TXD/RXD
  ME1 |= UTXE0 + URXE0;           // TX- und RX-Modul einschalten
  UCTL0 |= CHAR;                  // 8 data bits, 1 stop bit, no parity 
(8N1)
  UTCTL0 |= SSEL0;                // UCLK als ACLK festlegen / UCLK = 
1MHz
  UBR00=0x68;                     // 9600 Baud aus 1MHz erzeugen
  UBR10=0x00;
  UMCTL0=0x04;// Modulation der Baudrate durch Korrekturfaktor genau 
9606bps
  UCTL0 &= ~SWRST;                // USART freigeben
  IE1|= URXIE0 + UTXIE0;          // TX- und RX-interrupts anschalten
  IFG1 &= ~UTXIFG0;               // Initales interrupt-flag loeschen
}

In meiner while(1) steht dann

init_uart_0();

  int i;

  for (i = 0; i < 1024; i++)
  {
    //while (!(IFG1 & URXIFG0));
        nmeabuffer[i] = RXBUF0;
  }

    nmeabuffer[0] = '\0';  // End of File Marker an Pos0 setzen
    i = 0;
    init_spi_0();

Irgendwie will es einfach nicht so wie ich es möchte. Benutze ein Conrad 
CR4 Modul welches ein u-blox LEA 4-H drauf hat. Über Infos wäre ich 
dankbar.

Gruss reflection

von Msp 4. (msp430_crew)


Lesenswert?

Du musst die Zeichen die Du empfangen willst in der 
Interrupt-Service-Routine einlesen, nicht in einer while-Schleife!
Wozu gibst Du sonst die Interrupts frei?

von reflection (Gast)


Lesenswert?

Sorry, aber ich verstehe gerade nur Bahnhof. Kannst Du mir vielleicht 
anhand eines Codeschnipsels zeigen? Zum Thema Interrupt bin ich bis 
jetzt noch nicht vorgestossen :o) Bitte um Nachsicht

Gruss reflection

von reflection (Gast)


Lesenswert?

//while (!(IFG1 & URXIFG0));

Ach ja, wenn ich diese Zeile reinstelle (ist ja Kommentar) dann läuft 
gar nichts mehr, hat das was mit der Sache zu tun? Das Programm bleibt 
dann gleich stehen und es geht nix mehr

Gruss reflection

von Msp 4. (msp430_crew)


Lesenswert?

reflection wrote:
> Sorry, aber ich verstehe gerade nur Bahnhof. Kannst Du mir vielleicht
> anhand eines Codeschnipsels zeigen? Zum Thema Interrupt bin ich bis
> jetzt noch nicht vorgestossen :o) Bitte um Nachsicht
>
> Gruss reflection

Weißt Du denn was eine Interrupt-Service-Routine ist?
Wie beim Timer, wenn der überläuft unterbricht das aktuelle Programm und 
geht dort hin.
Bei der seriellen Schnittstelle ist es genauso. Kommt ein Zeichen an, 
geht das Programm zur ISR und dort musst Du das Zeichen weiter 
verarbeiten!

von reflection (Gast)


Lesenswert?

Irgendwie schaffe ich es einfach nicht. Er läuft gar nie in den 
Interrupt. Kann mir jemand helfen was ich falsch mache?

Ach ja, signal.h ist includiert

unsigned char nmeabuffer[1024];// Empfangsbuffer GPS Daten (NMEA Format)

void init_uart_0(void)
{
  WDTCTL = WDTPW + WDTHOLD;// Watchdog aus
  P3SEL |= 0x30;           // P3.4 und 3.5 als USART0 TXD/RXD
  ME1 |= UTXE0 + URXE0;    // TX- und RX-Modul einschalten
  UCTL0 |= CHAR;           // 8 data bits, 1 stop bit, no parity (8N1)
  UTCTL0 |= SSEL0;         // UCLK als ACLK festlegen / UCLK = 1MHz
  UBR00=0x68;              // 9600 Baud aus 1MHz erzeugen
  UBR10=0x00;
  UMCTL0=0x04;           // genau 9606bps
  UCTL0 &= ~SWRST;         // USART freigeben
  IE1|= URXIE0 + UTXIE0;   // TX- und RX-interrupts anschalten
  IFG1 &= ~UTXIFG0;        // Initales interrupt-flag loeschen
}


while(1)
{
init_uart_0();
    interrupt (UART0RX_VECTOR) usart0_rx(void)
    {
       nmeabuffer[i] = RXBUF0;
       i += 1;
    }
}

Schlussendlich möchte ich einfach das er die Daten die an UART0 RX 
ankommen in den nmeabuffer speichert. Wenn nichts kommt soll er andere 
Sachen machen, die habe ich aber jetzt nicht im while(1) aufgeführt.

Wäre echt nett wenn mir jemand helfen könnte. Habe nun schon einiges 
über Interrupts gelesen, aber es will halt immer noch nicht.

Gruss reflection

von Christian R. (supachris)


Lesenswert?

Die Interrupt Service Routine gehört ja auch nicht in eine Funktion, 
denn sie ist selber eine.
Schreib sie mal in eine extra Datei oder wenigstens außerhalb deiner 
main() Funktion.

von reflection (Gast)


Lesenswert?

Habe die Interrupt Routine mal ganz an den Anfang genommen. Nun scheint 
er reinzulaufen, aber der Buffer bleibt trotzdem leer. Ist es ein Code 
Fehler oder habe ich da vielleicht nen Wurm in der Hardware?

Gruss reflection

Danke nochmal für den wertvollen Tip!

von Christian R. (supachris)


Lesenswert?

Setzt du denn i auch irgendwann mal auf 0? Stimmt die Baudrate? Meine 
Empfänger hatten immer 4800. Stimmt die 1MHz auch wirklich?

von reflection (Gast)


Lesenswert?

Also was ich neues zu berichten habe:

Ich hab ein Signal am TX Pins des u-Blox Moduls welches ich auf den RX 
des uP führe (gemessen)

1 MHZ stimmt, mache auch den anderen UART aus dieser Frequenz und da 
klappt es.

i wird abgefragt und wenn der Buffer voll ist wieder 0 gesetzt.

Baudrate, na da bin ich mir langsam auch nicht mehr sicher. Ich habe in 
u-Blox Center 9600 baud deklariert. Frage ist halt ob er das auch so 
übernimmt. Konnte das mit dem KO irgenwie nicht so recht rausfinden. 
gesendet und gespeichert habe ich die Änderungen in u-Center. Wenn ich 
den Empfänger wegnehme udn wieder ranmache findet er auch die vorher 
abspeicherten Einstellungen.

Kann mir vielleicht jemand sagen ob ich den Buffer korrekt befülle, oder 
ob der irgnedwo im Nirvana hängt? Denke langsam aber sicher der schreibt 
mir die RX Daten irgendwo hin, nur nicht in den Buffer. Könnte das ein 
Prob mit Pointern sein?

Gruss reflection

von reflection (Gast)


Lesenswert?

Muss ich eigentlich wenn ein Interrupt anfällt, diesen nach dessen 
Abarbeitung löschen, oder macht er das selber (Flag)?

Muss ich warten bis er die Daten im Buffer vollständig drin hat? Würde 
man glaube ich mit dem Befehl

while ((IFG1 & UTXIFG0) == 0);

machen, oder?

Gruss reflection

PS: Wäre toll wenn mir jemand einen Codeschnipsel geben könnte wo Daten 
von RX einen Buffer geschrieben werden.

von reflection (Gast)


Lesenswert?

Und noch ne Frage, muss ich GIE irgendwo einschalten? Das mache ich 
nämlich nicht. Klappt das mit den Interrupts auch ohne GIE oder liegt 
wohl da der Fehler?

Gruss reflection

von Christian R. (supachris)


Lesenswert?

Der GIE muss natürlich aktiviert werden. Das Flag wird eigentlich beim 
Anspringen der ISR automatisch gelöscht. Warten musst du nicht, denn der 
Empfangs-Interrupt kommt erst, wenn das Zeichen komplett empfangen ist.
Setz doch mal einen Breakpoint am Anfang der ISR und schau, was im 
RXBUF0 steht.

von reflection (Gast)


Lesenswert?

Da steht eben immer 0 drin. Er springt auch in die Interrupt Routine. 
Ich erhöhe ja immer i um 1 und das macht er. Er schreibt mir aber wie 
gesagt immer nur 0 en in den Buffer. Scheinen auch nur 0en anzukommen. 
Wieso muss ich jetzt noch GIE extra aufführen? Er springt doch in die 
Interruptroutine? Was deklariere ich genau mit GIE. Mache ich das 
vielleicht schon mittels:

IE1|= URXIE0 + UTXIE0;   // TX- und RX-interrupts anschalten

Oben steht der komplette Code wie ich ihn im Moment habe. Wie schalte 
ich den die GIE genau ein?

Wäre über jede Info dankbar. Wenn es mal läuft schnall ich es auch 
meistens, aber so weiss ich langsam echt nicht mehr wo ich suchen soll

Gruss reflection

von reflection (Gast)


Lesenswert?

In den Codes von TI sehe ich auch nicht das da GIE eingeschaltet wird, 
oder habe ich Tomaten auf den Augen?

Gruss

von Christian R. (supachris)


Lesenswert?

In den Beispielen steht doch immer
1
_BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt

Oder eben ein anderer LPM. Und da ist das GIE Bit dabei.
Wenn im RXBUF0 nur 0 steht, kam entweder nix, und der Interrupt kam 
woanders her, ist aber unwahrscheinlich, oder dem Empfänger, Kabel 
sonstwie haben ein Problem und liefern nur 0.

Wieso hast du überhaupt den Sende-Int aktiviert?

von reflection (Gast)


Lesenswert?

Den Sende IR muss ich mal noch abschalten, habe ich einfach der 
Vollständigkeit halber drin. Also Daten kommen, das konnte ich mit dem 
KO messen, aber es steht nix im RXBuf drin. Habe jetzt auch die Kabel 
schon ca. 10 mal kontrolliert, an dem kann es also nicht liegen

Gruss reflection

PS: Das heisst ja dann, das ich so oder so mit LPM arbeiten muss, oder?

von reflection (Gast)


Lesenswert?

Kann es sein das mein Prob in der Initialisierung des UART liegt. Ich 
benutze diesen UART eben auch noch als SPI Schnittstelle.

interrupt (UART0RX_VECTOR) usart0_rx(void)
    {
       nmeabuffer[i] = RXBUF0;
       i += 1;
    }

void init_spi(void)
{
  U0CTL |= SWRST;
  P3SEL = 0x0E;                          // Port 3 fur SPI verwenden
  U0CTL = CHAR + SYNC + MM;              // SPI-Modus (8-bit, Master)
  U0TCTL = CKPL + SSEL0 + STC;           // (polarity, ACLK, 3-wire)
  U0BR0 = 0x02;                          // SPICLK = ACLK/2 entspricht 
500kHz
  U0BR1 = 0x00;
  U0MCTL = 0x00;
  ME1 |= USPIE0;                         // Modul aktivieren
  U0CTL &= ~SWRST;                       // SPI aktivieren
}

void init_uart_0(void)
{
  WDTCTL = WDTPW + WDTHOLD;// Watchdog aus
  P3SEL |= 0x30;           // P3.4 und 3.5 als USART0 TXD/RXD
  ME1 |= UTXE0 + URXE0;    // TX- und RX-Modul einschalten
  UCTL0 |= CHAR;           // 8 data bits, 1 stop bit, no parity (8N1)
  UTCTL0 |= SSEL0;         // UCLK als ACLK festlegen / UCLK = 1MHz
  UBR00=0x68;              // 9600 Baud aus 1MHz erzeugen
  UBR10=0x00;
  UMCTL0=0x04;           // genau 9606bps
  UCTL0 &= ~SWRST;         // USART freigeben
  IE1|= URXIE0 + UTXIE0;   // TX- und RX-interrupts anschalten
  IFG1 &= ~UTXIFG0;        // Initales interrupt-flag loeschen
}


while(1)
{
init_spi

... diverser C-Code

init_uart_0(); Hier soll er die Daten vom UART abholen

init_spi wieder in SPI Mode schalten damit ich die anderen Sensoren 
wieder ansprechen kann.

Kann es sein das ich da was vergesse umzustellen? Müsste doch gehen den 
UART0 einmal als SPI und einmal als serielle Schnittstelle zu nutzen, 
oder?

Gruss reflection



}

von Christian R. (supachris)


Lesenswert?

Achsoooo...sag das doch gleich. Dann musst du natürlich das UCTL0 
Register richtig beschreiben, und nicht einfach bloß |= Char. Denn bei 
SPI-Init sind ja noch MM und Sync gesetzt, die werden in deiner 
UART-Init nicht gelöscht!!! ALso arbeitet die Schnittstelle dann immer 
noch im SPI Mode. Das UTCTL0 Register genauso!

Und wieso schreibst du, er soll die Daten von UART abholen? Du kannst 
nur auf Interrupt warten, oder eben eine Polling-Routine schreiben, und 
das URXIFG auswerten.

Und was hat der Watchdog in der UART-Init zu suchen? Den musst du 
möglichst sofort nach Beginn der main(), oder wenn du große Arrays hast, 
wie z.B. dein 1024 Byte großes Char-Array noch VOR der main() 
ausschalten. Sonst macht der im besten Fall ständig einen WDT-Reset.

Da ist noch einiges im Argen bei dir.

Achso, bevor du die USART umkonfigurierst musst du natürlich UOCTL |= 
SWRST machen, sonst passiert gar nix.

von reflection (Gast)


Lesenswert?

Bitte nicht hauen :o)))) Tut mir leid, aber es sieht schon 1000mal 
besser aus als noch vor 3 Monaten :o) Das mit dem WDT habe ich schon 
gedacht, mache ich auch ganz am Anfang. Das heisst einmal deaktiviert 
muss ich den nie mehr deaktivieren oder?

Öhm, wie passe ich denn die Register nun am besten an? Soll ich zuerst 
mittels P3SEL alles auf 0x00 setzen und dann gleich wie oben vorgehen 
oder muss ich da jedes einzelne Bit auswerten? Was würdest Du machen? 
Ich weiss, es ist eigentlich ein Murks den Port als UART und SPI zu 
verwenden, aber geht halt nicht anders :o)) Würde das so klappen wie ich 
beschrieben habe, also mit zuerst 0 setzen?

Gruss und Danke!

reflection

von Christian R. (supachris)


Lesenswert?

1
P3SEL = 0x30;           // P3.4 und 3.5 als USART0 TXD/RXD
2
UCTL0 = SWRST;         // USART aus
3
UCTL0 |= CHAR;           // 8 data bits, 1 stop bit, no parity (8N1)
4
ME1 = UTXE0 + URXE0;    // TX- und RX-Modul einschalten
5
UTCTL0 = SSEL0;         // UCLK als ACLK festlegen / UCLK = 1MHz
6
UBR00=0x68;              // 9600 Baud aus 1MHz erzeugen
7
UBR10=0x00;
8
UMCTL0=0x04;           // genau 9606bps
9
IE1 |= UTXIE0;   // TX- und RX-interrupts anschalten
10
UCTL0 &= ~SWRST;         // USART freigeben

Könnte klappen.

Achso, den WDT einmal ausschalten reicht.
1
void __low_level_init(void)
2
{
3
WDTCTL = WDTPW+WDTHOLD;
4
}

Das vor die Main-Schleife. (GCC-Syntax)

von reflection (Gast)


Lesenswert?

Danke Christian

Das werde ich heute Abend gleich ausprobieren. Ich arbeite mit mspgcc.

Wieso löscht Du nicht das initiale Interrupt Flag? Muss man das nicht?

IFG1 &= ~UTXIFG0;        // Initales interrupt-flag loeschen

Wenn ich schon am Fragen bin, aber ich will es ja verstehen

P3SEL = 0x30;           // P3.4 und 3.5 als USART0 TXD/RXD
UCTL0 = SWRST;         // USART aus

Wieso setzt Du zuerst den USART und erst dann machst Du einen SWRST?

Melde mich dann wieder wenn ich mehr weiss und es testen konnte

Gruss reflection

von Christian R. (supachris)


Lesenswert?

Bei mir war da noch nie ein "initiales Flag". Höchstens das TX-Flag, das 
ansagt, dass man Senden darf. Du willst ja aber Empfangen. Das RX-Flag 
ist doch gelöscht, wenn man SWRST macht. Hab das auch noch nirgends 
gelesen.

Die Pins haben mit der USART-State-Machine nix zu tun. Eventuell musst 
du sogar die Richtung des Ports auch noch einstellen, bei manchen 
Zweitfunktionen ist das nicht automatisch, wenn man die Zweitfunktion 
aktiviert.

Auf jeden Fall muss während des Umkonfigurierens das SWRST Bit stehn, 
sonst wird nix umgestellt.

Edit: Was bringt es, das TX-Flag zu löschen? Dasheißt ja, du entziehst 
dir selber die Sende-Berechtigung.

von reflection (Gast)


Lesenswert?

Aha, dann ist schon einiges mehr klar. Hoffe ich kann es heute Abend 
testen, muss noch zur Schule...

Gruss reflection

von reflection (Gast)


Lesenswert?

Ach ja, ist

U0CTL gleich UCTL0? Habe das schon des öfteren gesehen und es hat mich 
bereits einige Male verwirrt

Gruss reflection

von reflection (Gast)


Angehängte Dateien:

Lesenswert?

Salu zusammen

Ich habe immer noch Probleme. Ich habe den Teil von supachris 
übernommen, aber jetzt gehen andere Sachen nicht mehr :o)

Habe einmal mein main.c angehängt, auch wenn ich das vermeiden wollte. 
Zerreisst mich bitte nicht in der Luft, wird vermutlich so ziemlich 
jedes Verbrechen beinhalten was man sich vorstellen kann. Bin wie 
bereits erwähnt blutiger Anfänger, also nicht kloppen :o)

Wenn ich den Uart0 so initialisiere wie supachris es geschrieben hat, 
läuft er mir in einen Interrupt wenn ich den Uart1 aufrufe (siehe main, 
relativ weit unten dort wo sdbuffer auf 505 geprüft wird), sprich, das 
Programm bleibt einfach stehen. Am Uart 1 kommt nichts an, der sendet 
nur, sollte er auf alle Fälle.
Weiter wird der Interrupt von UART0 nicht mehr ausgelöst. Habe eine 
Breakpoint in die Interruptroutine gesetzt und er hält dort nie an.

Wäre echt toll wenn jemand das Problem finden würde. Ich habe gestern 
wieder bis weit in die Nach daran herumgebastelt, aber es will einfach 
nicht so wie ich es gerne hätte. Konnte dafür viel lernen wie man den 
Debugger einsetzen kann :o)

Gruss reflection

PS: Mein Teil (Initialisierung Uart0 ist noch drin, aber als Kommentar. 
So lief er immer in den Interrupt, aber nmeabuffer blieb stets leer

von reflection (Gast)


Lesenswert?

Also bei Uart1 läuft er nicht mehr in einen Interrupt, keine Ahnung was 
da falsch war.

Uart0 geht aber immer noch nicht. Er springt gar nie in die Interrupt 
Routine, Daten kommen aber sicher an und ich habe jetzt noch einmal die 
Pinbelegung angeschaut und sie scheint korrekt zu sein. TX von GPS geht 
auf Pin33 (MSP430F149) also RX0

Gruss reflection

von Christian R. (supachris)


Lesenswert?

Alsooo....dass er bei UART1 Senden eine ISR aufruft, ist ja klar, 
schließlich hast du ja den TX-Int aktiviert. Du bekommst also einen 
Interrupt, der dir anzeigt, dass der UART zum Senden des nächsten 
zeichens bereit ist. Das macht Sinn, wenn man mit einem Sendepuffer und 
LPM arbeitet.

Mach erst mal lieber
1
void init_uart_1(void)
2
{
3
  WDTCTL = WDTPW + WDTHOLD;              // Watchdog aus
4
  P3SEL |= 0xC0;                         // P3.6 und 3.7 als USART1 TXD/RXD
5
  ME2 |= UTXE1 + URXE1;                  // TX- und RX-Modul einschalten
6
  UCTL1 |= CHAR;                         // 8 data bits, 1 stop bit, no parity (8N1)
7
  UTCTL1 |= SSEL0;                       // UCLK als ACLK festlegen / UCLK = 1MHz
8
  UBR01=0x08;                            // 115200 Baud aus 1MHz erzeugen http://mspgcc.sourceforge.net/baudrate.html
9
  UBR11=0x00;
10
  UMCTL1=0x5B;               // Modulation der Baudrate durch Korrekturfaktor genau 114942bps
11
  UCTL1 &= ~SWRST;                       // USART freigeben
12
  IE2 |= URXIE1;                // TX- und RX-interrupts anschalten
13
}

Da stand übrigens schon wieder der Unsinn, vom initialen Sende-Flag 
drin. Wie willst du was senden, wenn du das Flag löscht, was dir ansagt, 
dass du Senden darfst???

Genauso bei UART_0 init. Kein Wunder dass du nix senden kannst.

Dann bei SPI_Init:
1
void init_spi_0(void)
2
{
3
  U0CTL |= SWRST;
4
  P3SEL = 0x0E;                          // Port 3 fur SPI verwenden
5
  U0CTL = CHAR + SYNC + MM;              // SPI-Modus (8-bit, Master)
6
  U0TCTL = CKPL + SSEL0 + STC;           // (polarity, ACLK, 3-wire)
7
  U0BR0 = 0x02;                          // SPICLK = ACLK/2 entspricht 500kHz
8
  U0BR1 = 0x00;
9
  U0MCTL = 0x00;
10
  ME1 |= USPIE0;                         // Modul aktivieren
11
  U0CTL &= ~SWRST;                       // SPI aktivieren
12
}

Zuerst setzt du das SWRST-Bit, OK, das ist richtig. Aber 2 Zeilen weiter 
unten löscht du es schon wieder, indemk du die Bits für SPI einfach 
setzt, anstatt sie per |= zu aktivieren. Das wird nicht ordentlich 
klappen.

Wieso hältst du dich nicht an die Reihenfolge der USART-Init aus dem 
User Guide?

von reflection (Gast)


Lesenswert?

Ich komme nicht mehr draus, sorry...

Also UART1 und SPI0 laufen tadellos und machen auch was sie sollen, das 
kann ich kontrollieren. Mein Prob liegt bei UART0. Wie gesagt, er läuft 
nicht in den Interrupt, weiss nicht wieso auf einmal nicht mehr. Die 
Daten werden auf alle Fälle einfach über TX Uart1 auf den PC ausgegeben, 
das funktioniert. Auch das mit dem Umstellen auf SPI funktioniert nun 
wieder.


Wenn ich das Prog wie oben ausführe macht UART1 keinen Interrupt, das 
Prog läuft einfach drauf los und sendet die Daten an die serielle 
SChnittstelle, ohne Interrupt

Wenn ich UART0 definiere passiert gar nichts, er springt nie in die 
Interrupt Routine.

Nach UART0 konfiguriere ich ja wieder alles im SPI Mode. Das läuft auch, 
ich kann auch nach zig Durchläufen durch while(1) Daten via SPI lesen.

Gruss reflection

PS: Das mit dem Flag habe ich noch nicht korrigieren können, aber das 
sollte ja nicht so einen Fehler auslösen, oder?

von Christian R. (supachris)


Lesenswert?

Du hast ja auch in deinem Code oben nur den Sende-Int für UART0 
aktivier:
1
IE1 |= UTXIE0;

Ich würds mal mit URXIE0 probieren.

von reflection (Gast)


Lesenswert?

Nö, in meinen main.c steht

void init_uart_1(void)
{
  P3SEL |= 0xC0;                         // P3.6 und 3.7 als USART1 
TXD/RXD
  ME2 |= UTXE1 + URXE1;                  // TX- und RX-Modul einschalten
  UCTL1 |= CHAR;                         // 8 data bits, 1 stop bit, no 
parity (8N1)
  UTCTL1 |= SSEL0;                       // UCLK als ACLK festlegen / 
UCLK = 1MHz
  UBR01=0x08;                            // 115200 Baud aus 1MHz 
erzeugen http://mspgcc.sourceforge.net/baudrate.html
  UBR11=0x00;
  UMCTL1=0x5B;               // Modulation der Baudrate durch 
Korrekturfaktor genau 114942bps
  UCTL1 &= ~SWRST;                       // USART freigeben
  IE2 |= URXIE1 + UTXIE1;                // TX- und RX-interrupts 
anschalten
  IFG1 &= ~UTXIFG1;                      // Initales interrupt-flag 
loeschen
}

schalte also beide frei RX und TX

von reflection (Gast)


Lesenswert?

grrrrr Sorry hier der UART0 habe versehentlich UART1 gepostet

void init_uart_0(void)
{
  UCTL0 = SWRST;
  P3SEL |= 0x30;                         // P3.4 und 3.5 als USART0 
TXD/RXD
  ME1 |= UTXE0 + URXE0;                  // TX- und RX-Modul einschalten
  UCTL0 |= CHAR;                         // 8 data bits, 1 stop bit, no 
parity (8N1)
  UTCTL0 |= SSEL0;                       // UCLK als ACLK festlegen / 
UCLK = 1MHz
  UBR00=0x68;                            // 9600 Baud aus 1MHz erzeugen 
http://mspgcc.sourceforge.net/baudrate.html
  UBR10=0x00;
  UMCTL0=0x04;               // Modulation der Baudrate durch 
Korrekturfaktor genau 9606bps
  UCTL0 &= ~SWRST;                       // USART freigeben
  IE1|= URXIE0 + UTXIE0;                 // TX- und RX-interrupts 
anschalten
}

von reflection (Gast)


Lesenswert?

Also was ich inzwischen gemacht habe:

Beim SPI die Bits mittels |= setzen  --> funktioniert

Die Zeilen wo ich diese ominösen Flags lösche entfernt. --> funktioniert

Fazit: SPI und UART1 laufen, UART0 weiterhin nicht. Er spring nie in den 
Interrupt, auch wenn ich das Flag nicht lösche. Setze ich beim noch 
_EINT(); rein, dann kreiert UART1 Sendeinterrupts, aber UART0 kommt nie 
in den Interrupt. Der UART0 Interrupt muss zeitlich gesehen sicher vor 
UART1 kommen. Die Daten des GPS (UART0) liegen bereits nach dem 
Einschalten an. Der Interrupt von UART1 wird erst gesetzt wenn der 
sdbuffer voll ist und das braucht ein bisschen Zeit (ca. 2 Sek) Da 
müssten schon lange Daten von UART0 kommen.

Ich denke es liegt nicht mehr an viel, aber es läuft halt trotzdem 
nicht. Schade, kann evtl. am Weekend wieder mal nach langer Zeit auf ne 
Rennstrecke trainieren gehen und hätte da halt gerne das Teil 
mitgenommen und getestet, aber das wird wohl nichts...

Gruss

von reflection (Gast)


Lesenswert?

Ich habe mal was anderes Probiert. Habe Hardwareseitig das GPS an UART1 
gehängt, damit ich UART0 nicht während des laufens umprogrammieren muss. 
Es läuft trotzdem nicht. Scheint also nicht an der Umkonfigurierung des 
UART0 zu liegen. Er scheint mit folgendem Code eine Interrupt zu 
generieren, aber er springt nicht in meine Interruptroutine rein, das 
Prog bleibt am Anfang einfach stehen.
Ich bin kurz davor den ganzen Print aus dem Fenster zu schmeissen und 
meine uP Projekte zu verwerfen. Ich komm einfach auf keinen grünen 
Zweig. Das kann doch wohl nicht so schwierig sein... Hat mir wirklich 
niemand einen Codeteil der genau das macht, Daten von einem UART lesen? 
Wäre echt toll!

Ich habe signal.h includiert, muss ich noch was anderes machen?

Muss ich irgendwo _EINT(); setzen? Wenn ja, wo?

Gruss reflection


void init_uart_1(void)
{
  WDTCTL = WDTPW + WDTHOLD;      // Watchdog aus
  P3SEL |= 0xC0;                 // P3.6 und 3.7 als USART1 TXD/RXD
  ME2 |= UTXE1 + URXE1;          // TX- und RX-Modul einschalten
  UCTL1 |= CHAR;                 // 8 data bits, 1 stop bit, no parity 
(8N1)
  UTCTL1 |= SSEL0;               // UCLK als ACLK festlegen / UCLK = 
1MHz
  UBR01=0x68;                    // 9600 Baud aus 1MHz erzeugen 
http://mspgcc.sourceforge.net/baudrate.html
  UBR11=0x00;
  UMCTL1=0x04;
  UCTL1 &= ~SWRST;                       // USART freigeben
  IE2 |= URXIE1;                // TX- und RX-interrupts anschalten
}

Hier dann die Interrupt Routine


interrupt (UART1RX_VECTOR) usart1_rx(void)
    {
       nmeabuffer[i] = RXBUF1;
       i += 1;
    }

von reflection (Gast)


Lesenswert?

Kann mir keiner Helfen?

von Christian R. (supachris)


Lesenswert?

An welchem Anfang bleibt es denn stehn? Ohne EINT() ist der Interrupt 
eigentlich gar nicht aktiv, nach dem Reset sollte der aus sein, also 
müsstest du halt den auch irgendwann mal freigeben.

von reflection (Gast)


Lesenswert?

Also er bleibt bei der Initialisierung des UART1 stehen

Denke er bekommt einen Interrupt von RX, aber geht nicht in die 
Interruptroutine. Muss ich den Namen der Routine noch irgendwo explizit 
definieren?

von reflection (Gast)


Lesenswert?

Muss ich irgendwie noch die Richtung der IO's definieren? Also ala

P3SEL oder so? Habe ich nicht gemacht, SPI und UART1 Senden laufen auch 
ohne. Denke das mache ich bereits in der Initialisierung, oder?

Gruss

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Poste Deinen vollständigen Quelltext, vielleicht lässt sich ja was 
finden.

Bitte als Dateianhang.

von reflection (Gast)


Angehängte Dateien:

Lesenswert?

Salu rufus

Hier mein aktuelles main.c

Wäre toll wenn Du mir sagen könntest was schief läuft :o)

Also er bleibt bei der Initialisierung des UART1 stehen

Denke er bekommt einen Interrupt von RX, aber geht nicht in die
Interruptroutine. Muss ich den Namen der Routine noch irgendwo explizit
definieren? Ich will Daten die kontinuierlich an RX1 ankommen in den 
nmeabuffer einlesen

Gruss

von Christian R. (supachris)


Lesenswert?

Dann mach doch VOR der Uminitialisierung der USART ein DINT(); und 
nachher wieder EINT();
Damit müsste das erledigt sein. Wenn ein Int kommt, springt er auch in 
die entsprechend dem Vektor deklarierte ISR. Wenn er da nicht 
reinspringt, kommt kein INT, jedenfalls nicht der, auf den du wartest.

User Guide:
"Setting PxSELx = 1 does not automatically set the pin direction. Other
peripheral module functions may require the PxDIRx bits to be configured
according to the direction needed for the module function. See the pin
schematics in the device-specific datasheet."

von reflection (Gast)


Angehängte Dateien:

Lesenswert?

Salu Christian

Ich mache es jetzt ohne Uminitialisierung, habe es mal probehalber an 
den UART1 gehängt und die Routinen angepasst. Im Post 04.09.2007 14:32 
ist nun das neue main.c

Frage: Wo ist die Defintion in den Header Files zu

interrupt (UART1RX_VECTOR) usart1_rx(void)
    {
       nmeabuffer[i] = RXBUF1;
       i += 1;
    }

Ist das im signal.h drin? Da steht nämlich überhaupt nichts von UART1RX

Mein Signal.h sieht folgenermassen aus (Attachment)

von Christian R. (supachris)


Lesenswert?

Die Vektoren sind in der msp430x16x.h deklariert.

von reflection (Gast)


Lesenswert?

Danke, die sind da, wenigstens schonmal das...

Ich werde es wohl aufgeben, glaube ich habe einfach zu wenig Ahnung und 
wenn ich nicht mal das auf die Reihe kriege, dann lass ich es lieber 
ganz bleiben. Schade um die 100te Stunden die ich bereits investiert 
habe, aber es nützt nichts, ohne einen Code der läuft komm ich nicht 
weiter

Gruss

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was soll das hier?

  IFG1 &= ~UTXIFG1; // Initales interrupt-flag loeschen

Das hier in init_uart_1 kann nicht funktionieren:

  UBR00=0x68;                          // 9600 Baud aus 1MHz erzeugen
  UBR10=0x00;
  UMCTL0=0x04;

... das sind die Register von Uart0.


Warum schaltest Du an zig verschiedenen Stellen den Watchdog wieder und 
wieder aus, ein Tritt sollte dem Vieh doch genügen ...

von Christian R. (supachris)


Lesenswert?

Sach ich ja die ganze Zeit. Er baut an zu vielen Stellen gleichzeitig 
und verliert total den Überblick. Lieber erst mal immer eins nach dem 
anderen zum Laufen bringen.

Und Aufgeben? Wassn das für ne Einstellung???

von reflection (Gast)


Lesenswert?

Hallo zusammen

Danke dafür das Ihr Euch so viel Zeit für mich nehmt. Ich hatte heute 
einen rieeeeese sch..... Tag, und irgendwie fragte ich mich wieso ich 
das eigentlich mache. Arbeite 100% also 43h, gehe noch 18h pro Woche zur 
Schule und dann habe ich halt auch noch private Projekte. Das soll keine 
Ausrede für meine obenstehende Aussage sein, aber es musste halt mal 
raus :o)

Wegen dem Wachhund: Ich dachte mir so läuft es und ich wollte zuerst die 
UART hin bekommen und danach alles aufräumen. Gibt noch mehrere Sachen 
die da anstehen, darum blieb es vorerst drin.

Was ich noch nicht geschnallt habe, auch durch mehrere Berichte die ich 
gelesen habe.

Wieso muss ich _EINT(); machen und danach noch explizit den 
entsprechenden Interrupt einschalten? Also diese Zeile z.B.

 IE2 |= URXIE1;                // TX- und RX-interrupts anschalten

Was hat das für einen Sinn? Heisst _EINT(); das ich einfach mal 
grundsätzlich Interrupts zulasse und danach läuft noch kein einziger, 
wenn er nicht noch explizit gesetzt wurde?

Ein Interrupt ist ja ein Zeiger auf eine bestimmte Adresse wenn ich das 
richtig verstanden habe, wie weiss der MSP dann wo er weiterfahren soll? 
Wird das über den Interruptnamen gemacht? UART1RX_VECTOR

Ich werde den Code morgen gleich ausprobieren!

Gruss reflection

PS: Werde sonst morgen den Code überarbeiten und mal alle Watchdogs und 
IFG1... rausnehmen, vielleicht wird es dann übersichtlicher

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Heisst _EINT(); das ich einfach mal
> grundsätzlich Interrupts zulasse

Ja.

> und danach läuft noch kein einziger,
> wenn er nicht noch explizit gesetzt wurde?

Ja.

Du musst das so sehen, es gibt Interruptquellen (die verschiedenen 
Hardwaremodule) und eine Interrupt"senke", den Prozessor.

Die "Senke" schaltest Du mit _EINT() scharf, die Interruptquellen kannst 
Du einzeln aktivieren.

_EINT() ist nur ein Macro, das das Bit GIE im Prozessorstatusregister 
setzt.

> Ein Interrupt ist ja ein Zeiger auf eine bestimmte Adresse wenn ich das
> richtig verstanden habe,
> wie weiss der MSP dann wo er weiterfahren soll?
> Wird das über den Interruptnamen gemacht? UART1RX_VECTOR

Nun, der Prozessor hat eine Tabelle, in der (Programm-)Adressen stehen, 
die aufgerufen werden, wenn der zugehörige Interrupt ausgelöst wird.
Das sind die sogenannten Interruptvektoren.
Und die werden der Einfachheit halber über ihre Namen angesprochen. Die 
sind im Datenblatt/Programmierhandbuch definiert.

Der C-Compiler hat eine (nichtportable) Spracherweiterung beigeschnallt 
bekommen, mit dem ihm mitgeteilt werden kann, daß der Code einer 
Funktion eine Interruptroutine ist und daß die Startadresse dieser 
Funktion in der Interrupttabelle an einer durch den Vektornamen 
definierten Stelle einzutragen ist.

von reflection (Gast)


Lesenswert?

Vielen Dank für die ausführliche Info! Jetzt ist es sogar mir klar 
(glaube ich im Moment zu mindest...)

Das würde dann aber heissen, das der Speicher "begrenzt" ist für so eine 
Interrupt Routine, oder? Wenn ich sagen wir mal rel. viel machen möchte 
wenn ein Interrupt auslöst wird, muss ich das dann in eine eigene 
Funktion schreiben und beim Interruptaufruf nur diese aufrufen?

Gruss reflection

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Das würde dann aber heissen, das der Speicher "begrenzt" ist für so eine
> Interrupt Routine, oder?

Nein. Die Interrupttabelle selbst enthält für jeden möglichen Interrupt 
genau einen Eintrag, und der besteht nur aus einer Adresse, dem 
sogenannten Interruptvektor.
Auf einem MSP430 sind das exakt zwei Bytes.
Dort bietet die Tabelle Platz für 16 Einträge und liegt im Adressraum 
von 0xFFE0 bis 0xFFFF. Sie ist beispielsweise im User's Manual der 
1xx-Reihe auf Seite 2-13 beschrieben.

In dieser Tabelle werden die Adressen der Interruptbehandlungsfunktionen 
gespeichert, nicht der Code der Funktionen selbst.

Um das Eintragen der Adressen kümmert sich erfreulicherweise der 
Compiler, der erzeugt auch die korrekten Aufrufbedingungen für 
Interruptfunktionen (Rückkehr mit RETI statt RET, Aufräumen des Stacks 
etc.).

> Wenn ich sagen wir mal rel. viel machen möchte
> wenn ein Interrupt auslöst wird, muss ich das dann in eine eigene
> Funktion schreiben und beim Interruptaufruf nur diese aufrufen?

Nein (s.o.).
Übrigens ist es aus Timinggründen nicht empfehlenswert, besonders viel 
Code oder besonders lange Vorgänge in einer Interrupbehandlungsfunktion 
auszuführen. So etwas sollte man in die Hauptschleife auslagern und eine 
sinnvolle Kommunikation zwischen Interruptbehandlungsfunktion und 
Hauptschleife implementieren.
Was nämlich geschieht, wenn der zeitliche Abstand zwischen dem Auslösen 
des Interrupts kürzer ist als die Laufzeit der 
Interruptbehandlungsfunktion?

Eben. Daher wird eine Uart-RX-Funktion empfangene Daten in einen Puffer 
schreiben und ein Flag setzen, daß Daten da sind, eine Auswertung der 
Daten oder gar eine Reaktion darauf aber erfolgt in der Hauptschleife.

von reflection (Gast)


Lesenswert?

Also, glaube es läuft! *schonmalfreu!*

void init_uart_1(void)
{
  P3SEL |= 0xC0;                 // P3.6 und 3.7 als USART1 TXD/RXD
  UCTL1 |= SWRST;
  ME2 |= UTXE1 + URXE1;          // TX- und RX-Modul einschalten
  UCTL1 |= CHAR;                 // 8 data bits, 1 stop bit, no parity
(8N1)
  UTCTL1 |= SSEL0;               // UCLK als ACLK festlegen / UCLK =
1MHz
  UBR01=0x68;                    // 9600 Baud aus 1MHz erzeugen
  UBR11=0x00;
  UMCTL1=0x04;
  UCTL1 &= ~SWRST;               // USART freigeben
  IE2 |= URXIE1;                 // RX-interrupts anschalten
  _EINT();
}

Hier dann die Interrupt Routine


interrupt (UART1RX_VECTOR) usart1_rx(void)
    {
       nmeabuffer[i] = RXBUF1;
       i += 1;
    }

Ich sehe nun das Daten in den nmeabuffer geschrieben werden. Nun zu 
meinem nächsten Prob:

Das GPS Modul sendet jede Sekunde einen vollständigen Datensatz. Ich 
habe im Moment 9600baud, das kann ich aber auch noch etwas schneller 
machen. Wenn ich nun das Prog laufen lasse hat er grundsätzlich immer 
Interrupts von RX und mein Prog läuft gar nie weiter, also er ist 
nonstop mit diesem Interrupt beschäftigt. Was kann man dagegen tun? 
Statt Interrupt, Polling? Wie würde das funktionieren? Das GPS sendet ja 
konstant Daten. Ich gehe einfach jedes mal wenn ich while(1) durchlaufe 
schauen ob was angekommen ist? Es kann ja dann sein das ich, wenn mein 
Prog blöd gesagt 1s durchläufzeit hät, Daten verliere oder Daten doppelt 
habe.

Wie würded ihr das Prob lösen?

Gruss und nochmals vielen Dank! Ihr seit die Besten!

reflection

von Christian R. (supachris)


Lesenswert?

Na wie schon gesagt, du musst dir überlegen, was momentan wichtig ist, 
abzuarbeiten. Solange du noch keinen kompletten Datensatz vom GPS 
zusammen hast, musst du alle anderen Aufgaben sein lassen und warten, 
bis die Daten vollständig sind. Dann musst du diese Daten verarbeiten, 
und in dieser Zeit den GPS-UART-Interrupt ausschalten. Erst wenn du 
alles andere erledigt hast, den Int wieder einschalten und auf den neuen 
Datensatz warten, geht ja immer mit $ los und endet mit CR+LF.
Einsortieren macht ja auch keinen Sinn, wenn du irgendwo in der Mitte 
gerade bist, du musst halt erst mal warten bis ein $ kommt, dann den 
Zeichenzähler auf Null setzen, und Daten einlesen. Ist die Zeile, die du 
haben willst vorbei, wird das Einlesen gestoppt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1
interrupt (UART1RX_VECTOR) usart1_rx(void)
2
{
3
  nmeabuffer[i] = RXBUF1;
4
  i += 1;
5
}

Was passiert hier, wenn der Wert i größer wird, als die Anzahl der im 
Array nmeabuffer zur Verfügung stehenden Einträge (minus eins)?

Genau, ein "buffer overflow".

von reflection (Gast)


Lesenswert?

eieiei Na da hast Du natürlich recht, ich frage in meiner While(1) 
jedes mal i ab und lösche den nmeabuffer wenn er voll ist. Da er aber 
nie mehr da rauskommt wird er natürlich auch nicht wieder auf 0 gesetzt.
Ich habe mir das so vorgestellt

while(1) läuft
Interrupt tritt auf
Interruptroutine wird abgearbeitet (also 1Byte geschrieben)
Dann läuft while(1) weiter
der nächste Interrupt kommt
Interruptroutine wird abgearbeitet (also 1Byte geschrieben)
Dann läuft while(1) weiter


So wie es scheint tritt aber sobald der erste Interrupt abgearbeitet ist 
bereits der nächste ein...

Die anderen Sachen (Beschleunigungsmessung 3-Achsen, 3x Gyro, serielle 
Schnittstelle zu PC, LCD) sollen halt schon rel. hohe Prio haben. Das 
GPS muss das nicht haben. Ich habe gelesen das jede Sekunde ein 
Datensatz kommt und dieser bei 9600baud ca. 0.8s dauert bis er 
übertragen ist. Das is natürlich ein bisschen lang.
Ich denke ich muss mir überlegen die GPS Daten auf einem eigenen uP 
einzulesen und zu verarbeiten. Was meint ihr?

Gruss reflection

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> So wie es scheint tritt aber sobald der erste Interrupt abgearbeitet ist
> bereits der nächste ein...

Das würde bedeuten, daß Du irgendwo massive Probleme mit der 
Verarbeitungsgeschwindigkeit hast.

UART-Empfang mit 9600 Baud erzeugt knapp 1000 Interrupts pro Sekunde, 
und der Code in Deiner Interruptbehandlungsfunktion ist nicht wirklich 
umfangreich.

Wenn da wirklich Interrupt auf Interrupt folgt, würde das bedeuten, daß 
Dein msp430 mit einem Systemtakt im kHz-Bereich arbeitet, also nur 
wenige Instruktionen pro Millisekunde ausführen kann.

Uhrenquarz? Falsche Initialisierung?

Andererseits scheinst Du ja die korrekte Baudrate zu erzeugen, daher ist 
mir das Phänomen schleierhaft.

von reflection (Gast)


Lesenswert?

Also ich habe einen 8MHz Quarz an der Kiste dran. Den Takt habe ich noch 
rel. langsam gewählt (1Mhz / SPI 500kHz und UART 9600baud) damit ich da 
nicht irgendwelche Probs bekomme (Freiluftverdrahtung / 
Lochrasterplatine), den schraube ich schon noch rauf wenn alles läuft.

Ob immer gleich ein Interrupt den anderen folgt weiss ich nicht, aber 
wenn ich mit dem Debugger einen Breakpoint in der Interuptroutine setze 
sehe ich das er Daten holt und diese in den nmeabuffer schreibt. Wenn 
ich einen weiteren Durchlauf mache bleibt er wieder stehen in der 
Interruptroutine.

Ich habe noch folgendes rausgefunden:

Wenn ich den MSP starte macht er noch folgendes, aber er löscht das 
Display nicht mehr clearLCD(); der Text bleibt einfach immer stehen und 
er läuft nicht weiter. Liegt das vielleicht an meinem Delay? Dieses ist 
ca. 1.25s. Was passiert genau wenn während eines solchen Delays der 
Interrupt auftritt? Ach ja, der UART1 wird natürlich vor diesen Zeilen 
initialisiert.

init_LCD();                  // LCD initialisieren

   ZeilePosition(1,3);                   // 1. Zeile 3. Position
   sendString("reflectionRacing");

   ZeilePosition(2,8);                   // 2. Zeile 8.Position
   sendString("G-Sens");

   ZeilePosition(4,3);                   // 4. Zeile 3.Position
   sendString("Ver. 0.1.2 Beta");

   delay(25000);
   clear_LCD();

Gruss reflection

von Christian R. (supachris)


Lesenswert?

Die Kunst ist, an den passenden Stellen Interrupt-Quellen ein- und 
auszuschalten, um verschachtelte Ints, priorisierte Ints oder eben den 
richtigen Programmablauf zu erzielen. Da von uns keiner wissen kann, was 
genau deine Mimik da machen soll, ist es müßig, dir den Code vorzukauen.
Das musst du selber machen.
Wenn Daten auf dem Display ausgegeben werden sollen, macht es keinen 
Sinn, das per While Schleife so schnell es geht zu machen. Da reicht ein 
Timer-Interrupt alle 500ms oder sowas. Desweiteren sollte man die NMEA 
Daten schon so schnell wie möglich vor-sortieren, macht ja keinen Sinn, 
alles zu speichern, wenn man nur die Position braucht....Vielleicht ist 
so ein kleiner MSP mit 8MHz bei so vielen Sachen einfach zu 
langsam....das musst du aber selbst entscheiden....wenn man alle 10ms 
die Beschleunigung messen will, und dann auch noch Float-Werte benutzt, 
naja, kein Wunder....

von Falk B. (falk)


Lesenswert?

@ reflection (Gast)

>sehe ich das er Daten holt und diese in den nmeabuffer schreibt. Wenn
>ich einen weiteren Durchlauf mache bleibt er wieder stehen in der
>Interruptroutine.

Ohje. Breakpoints und Interrupts vertragen sich nicht sonderlich. Dein 
Debugger kann kaum eine Echtzeitemulation machen.

>Wenn ich den MSP starte macht er noch folgendes, aber er löscht das
>Display nicht mehr clearLCD(); der Text bleibt einfach immer stehen und
>er läuft nicht weiter. Liegt das vielleicht an meinem Delay? Dieses ist

Das ist keine echte Initialisierung. Die geht anders. Sind dort die 
Zeiten eingehalten?

@ Christian Richter (supachris)

>Die Kunst ist, an den passenden Stellen Interrupt-Quellen ein- und
>auszuschalten, um verschachtelte Ints, priorisierte Ints oder eben den

Priorisierte Interrupst sind was für Leute die wissen was sie tun. Der 
OP gehört (noch) nicht dazu.

>Sinn, das per While Schleife so schnell es geht zu machen. Da reicht ein
>Timer-Interrupt alle 500ms oder sowas. Desweiteren sollte man die NMEA

Ja, wobei die Ausgabe NICHT im Interrupt erfolgt, sondern in der 
Hauptschleife, getriggert über ein Flag aus dem Interrupt.

>alles zu speichern, wenn man nur die Position braucht....Vielleicht ist
>so ein kleiner MSP mit 8MHz bei so vielen Sachen einfach zu

Kaum. Bei halbwegs gescheiter Programmierung langweilt der sich ohne 
Ende.

>langsam....das musst du aber selbst entscheiden....wenn man alle 10ms
>die Beschleunigung messen will, und dann auch noch Float-Werte benutzt,

Float braucht man selten.

Festkommaarithmetik

MFG
Falk

von Christian R. (supachris)


Lesenswert?

Ja, sach ich ja, er hat anscheinend kein schlüssiges Software-Konzept 
gemacht.Da kann das ja nicht gescheit klappen. Und erst UART Int für 
GPS-Daten freischalten, dann die wait() Funktion für´s Display...naja, 
ohne Worte.

von reflection (Gast)


Lesenswert?

Hm, da gibts wohl noch sehr viel zu machen! Werde ich auch, aber brauche 
halt für alles ein bisschen mehr Zeit :o)

Danke noch einmal an alle die mich tatkräftig unterstützt haben.

Gruss reflection

von Karl H. (kbuchegg)


Lesenswert?

reflection wrote:

> GPS muss das nicht haben. Ich habe gelesen das jede Sekunde ein
> Datensatz kommt und dieser bei 9600baud ca. 0.8s dauert bis er
> übertragen ist. Das is natürlich ein bisschen lang.

Das heist aber nicht, dass dein µC ganze 0.8s damit beschäftigt
ist über die UART zu empfangen.
Dazu hast du ja gerade den Interrupt. Wenn ein Zeichen vollständig
ist, kommt der Interrupt, der µC verbraucht ein paar µs darauf
das Zeichen zu verarbeiten und weiter gehts mit anderen Dingen.
Von den 0.8s die die Übertragung eines Datensatzes braucht,
wendet dein µC gerade mal ein paar zig µs (verteilt auf diese
0.8s) darauf auf, die Daten zu empfangen.

> Ich denke ich muss mir überlegen die GPS Daten auf einem eigenen uP
> einzulesen und zu verarbeiten. Was meint ihr?

Quatsch.

von Falk B. (falk)


Lesenswert?

reflection wrote:

> GPS muss das nicht haben. Ich habe gelesen das jede Sekunde ein
> Datensatz kommt und dieser bei 9600baud ca. 0.8s dauert bis er
> übertragen ist. Das is natürlich ein bisschen lang.

Das wären ja bei kontinuierlicher Übertragung etwa 768 Byte. Ist das so?

MfG
Falk

von jjk (Gast)


Lesenswert?

>> GPS muss das nicht haben. Ich habe gelesen das jede Sekunde ein
>> Datensatz kommt und dieser bei 9600baud ca. 0.8s dauert bis er
>> übertragen ist. Das is natürlich ein bisschen lang.

>Das wären ja bei kontinuierlicher Übertragung etwa 768 Byte. Ist das so?

Naja, kommt drauf an wie man zaehlt und was man unter "Datensatz" 
versteht;)

NMEA-Daten werden in sentences uebertragen, GGA, GSV, RMC usw.
Jeder einzelne NMEA Datensatz kann dabei bis zu 82 Byte lang sein:


At 4800 b/s you can only send 480 characters in one second. Since an 
NMEA sentence can be as long as 82 characters you can be limited to less 
than 6 different sentences.

Deshalb senden praktisch alle GPS Module und auch die GPS Maeuse nur 4-5 
NMEA Datensaetze damit es ueberhaupt innerhalb einer Sekunde update rate 
machbar ist bei 4800 Baud.
Bei 9.6 hat man etwas mehr Luft.
Der Trick besteht aber letztlich darin das Modul so zu konfigurieren 
dass es genau den einen Datensatz schickt den man braucht statt den erst 
spaeter im uC rauszufiltern.
GGA z.B. ist nur 64 Byte gross und enthaelt alle Positionsdaten.
Wenn man dann noch mit 9.6 arbeitet dauert die Uebertragung nur rund 55 
Millisekunden.

Noch geschickter ist es gleich auf NMEA zu verzichten und dafuer das 
proprietaere Protokoll, in diesem Falle uBX, zu verwenden. Da hat man 
fixe Datensatzlaengen. NMEA Datensaetze dagegen haben keine fixe Laenge, 
fehlende Daten werden naemlich nicht durch Nullen ersetzt sondern 
schlicht ausgelassen. Man muss also immer brav die Kommata zaehlen um 
auch sicher bestimmte Daten zu erwischen. Das ist aufwendiger.

Das Pendant zu GGA ist die uBx

juergen

von jjk (Gast)


Lesenswert?

>> GPS muss das nicht haben. Ich habe gelesen das jede Sekunde ein
>> Datensatz kommt und dieser bei 9600baud ca. 0.8s dauert bis er
>> übertragen ist. Das is natürlich ein bisschen lang.

>Das wären ja bei kontinuierlicher Übertragung etwa 768 Byte. Ist das so?

Naja, kommt drauf an wie man zaehlt und was man so unter "Datensatz" 
versteht;)

NMEA-Daten werden in sentences uebertragen, GGA, GSV, RMC usw.
Jeder einzelne NMEA Datensatz kann dabei bis zu 82 Byte lang sein:

At 4800 b/s you can only send 480 characters in one second. Since an 
NMEA sentence can be as long as 82 characters you can be limited to less 
than 6 different sentences.

Deshalb senden praktisch alle GPS Module und auch die GPS Maeuse per 
default nur 4-5 NMEA Datensaetze damit es ueberhaupt innerhalb einer 
Sekunde update rate machbar ist bei default 4800 Baud.
Bei 9.6 hat man etwas mehr Luft.

Der Trick besteht aber letztlich darin das Modul so zu konfigurieren 
dass es genau den einen Datensatz schickt den man braucht, statt erst 
alle zu empfangen und den einzigen den man davon braucht erst spaeter im 
uC rauszufiltern.

Die entsprechende NMEA Konfiguration macht man bei u-blox mit dem 
CFG-MSG command, nachzulesen im ANTARIS Protocol Spec Dokument 
GPS.G3-X-03002-D

GGA z.B. ist nur 64 Byte gross und enthaelt alle Positionsdaten.
Wenn man dann noch mit 9.6 arbeitet dauert die Uebertragung dafuer nur 
rund 55 Millisekunden.

Noch geschickter ist es, gleich auf NMEA zu verzichten und dafuer das 
proprietaere Protokoll, in diesem Falle uBX, zu verwenden. Da hat man 
fixe Datensatzlaengen. NMEA Datensaetze dagegen haben keine fixe Laenge, 
fehlende Daten werden nicht durch Nullen ersetzt sondern schlicht 
ausgelassen. Man muss also immer brav die Kommata zaehlen um auch sicher 
bestimmte Daten zu erwischen. Das ist aufwendiger.

Das Pendant zu GGA ist die uBX Message NAV-POSLLH mit gerade mal 28 Byte 
fixe Laenge ;)

juergen

von jjk (Gast)


Lesenswert?

Sorry, hatte auf send gedrueckt bevor ich zu Ende geschrieben hatte ;)

juergen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.