-         

Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 25

Thema: RS232 (Hardware) Buffer

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672

    RS232 (Hardware) Buffer

    Anzeige

    Hallo,

    ich Suche eine Möglichkeit einen seriellen Datenstrom zwischenzuspeichern und verzögert auszugeben. Da ich nicht sehr viel Platz habe wäre mir ein SMD-Chip recht. RS232 ist auch etwas übertrieben, die seriellen Signale sind 0V / 3,3V. die Versorgungsspannung ebenfalls 3,3V.

    Der Grund des ganzen: Ich möchte einen GPS-Empfänger an einem Atmel abfragen. Mit meinem Test-Empfänger hat alles wunderbar geklappt. Jetzt habe ich den richtigen angeschlossen (Navilock NL501 ETTL), aber der sendet die Zeichen zu schnell. Die Baudrate ist zwar schon 2400, aber die Pause zwischen den Zeichen ist zu kurz. Ich schreibe im Atmel bereits in einen Buffer, aber trotzdem werden Zeichen verschluckt.

    Da immer ca. 20 bis 50 Zeichen gesendet werden und danach eine Sekunde Pause ist müsste ich diese Zeichen in einem Buffer zwischenspeichern und dann mit Pausen Zeichen für Zeichen ausgeben.

    Mein AVR läuft bereits mit 8 MHz, deswegen denke ich das ich mit einem weiteren Atmel keinen Buffer bauen kann, auch wenn dieser sonst überhaupt nichts zu tun hat.

    Kennt jemand einen (SMD) Chip der so etwas bewerkstelligt, meinetwegen mit Abfragen der RTS Leitung oder änliches?

    Viele Grüße
    Andreas

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.08.2006
    Ort
    Budapest
    Alter
    30
    Beiträge
    563
    Wenn Du im AVR die serielle Schnittstelle Interruptbasiert behandelst, und einen FIFO Buffer mit ausreichender Grösse softwaremässig implementierst, sollte es kein Problem sein, das ganze on Chip zu erledigen.

    Im RN-Wissen Berecih gibt es den kompletten Code für Interrupt-UART und FIFO in C, funktioniert ohne Probleme.

    Eventuell könntest Du noch Deine Berechnungen i-wie optimieren (zur Not an kritischen Stellen mit inline-Assembler).

    mfg

    pongi

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672
    Hallo pongi,

    genauso ist es ja gelöst. Ich habe jetzt zum testen folgenden Code verwendet:

    U8 Pos;
    U8 Err;
    U8 Buf[255];

    Err = 0;
    Buf[0] = 0;
    Pos = 1;

    while (Buf[Pos - 1] != '$')
    {
    if ((UCSR1A & (1<<DOR1)) != 0)
    Err++;

    if ((UCSR1A & (1<<RXC1)) != 0)
    Buf[Pos++] = UDR1;
    }

    Die GPS-NMEA-Datensätze beginnen immer mit einem $-Zeichen, deshalb nutze ich das als Trenner für diese kurze Test-Schleife. Das ganze läuft auf einem AT90USB1287 als einziger Code mit einem 8MHz-Quarz. Die Baudrate beträgt 4800.

    Die Datenzeilen kommen im Sekunden-Takt und sind immer zwischen 40 und 80 Byte lang. Aber selbst hier bekomme ich in der Schleife oben zwischen 20 und 30 Err-Counts. (Data Overrun des USART)

    Wenn ich mir nach der Schleife auf einem angeschlossenem Display den empfangenen Datensatz anzeigen lasse fehlen tatsächlich ca. so viele Zeichen. Ich habe zum testen parallel den TXD-Pin über mein STK500 mit Hyperterminal angeschaut und hier ist alles da.

    Das ganze ist für mich jedoch etwas unlogisch, da bei 4800 Baud der Prozessor ja theoretisch 2ms Zeit hat bis das nächste Zeichen kommt. In dieser Zeit schafft er bei 8MHz knapp 4000 Clocks, oder bei einem Durchschnitt von 3 Clocks pro Befehl über 1000 Befehle.

    Der Quarz stimmt, da ich im selben Prozessor ein Wave mit 11025 Hz aufzeichne und diese Aufzeichnung passt.

    Einen Frame- oder Parity-Error bekomme ich nicht, das habe ich in der Schleife auch schon zählen lassen. Einzig die DOR-Anzahl erhöht sich wenn ich diese beiden Bits mitzähle.

    Wo ist das Problem bzw. mein Denkfehler? Sollte ich das ganze eventuell noch mal im AVR-Software-Forum posten?

    Viele Grüße
    Andreas

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ich steh' wahrscheinlich auf dem schlauch, ggf. bitte ich um Schläge.
    Deine Schleife bricht doch genau dann ab, wenn grad ein $ gekommen ist.
    dann geht aber doch die Message erst los ?

    Woran erkennt man, daß die Message zu Ende is ? Irgendwelche Längenangaben in der Message ?
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672
    Hallo PicNick,

    du bist nicht doof. Ich habe zur Übersicht nur den wichtigen Teil gepostet. Vorher kommt noch eine kurze Schleife die auf das erste $ wartet. Die Messung erfolgt dann über einen ganzen Datensatz. ($GPRMC-Meldung) Der GPS-Empfänger ist so konfiguriert das er nur diesen im Sekunden-Takt sendet.

  6. #6
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    I see. d.h heisst, du checkst die Message dann, wenn die nächste kommt ?
    nix gut.
    Das Ende einer Message muß doch zu erkennen sein ? gibt's da doku ?
    Irgendein Standard ? (GPS-mäßig bin ich tot)

    EDIT: Wiki lesen bildet.

    Das Ende ist offenbar ein Asteriks (*) dann würde ich
    Code:
    pos = 0
    while (1)
    {  
            errorcheck
            if zeichen 
            {
                 temp = UDR
                 if temp == $
                        pos = 0;
                 if temp == *
                        break;
                 buf [pos++] = temp
            }
    }
    workout  buf[0...pos]
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672
    Hallo PicNick,

    in meiner tatsächlichen Anwendung mit IRQ und FIFO prüfe ich auch auf den * und sogar die Checksumme. Nur in diesem kleinen Test wollte ich den Prozessor nicht mit komplizierten Prüfungen belasten.

    Aber wenn ich den Test auf den * als Prüfung umschreibe funktioniert es tatsächlich. Komisch ist nur, warum er dann vorher Zeichen verschluckt.

    Aber da werde ich jetzt mal eine Nacht drüber schlafen und hoffen das mir dazu was einfällt.

    Vielen Dank und Viele Grüße
    Andreas

  8. #8
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    ..eine Nacht drüber schlafen ..
    Recht so. Rühr dich halt wieder.
    Wie gesagt, bis 9600 muß das LOCKER auch so gehen, das gibt's nicht.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.06.2004
    Ort
    nahe Heidelberg
    Alter
    39
    Beiträge
    233
    keine Info zu GPS-Modulen:

    Sehr viele GPS-Module, welche das NMEA-Protokoll unterstützen, lassen sich auch konfigurieren. Da können so einige Sachen wie z.B. der Einsatzzweck (Mobiler einsatz, Stationärer Einsatz usw. ) aber auch einige Dinge zum Protokoll eingestellt werden. Dazu gehören z.B. welche Messages das Modul schicken soll, wie oft es Daten senden Soll und vieles mehr.

    Trotz alle dem kommt ein AVR mit 8MHz getaktet, wenn er nicht anderweitig ausgelastet ist, ohne Probleme mit nem GPS bei 9600 Baud un 3..5 Updates pro Sekunde klar.

    Gruß, Volker

  10. #10
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672
    Hallo Volker,

    selbstverständlich habe ich mein GPS-Modul konfiguriert. Das habe ich auch in einem meiner Beiträge angedeutet.

    Das Modul ist ein Sirf3-Chip den ich auf 4800 Baud und nur die Meldungen $GPRMC und $GPGSA im Sekunden-Takt konfiguriert habe. Wenn ich mir die geschickten Daten im Hyperterminal ansehe kommen die beiden Nachrichten fast auf einen Schlag in der Reihenfolge RMC und GSA, danach eine Sekunde Pause und wieder die Nachrichten...

    Ich habe ja dank des Denkanstosses von PicNick festgestellt das der Controller schnell genug ist um die Daten zu Empfangen. Bei 4800 Baud habe ich wie gesagt über 2ms Zeit zwischen den Zeichen. Das sind bei 8Mhz auf jeden Fall über 1000 Befehle.

    Ich speichere die empfangenen Zeichen im USART-IRQ in einen Buffer und setze ein Flag, wenn eine Nachricht vollständig angekommen ist. Wenn im Hauptprogramm Zeit ist wird dieses Flag überprüft, und wenn gesetzt der Buffer ausgewertet. Ich arbeite sogar mit 2 Buffern, um einen auswerten zu können und im anderen schon wieder die nächste Nachricht aufzuzeichnen.

    Allerdings funktioniert irgendwas nicht. Ich habe heute fast den ganzen Tag an dem Problem gesessen, aber keinen Fehler gefunden. Vermutlich sehe ich den Wald vor lauter Bäumen nicht mehr. Deshalb wäre es nett wenn mal hier jemand schnell über den Quellcode gucken kann wo mein brutaler Denkfehler ist.

    Erst mal die Deklarationen der Buffer, Flags, Pointer, etc.:

    volatile U8 Akt_GPS_Rekord_Buffer= 0;
    volatile U8 Akt_GPS_Rekord_Ende= 254;
    volatile U8 GPS_Buffer_Auswerten[2];
    volatile U8 GPS_Buffer_Pointer[2];
    volatile char GPS_Buffer1[255];
    volatile char GPS_Buffer2[255];

    #define Aus 0
    #define Ein 1

    Und hier die IRQ-Behandlung:

    ISR (USART1_RX_vect)
    {char Zeichen;

    Zeichen = UDR1;

    if (Zeichen == '$')
    {if (Akt_GPS_Rekord_Buffer == 0)
    {if (GPS_Buffer_Auswerten[1] == Aus)
    Akt_GPS_Rekord_Buffer = 1;

    if (GPS_Buffer_Auswerten[2] == Aus)
    Akt_GPS_Rekord_Buffer = 2;
    }

    if (Akt_GPS_Rekord_Buffer > 0)
    {GPS_Buffer_Pointer[Akt_GPS_Rekord_Buffer] = 0;
    Akt_GPS_Rekord_Ende = 254;
    }
    } else if ((Zeichen == '*') & (Akt_GPS_Rekord_Buffer > 0))
    {if (GPS_Buffer_Pointer[Akt_GPS_Rekord_Buffer] < 253)
    Akt_GPS_Rekord_Ende = GPS_Buffer_Pointer[Akt_GPS_Rekord_Buffer] + 2;
    else
    Akt_GPS_Rekord_Buffer = 0;
    }

    if (Akt_GPS_Rekord_Buffer > 0)
    {switch (Akt_GPS_Rekord_Buffer)
    {case 1: {GPS_Buffer1[GPS_Buffer_Pointer[Akt_GPS_Rekord_Buffer]++] = Zeichen;
    break;}
    case 2: {GPS_Buffer2[GPS_Buffer_Pointer[Akt_GPS_Rekord_Buffer]++] = Zeichen;
    break;}
    }

    if (GPS_Buffer_Pointer[Akt_GPS_Rekord_Buffer] > Akt_GPS_Rekord_Ende)
    {if (Akt_GPS_Rekord_Ende < 254)
    GPS_Buffer_Auswerten[Akt_GPS_Rekord_Buffer] = Ein;
    Akt_GPS_Rekord_Buffer = 0;
    }
    }
    }

    Für alle die nicht wissen wie eine NMEA-Nachricht aufgebaut ist: Sie fangen mit einem Dollar ($) an, und enden mit einem Asteriks (*) gefolgt von zwei Zeichen für die Checksumme. Also zum Beispiel:
    $GPRMS.......*AA

    Viele Grüße
    Andreas

Seite 1 von 3 123 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •