RS232 Daten übertragung

Gast #151272
Lesenswert?

Hi.

Ich will über eine rs232 schittstelle daten übertragen.
Um dem AVR ein kommando zu senden, sende ich einfach ein byte. nun muss
ich aber auch in manchen fällen werte (von mehreren bytes) zum AVR
übertragen.
Jetzt wollte ich fragen, wie ich das am besten mache. Da müsst ich ja
ein kommando voraus senden, das mir eine mehr byte übertragung
initialisiert. oder wär es besser, jedes kommando aus 3 bytes bestehen
zu lassen? Das erste byte wäre dann immer das kommando und die 2
anderen die (optimalen) parameter.

Gibts dazu ein beispiel, wie ich sowas machen kann ?

MfG Achim
Gast #151274
Lesenswert?

"In C gibt es für so was Librarys"
Prima sinnfreie Aussage. Hättest auch schreiben können:
"In Assembler gibt es für so was Librarys".

Über die Rechtschreibung und das gute Deutsch schreibe ich jetzt mal
lieber nichts.

Zum Thema:

Wie Du das am besten machst, hängt von der Anwendung ab.
In mittleren bis grossen Applikationen ist es sinnvoll, das Ganze über
eine Zustandsmaschine mit (Ring-)Puffer und Interrupt zu lösen.

Was muss denn der MC alles machen?
Gast #151275
Lesenswert?

Der µC mus folgendes machen:

- Messwerte von sensor erfassen (jede 3 Sekunden)
- Ein 4x 27 Text-Display ansteuern (mit menü)
- Werte in EEprom speichern und auslesen
- 3 Taster Pollen
- und halt den UART ansteuern

bis jetzt habe ich den µC nur per Interrupt auf 1 Byte-Befehle
reagieren lassen:


SIGNAL (SIG_UART_RECV) {
  unsigned char data = UDR;
  switch (data) {
      case '1': uart_puts("Test\n"); break;
      case 'i': uart_puts("Text\n"); break;
      default: uart_puts("Befehl nicht erkannt");break;
  }
}

Bis jetzt hats so auch immer gereicht, aber jetzt muss der AVR auch
daten (einstellungen) empfangen können.
Das mit dem Ring-Puffer verstehe ich nicht ganz.
Ich hab mal überlegt das so zu lösen:

unsigned int char_index;
unsigned char puffer[3];

SIGNAL (SIG_UART_RECV) {
  unsigned char data = UDR;
        if (char_index > 0)
        {
            puffer[char_index] = data;
            if (char_index >= 3)
            {
               char_index = 0;
               bearbeite_befehl(&puffer);
            }
        }
        else
   switch (data) {
      case '1': uart_puts("Test\n"); break;
      case 'i': uart_puts("Text\n"); break;
      case 's': char_index=1;puffer[0] = data;break;
      default: uart_puts("err");break;
    }
}

(nur ein beispiel aus dem kopf)
aber wenn meine datenübertragung mittden drin abbricht, dann hab ich
ein Problem (mein µC denkt, es kommen noch einstellungsbytes und
übernimmt somit falsche daten)

Gruß
Gast #151276
Lesenswert?

Die komplette Datenverarbeitung solltest Du aus dem Interrupt
rausnehmen. Deshalb auch der Ringpuffer: Das ist nichts anderes als ein
(virtuell) ringförmiger Speicherbereich, der kein Ende und keinen Anfang
hat, es gibt halt zwei Zeiger, einer zeigt auf die nächste zu
beschreibende Speicherstelle, der andere auf das letzte, nicht
bearbeitete Datum. Immer, wenn ein Receive-IRQ kommt, wird das Datum in
den Puffer geschrieben und der Zeiger eins hochgesetzt.
Die Auswertung machst Du dann in einem Interrupt niederer Priorität
oder im Hauptprogramm.
Das Problem, dass Deine Routine hängenbleiben kann, löst Du, indem Du
einen TimeOut einbaust, z.B. bei Beginn der Auswertung ein Flag setzen
und dann im Timer-IRQ nach einer gewissen Zeit zurücksetzen.
Gast #151277
Lesenswert?

@Dieter:
Wie meinst du das, die komplette datenverarbeitung raus nehmen ?
Soll ich in der Interrupt Routine nur noch der datenempfang realisieren
oder wie ?
soll ich dann sobald der puffer voll ist, erst zu einer
datenverarbeitungsroutine wechseln und dort das empfangene (puffer
inhalt) verarbeiten.

Das mit dem zurücksetzen habe ich verstanden.
wo stehen denn die interrupt prioritäten ?

MfG
Gast #151278
Lesenswert?

Das mit der Verarbeitung siehst Du richtig.
Den Puffer kannst Du im Prinzip jederzeit verarbeiten, natürlich aber
so, dass er nicht überläuft (abhängig von der UART-Geschwindigkeit).
Am besten in Form einer Zustandsmaschine, d.h. nach jedem verarbeitetem
Zeichen wird der Zustand gewechselt und gegebenfalls die Maschine
zurückgesetzt. Das würde ich dann aber mit einer Start- und
Stopp-sequenz machen, das spart den Timeout.
Bei mir habe ich etwas Ähnliches laufen (Freisprecheinrichtung für das
Telefon im Auto samt SMS, etc.), also auch UART, Display, Tasten.
Da der AVR ja unverständlicherweise keine Hardware-IRQ-Level wie andere
MCs hat, habe ich das in Software implementiert, d.h. UART hat hohe
Priorität und ist nicht unterbrechbar. Dazu zwei Timer-IRQs, von denen
der eine unterbrechbar ist und in diesem IRQ findet bei mir die
Verarbeitung des Empfangspuffers statt. Im anderen Timer-IRQ dann so
etwas wie Echtzeituhr, Tastatur-Entprellen, LEDs, etc.
In der Hauptschleife läuft dann das User-Interface, also die
Menüsteuerung.
Gast #151279
Lesenswert?

Hallo Dieter.
Klingt ja mega interessant !
könntest du mir evtl. deinen code zuschicken, damit ich mir das alles
mal anschauen kann ? Wär echt nett !
(hab leider grad keine eigene email (wegen providerwechsel) nehm
einfach die: simonfr [at] web.de )

Vielen Dank schonmal im voraus!
Gruß Achim

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