- SF800 Solar Speicher Tutorial         
Ergebnis 1 bis 10 von 29

Thema: Senden und empfangen auf dem UART mit ISR kompatibel zur bisherigen RP6lib

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #6
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    Ok, da das Thema ISR für dich Neuland zu sein scheint, versuche ich das noch etwas genauer zu erklären.

    Prozessoren arbeiten normalerweise einfach ein Programm ab und fragen dabei Zustände ab.
    Auch wenn Prozessoren dabei sehr schnell sind, bedeutet das ggf. warten auf ein Ereignis/Zustand.
    Wärend des Wartens kann es nun sein das an anderer Stelle etwas passiert, also ein Ereignis statt findet.
    Dafür hat man Interrupts erfunden. Der erste, wichtigste und selbstverständlichste "Interrupt"
    ist eigentlich das Reset Signal. Es zwingt den Prozessor die Programmstruktur von vorn abzuarbeiten, und
    unterbricht die laufende Arbeit.
    Es gibt weitere Interrupts, manche hängen mit externen Leitungen zusammen, manche passieren auf Grund
    von Änderungen im Prozessor. Der Unterschied von einem Reset zu einem echten Interruprt wie man es im
    RP6 nutzt ist, das man nach einem Interrupt an der Stelle weiter arbeiten kann, wo man vom Interrupt
    unterbrochen wurde. Wärend einer Warteschleife kann also auf Anforderung eines Interrupts spezieller Code
    abgearbeitet werden und nach Beendigung des Spezialcodes kehrt der Prozessor an seine Warteschleife zurück.
    Diesen speziellen Code nennt man ISR. Interrupts haben dabei Eigenschaften.

    Interrupts kann man per Software einzeln oder alle ab und an schalten.
    Interruptquellen gibt es massenhaft... ich meine so um ca. 20 im RP6 und werden durch bestimmte Ereigisse ausgelöst.
    Andere Prozessoren kennen bis zu mehrere hundert und sogar per Software auslösbare.
    Allerdings muss man eine ISR nur für die Interrupts haben wenn man diesen speziellen Interrupt auch braucht / nutzt.
    Interrupts bzw. die Ausführung der passenden ISR können geschachtelt passieren wenn 2 Interrupts dicht aufeinander folgen.
    ISR sollten kurz sein damit schnell wieder zum vorherigen Programmteil zurück gesprungen werden kann.
    Das Hauptprogramm merkt nicht das es durch ein Interrupt unterbrochen wurde. Da ISR aber Register und Variablen ändern
    können, sollten alle diese Variablen als volatile definiert sein.
    Der Compiler sorgt durch die Definition ISR dafür, das die Register im Prozessor vor Ausführung der ISR gesichert und bei beenden
    der ISR der alte Zustand in den Registern wieder hergestellt werden.

    Eine ISR ist also ein kleines Stück Programm, welches unabhängig vom Hauptprogramm bei Eintreten eines Ereignisses
    ausgeführt wird. Nehmen wir als Beispiel einen Radencoder aus der RP6RobotBaseLib.c.

    Code:
    ISR (INT0_vect)
    {
        mleft_dist++;
        mleft_counter++;    
    }
    Der Radencoder leitet sein Signal ENC_R oder L laut Schaltplan an PD2 bzw. PD3. Impulse an PD2 und PD3 führen
    daher zum auslösen des jeweiligen Interrupts. Eingeschaltet wurden die Interrupts in der Funktion void initRobotBase(void)
    unter // Initialize External interrupts:

    Rollt der RP6 nun, werden sehr viele Interrupts ausgelöst und wie in der ISR zu sehen 2 Variablen aufaddiert.
    Würden wir an der Stelle keinen Interrupt einsetzen, müsste der Prozessor laufend den Eingang auf Veränderungen abfragen.
    Gehen würde das auch aber der RP6 könnte kaum noch was anderes machen.
    Also nutzt man da besser Interrupts.

    Guckst du dir nun das UART file an, wirst du sehen das zum Empfangen von Zeichen schon eine ISR genutzt wird.
    Beim senden wird in der Originaldatei das Senderegister durch eine Warteschleife mit while (!(UCSRA & (1<<UDRE)));
    abgefragt. Das bedeutet, der Prozessor wartet mit dem versenden von Zeichen IM HAUPTPROGRAMM bis jeweils das Senderegister leer ist um ein weiteres Zeichen zu versenden.
    In der Zeit passieren zwar Interrupts aber er macht eben nichts anderes.
    Meine Änderung ist in der Hauptsache der Umbau der Sendefunktion auf ISR, so das das nächste Zeichen aus einem Ringbuffer (32 Byte) "automatisch" bzw. per ISR ins Senderegister kopiert wird sobald das Register frei ist. "Senderegister frei" ist dabei eine der vielen Interrupt quellen. Das Hauptprogramm füllt also den Buffer und die ISR arbeitet das ab.
    Es gibt 2 Situationen, die eine Ausnahme erfordern. Buffer voll.... dann muss eben doch gewartet werden bis wieder Platz
    im Buffer ist.. oder Buffer leer.. ist nichts zum senden da ...dann muss man den Interrupt abschalten.
    Daraus folgt, das man in der Sendefunktion den Interrupt zunächst anschalten muss damit die ISR dann die weitere Arbeit
    machen kann... Das ist auch der Unterschied zwischen Radencoder- und UART-ISR ..Die ISR für die Radencoder läuft
    immer, die SendeISR nur dann wenn Zeichen zu übertragen sind. Damit wartet aber nicht mehr das Hauptprogramm auf "Senderegister frei". Das verändert natürlich das Laufzeit Timing des Hauptprogramms so lange der Buffer nicht voll ist.
    Ein komplexes Betriebssystem könnte nun z.B. auch noch den Buffer vergrößern wenn es auf "Buffer voll" trifft. Für den RP6 ist das aber zu komplex bzw. zu viel Aufwand.

    ISR sind also kleine Progrämmchen, die auf ein Event (IRQ oder Interruptrequest) hin unabhängig vom Hauptprogramm
    vom Prozessor angesprungen werden. Das ist ein sehr vielseitiges Konzept und kann sogar dafür genutzt werden,
    eine Form von Multitasking (Timeslicing) zu nutzen indem per ISR und Timerinterrupt zwischen mehreren Hauptprogrammen
    umgeschaltet wird. Beim RP6 wird dies so nicht genutzt, dort laufen aber viele Reaktionen auf Sensoren über ISR.

    So.. das war eine kurze Einführung zum Thema ISR aus dem Ärmel geschüttelt. Vielleicht hilft dir das weiter.

    Weitere Änderungen von mir betreffen eigentlich nur einen etwas anderen (einfacherem) Ringbuffer Algorithmus, die Erkennung des Zeichen 0x00, welches vorher nicht erkannt werde konnte weil 0x00 als returnwert für "kein char empfangen" stand und ein wenig Kosmetik.
    Gruß
    Geändert von RolfD (21.04.2014 um 11:55 Uhr)
    Sind Sie auch ambivalent?

Ähnliche Themen

  1. IR Senden und Empfangen mit ATtiny
    Von bnitram im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 03.03.2012, 12:32
  2. Problem mit dem senden von Zeichen per UART
    Von KingTobi im Forum C - Programmierung (GCC u.a.)
    Antworten: 14
    Letzter Beitrag: 30.10.2008, 20:29
  3. Atmega32/STK500 -UART senden/empfangen klappt nicht
    Von Leuchtturm im Forum C - Programmierung (GCC u.a.)
    Antworten: 12
    Letzter Beitrag: 16.01.2007, 14:02
  4. Uart senden empfangen Interrups
    Von ronald im Forum AVR Hardwarethemen
    Antworten: 15
    Letzter Beitrag: 06.03.2006, 20:24
  5. UART ermöglicht Senden, aber kann nicht Empfangen
    Von batti112 im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 18.09.2004, 15:05

Berechtigungen

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

LiFePO4 Speicher Test