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
"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?
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ß
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.
@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
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.
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
Ich habe so was bei mir bereitgestellt: http://www.blafusel.de/misc/atmega8_io.html#6 Vielleicht hilft ja ein Studium der (einfachen) Sourcen Dir weiter.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.