Abschnitte der Website
Die Wahl des Herausgebers:
- Welche Funktionen bietet das Spielen auf dem europäischen Archeage-Server?
- Unterbrechungen in atmega8. Trainingskurs. Das Konzept der Unterbrechung. Wir geben dem Mikrocontroller eine Stimme. Das Funktionsprinzip externer Interrupts im AVR
- Interessante Fakten und nützliche Tipps Laserpointer-Datenübertragungsdiagramm
- Kurze theoretische Informationen
- Wird die SPS ihre Position in der modernen Industrieautomation behaupten können?
- Retrovirus – was ist das?
- Blogger ist ein Beruf, der Ihnen Spaß machen wird
- Reform des Wohnungswesens und der kommunalen Dienstleistungen Fonds zur Unterstützung der Reform des Wohnungswesens und der kommunalen Dienstleistungen
- Datenübertragungsnetze in industriellen Steuerungssystemen Der Prozess der dezentralen Abfrage eines Subsystems
- Methoden zur parametrischen Identifizierung von Kontrollobjekten
Werbung
Unterbrechungen in atmega8. Trainingskurs |
Einer der Vorteile des ATmega8-Mikrocontrollers ist seine große Auswahl an verschiedenen Interrupts. Unterbrechen ist ein Ereignis, bei dessen Eintreten die Ausführung des Hauptprogramms unterbrochen und eine Funktion aufgerufen wird, die einen Interrupt eines bestimmten Typs behandelt. Interrupts werden in interne und externe unterteilt. Zu den Quellen interner Interrupts gehören integrierte Mikrocontrollermodule (Timer, USART-Transceiver usw.). Externe Interrupts treten auf, wenn externe Signale an den Mikrocontroller-Pins ankommen (z. B. Signale an den RESET- und INT-Pins). Die Art der Signale, die zum Auftreten eines Interrupts führen, wird im Steuerregister eingestellt MCUCR, insbesondere in den Bits - ISC00 (Bit 0) und ISC01 (Bit 1) für den Eingang INT 0; ISC10 (Bit2) und ISC11 (Bit3) für INT1-Eingang. Im ATmega8-Mikrocontroller hat jeder Interrupt seinen eigenen Interrupt-Vektor(Adresse am Anfang des Programmspeicherbereichs, in dem der Befehl zum Sprung zur angegebenen Interrupt-Routine gespeichert ist). In Mega8 haben alle Interrupts die gleiche Priorität. Treten mehrere Interrupts gleichzeitig auf, wird der Interrupt mit der niedrigeren Vektornummer zuerst bearbeitet. Interrupt-Vektoren in Atmega8
Unterbrechungsmanagement4 Register sind für die Verwaltung von Interrupts in ATmega8 verantwortlich: GIMSK(auch bekannt als GICR) – Interrupts basierend auf Signalen an den Eingängen INT0, INT1 verbieten/aktivieren GIFR- Verwaltung aller externen Interrupts TIMSK, TIFR- Verwaltung von Unterbrechungen durch Timer/Zähler Registrieren GIMSK(GICR) INTFx=1: Am INTx-Eingang ist ein Interrupt aufgetreten. Beim Eintritt in die Interrupt-Handling-Routine wird INTFx automatisch auf den Protokollstatus zurückgesetzt. 0 Registrieren TIMSK
TOIE1=1: T/C1-Überlauf-Interrupt aktiviert OCIE1A=1: Interrupt, wenn das Vergleichsregister A mit dem Inhalt des aktivierten Zählers T/C1 übereinstimmt OCIE1B=1: Interrupt, wenn das Vergleichsregister B mit dem Inhalt des aktivierten Zählers T/C1 übereinstimmt TICIE=1: Interrupt aktiviert, wenn die Erfassungsbedingung erfüllt ist TOIE0=1: T/C0-Überlauf-Interrupt aktiviert Registrieren TIFR
TOV1=1: T/C1-Überlauf aufgetreten OCF1A=1: Vergleichsregister A stimmt mit dem zulässigen Inhalt des Zählers T/C1 überein OCF1B=1: Vergleichsregister B stimmt mit dem zulässigen Inhalt des Zählers T/C1 überein ICF=1: Erfassungsbedingungen erfüllt TOV0=1: T/C0-Überlauf aufgetreten Beim Aufrufen der Interrupt-Handhabungsunterroutine wird das dem Interrupt entsprechende TIFR-Registerflag automatisch auf den Protokollstatus zurückgesetzt. 0 Interrupts funktionieren nur, wenn allgemeine Interrupts im SREG-Statusregister aktiviert sind (Bit 7 = 1). Wenn ein Interrupt auftritt, wird dieses Bit automatisch auf 0 zurückgesetzt, wodurch nachfolgende Interrupts deaktiviert werden. In diesem Beispiel ist der INT0-Pin im Pull-Up-Eingangsmodus aktiviert. Wenn der Pin mithilfe einer Taste mit Masse kurzgeschlossen wird, wird an ihm eine logische 0 gesetzt (die Flanke des Signals fällt von der Versorgungsspannung auf 0) und der Interrupt-Handler wird ausgelöst, wodurch die mit dem Null-Pin des Ports verbundene Glühbirne eingeschaltet wird B void lampON() unterbrechen void ext_int0_isr(void) DDRD.2=0; SREG|= (1 while(1) ( Das obige Beispiel zeigt auch, wie Interrupt-Vektoren in Code Vision AVR festgelegt werden (Interrupt void ext_int0_isr(void)). Für andere Fälle werden Interrupt-Vektoren ähnlich festgelegt: EXT_INT0 2 Was ist eine Unterbrechung? Lassen Sie uns damit mit der Theorie abschließen und mit der Praxis fortfahren (obwohl es weiter unten noch mehr Theorie geben wird). Wie Sie wahrscheinlich schon vermutet haben, schreiben wir einen Interrupt (der durch eine Taste erzeugt wird), der aufleuchtet und die Diode ausschaltet. #enthalten Lassen Sie uns zustimmen, dass der Interrupt (physisch) den Strom am Controller-Zweig nicht ein- oder ausschaltet (da ich bereits darüber nachgedacht habe, dass dies erledigt ist), sondern nur das Flag ändert. Bei bestimmten Werten schaltet sich die Diode ein und aus. Int num = 1; Lassen Sie uns nun einen Interrupt deklarieren: ISR(SIG_INTERRUPT1)( if (num == 1) num = 0; else num = 1; ) Wie Sie sehen, wird in den Makroklammern der sogenannte Interrupt-Vektor angegeben. Dieser Vektor teilt dem Compiler mit, für welchen Eingang der Interrupt generiert wird. Für INT1 ist es SIG_INTERRUPT1. Bei einem ADC ist dies beispielsweise SIG_ADC. (Die gesamte Liste ist im Buch „Shpak Yu.A. Programming in C for AVR and PIC microcontrollers“ perfekt beschrieben.) Sei(); // im Allgemeinen GIMSK |= (1< Sobald dies erledigt ist, müssen Sie das Interrupt-Verhalten konfigurieren. Es kann auf unterschiedliche Weise generiert werden. Ich denke, Sie werden verstehen, wie man das übersetzt. MCUCR = (0< Nun legen wir den gesamten Port C als Ausgang fest: DDRC = 0xff; // Port C - Ausgabe Nun, das sollte schon klar sein: While (1)( if (num == 1) PORTC |= 1; // ersten Ausgang C einschalten else PORTC &= ~1; // ersten Ausgang C ausschalten _delay_ms(100); // 100 ms warten) Es besteht kein Grund zu warten. Darüber hinaus verringert sich dadurch die Leistung. Aber ich will es so. #define F_CPU 8000000UL // 8MHz #include Wir kompilieren Hex und bauen die Schaltung in Proteus zusammen. Wir freuen uns über die Unterbrechungsfunktion beim Ändern der Tastenposition. Es kommt oft vor, dass eine Mikroschaltung leise arbeiten und arbeiten muss, aber aus irgendeinem Grund alles fallen lässt und etwas anderes tut. Und dann - kehren Sie wieder zur ursprünglichen Aufgabe zurück ... Es ist zum Beispiel wie eine Uhr - sie zeigt die Zeit an, bis die Weckerzeit kommt. Und es scheint, als gäbe es keine äußeren Einflüsse – Knopfdruck, Reset – und die Mikroschaltung schaltet sich selbst. Dies kann mithilfe von Interrupts implementiert werden – Signalen, die den Prozessor über das Eintreten eines Ereignisses informieren. Hier ein Beispiel aus dem Alltag: Sie sitzen in der Küche, trinken Tee mit Himbeermarmelade und leckeren Leckereien und warten auf Gäste. Woran erkennt man, dass jemand angekommen ist? Es gibt zwei Möglichkeiten: Entweder machen wir alle fünf Minuten eine Pause von der Marmelade, ich meine den Tee, und rennen, um zu sehen, ob jemand an der Tür steht, oder wir kaufen eine Türklingel und warten in aller Ruhe an einem beheizten Ort, bis jemand klingelt. Wenn also ein Gast anruft, ist das ein Ereignis. Dementsprechend brechen wir ab und eilen zur Tür. Die Mikroschaltung hat also Unterbrechungen. Und nicht nur einer. Interrupts werden in externe unterteilt – diese werden bei einer bestimmten Spannung an einigen Pins der Mikroschaltung (INT0, INT1 und manchmal auch am gesamten PCINT-Port) ausgelöst – und intern – wenn der Zähler überläuft, wird der Watchdog-Timer ausgelöst, bei Verwendung von USART, wenn ein analoger Komparator, ADC und andere Peripheriegeräte unterbrochen werden. Dementsprechend entsteht ein Prioritätsproblem. Es ist, als würden wir immer noch da sitzen und Tee trinken, aber sie klingeln nicht nur an unserer Tür, sondern auch am Telefon... Und man lässt sich nicht auseinanderreißen, es muss zuerst etwas getan werden. Daher enthält das Datenblatt eine Tabelle mit Interrupt-Vektoren. Je niedriger die Interrupt-Nummer, desto höher die Priorität. Hier gibt es mehrere Feinheiten... Ein Ereignis ist eingetreten – eine Interrupt-Anfrage wurde gesendet, d. h. das sogenannte „Interrupt-Request-Flag“ ist gesetzt. Wenn alles in Ordnung ist, die Unterbrechung behoben ist, dann ist das Leben wunderbar und es wird verarbeitet. Wenn jedoch ein Interrupt deaktiviert ist (z. B. ein Interrupt mit höherer Priorität wird bereits verarbeitet), bleibt dieses Anforderungsflag hängen, bis Interrupts aktiviert werden. Danach überprüft der Chip das Anforderungsregister in der Reihenfolge seiner Priorität und verarbeitet es, falls ein Flag vorhanden ist. ABER! Es stellt sich heraus, dass selbst wenn die Unterbrechung verarbeitet wird, es keine Tatsache ist, dass das Ereignis, das sie verursacht hat, noch am Leben ist ... Es ist, als ob die Türklingel und das Telefon gleichzeitig klingelten, Sie gingen ans Telefon und die Gäste bereits entschied, dass niemand zu Hause war und ging. Und es schien, als gäbe es ein Ereignis – es klingelte an der Tür, aber es war niemand hinter der Tür. Ein weiteres Problem besteht darin, dass das Ereignis noch mehrmals auftreten kann, während ein weiterer Interrupt verarbeitet wird und das Anforderungsflag bereits gesetzt ist. Wir nahmen den Anruf entgegen, öffneten die Tür – und schon waren eine ganze Schar Gäste da! Beängstigend? Beängstigend... Ein weiteres Merkmal der Verwendung von Interrupts – und nicht nur von Interrupts: Wiedereintritt (oder Wiedereintritt). Ein wiedereintrittsfähiges Programm ist ein Programm, das von mehreren Benutzern (oder Prozessen) aufgerufen werden kann, ohne zumindest einen Fehler zu verursachen und höchstens ohne Rechenaufwand zu verursachen – zum Beispiel, wenn ein anderer Benutzer den Code nicht erneut ausführen muss. Mit anderen Worten: Wenn in der Küche, während Sie Gäste begrüßen, niemand ein paar Leckereien stiehlt, dann ist alles wiederkehrend.) Im Allgemeinen ist es eine ernste Sache – wenn man es nicht berücksichtigt, kann man lange Zeit mit der Frage „Warum funktioniert es nicht?!“ leiden. Dies muss beispielsweise berücksichtigt werden, wenn mehrere Interrupts verarbeitet werden und jeder einzelne eine globale Variable ändert ... Interrupts sind normalerweise NICHT wiedereintretend. Das heißt, während der Interrupt ausgeführt wird, können Sie denselben Interrupt nicht erneut aufrufen. Zum Schutz vor wiederholten Eingaben in den Handler werden Interrupts zum Zeitpunkt seiner Verarbeitung automatisch verboten (wenn Sie Interrupts im Interrupt aktivieren möchten). Man muss zehn-, zwanzigmal darüber nachdenken, bevor man so einen überstürzten Schritt wagt). Betrachten wir die Arbeit mit externen Interrupts: Wir müssen erstens konfigurieren, welches Ereignis die Unterbrechung auslöst, und zweitens, damit der Chip genau diese Unterbrechung überhaupt verarbeiten kann. Das MCUCR-Register ist für das erste im ATmega8-Chip verantwortlich – die Bits ISC11–ISC10, verantwortlich für INT1, und ISC01–ISC00, verantwortlich für INT0. Tabelle 1. Definition von Ereignissen zur Generierung eines Interrupts über INT1 Entsprechend gilt das Gleiche auch für INT0. Jetzt müssen wir nur noch die Interrupts an dem von uns benötigten Pin aktivieren – das GIGR-Register hat die Bits INT0 und INT1; auf die gewünschte „1“ gesetzt - und die externe Unterbrechung ist aktiviert! Aber es ist noch zu früh, um sich zu freuen – zusätzlich zu externen Interrupts müssen Interrupts im Allgemeinen aktiviert werden – setzen Sie das ganz linke Bit I des SREG-Registers auf „1“. Dasselbe kann mit dem Assembler-Befehl erfolgen: asm sei; Schauen wir uns ein einfaches Beispiel an: Ein Knopf wird an den INT0 (D.2)-Pin des ATmega8-Chips angeschlossen (an den Pin und an Null); drücken – es kommt zu einem Interrupt und die LED an Pin B.0 leuchtet auf. Die LED ist dementsprechend mit dem Bein und dem Gerät verbunden: //Programm für ATmega8, wenn Sie eine Taste an Pin INT0 (D.2) drücken – verbunden mit 0 – //schaltet die LED an Pin B.0 durch externen Interrupt ein – verbunden mit 1 //Typen neu definieren typedef unsigned char byte; sbit ddrButton bei ddD2_bit; //Generierungsschaltfläche sbit pinButton at pinD2_bit; sbit portButton bei portD2_bit; sbit ddrLight bei ddB0_bit; //Ausgang für die LED, zum Pull-up-Ausgang, 0 auf der Sbit-Taste schalten portLight bei portB0_bit; Byte flagButton = 0; //Button-Click-Flag; gedrückt - 1 void INT0_interrupt() org IVT_ADDR_INT0 //Sie müssen mindestens eine leere Funktion schreiben - //da der Compiler sie nicht selbst erstellt. Sonst funktioniert es nicht ( flagButton = 1; ) //Verarbeitung des Tastendrucks - unter Berücksichtigung von Bounce void buttonLight() ( if(flagButton) //wenn der Knopf gedrückt wird ( portLight = 0; //die LED einschalten delay_ms(500); portLight = 1; //die LED ausschalten flagButton = 0; ) ) void main() ( //Alle verwendeten Ports initialisieren ddrB = 0; portB = 0; ddrD = 0; portD = 0; // Initialisierung des Buttons – zum Eingang mit Pull-up portButton = 1; ddrButton = 0; //Initialisierung der LED, die bei 0 aufleuchtet und Drücken des Buttons – zum Ausgang und zu 1 portLight = 1; ddrLight = 1; / /Konfigurieren externer Interrupts MCUCR.ISC00 = 0; //Interrupt wird durch logische 0 auf INT0 generiert MCUCR.ISC01 = 0; GICR.INT0 = 1; //externen Interrupt aktivieren INT0 asm sei;//SREG.B7 = 1; / /enable unterbricht grundsätzlich Interrupts (Bit I); Befehle ähneln while(1) ( buttonLight() ; ) ) Ein wenig über die Syntax. Die Interrupt-Funktion wird wie folgt geschrieben: void function_name() org IVT_ADDR_INT0. Das Schlüsselwort org gibt an, dass als nächstes die Interrupt-Adresse aus dem Datenblatt kommt. Den Namen des Interrupts haben wir aus der Bibliothek: Wir geben IVT ein und drücken dann Strg + Leertaste (ich liebe solche Dinge ˆˆ). Sie können der Compiler-Hilfe zufolge auch iv anstelle des Wortes org verwenden. Noch eine kleine Anmerkung: Erstens sollte die Unterbrechung niemals umständlich sein – ein paar Zeilen und das war’s. Dies liegt daran, dass die Mikroschaltung bei der Verarbeitung eines Interrupts durch nichts anderes abgelenkt werden kann, was bedeutet, dass wir bei mehreren Interrupts das Eintreten eines Ereignisses verpassen können. Es kann sich auch herausstellen, dass wir überhaupt keine Interrupt-Verarbeitung benötigen – es reicht beispielsweise aus, dass die Schaltung aus dem Schlafmodus aufgewacht ist. Aber in diesem Fall müssen Sie immer noch eine Interrupt-Funktion schreiben, auch eine leere – den sogenannten „Stub“. Im Prinzip schreiben manche Compiler automatisch leere Funktionen für jeden Interrupt, aber das ist bei uns nicht der Fall – wir müssen es manuell machen. Heute werden wir uns mit dem Konzept der Unterbrechung und seiner Verwendung befassen. Natürlich verzichten wir nicht auf ein Trainingsprogramm, aber dieses Mal verzichten wir auf das Blinken der LEDs. Schon gut. Lasst uns so etwas wie eine Türklingel bauen. Aufgabe: Lassen Sie den Mikrocontroller beim Drücken einer Taste einen Piepton abgeben. Wir erstellen ein Ringprojekt im alten Arbeitsbereich. Wählen Sie den Typ des Mikrocontrollers aus. Erlauben Sie die Verwendung von Bitnamen, die in der Header-Datei definiert sind Ändern Sie den Ausgabedateityp. Speichern Sie das Projekt und den Arbeitsbereich. Stellen Sie sich die Situation vor. Sie sitzen bei der Arbeit und grübeln über einem weiteren Mikrocontroller-Programm. Der Chef kommt auf Sie zu und sagt: „Hören Sie, Pash, wir haben Oszilloskope für unsere Abteilung gekauft – Tektronix, Vierkanal.“ Hilf Vasya, sie zu ziehen.“ Du denkst: „Na ja, mein Gott, nur dieser Gedanke war im Weg … und auf dich.“ Und der Chef sieht dich so an und seine Augen sind so freundlich, so freundlich. Wie kannst du ihn ablehnen? Nun, Sie lassen alles stehen und liegen und gehen mit einem Freund Oszilloskope kaufen. Sie haben es hereingebracht. Wir haben berichtet. Und sie setzten sich wieder zu ihrem Programm. Ungefähr so sieht der Interrupt-Mechanismus aus. Ganz einfach, aber es gibt eine Reihe grundlegender Punkte. Zweitens: Das ist alles sehr ähnlich zu dem, was in einem Mikrocontroller passiert. AVR-Mikrocontroller umfassen eine ganze Reihe von Peripheriegeräten (Timer/Zähler, Analog-Digital-Wandler, Analogkomparator, asynchroner Transceiver usw.). Die Stärke des Mikrocontrollers besteht darin, dass alle diese Geräte parallel und unabhängig voneinander sowie parallel zum ausgeführten Programm arbeiten können. Jedes Peripheriegerät kann beim Eintreten eines bestimmten Ereignisses einen Interrupt auslösen. Der Interrupt tritt nur auf, wenn er aktiviert ist. Die Interrupt-Freigabe wird für jedes Gerät separat eingestellt. Darüber hinaus gibt es ein globales Enable/Disable-Flag für alle Interrupts – das ist das I-Flag im SREG-Register. Wenn ein Interrupt auftritt, speichert der Mikrocontroller den Inhalt des PC-Programmzählers auf dem Stapel, d. h. er merkt sich die Stelle, an der er unterbrochen wurde. Lädt die Adresse des entsprechenden Interrupt-Vektors in den Programmzähler und springt zu dieser Adresse. Es wird ein bedingungsloser Sprungbefehl ausgeführt, der zur Interrupt-Verarbeitungsunterroutine führt. Deaktiviert Interrupts durch Zurücksetzen des I-Flags und führt die Unterroutine aus. Nach der Ausführung der Interrupt-Handling-Routine aktiviert der Mikrocontroller Interrupts durch Setzen des I-Flags und stellt den Inhalt des Programmzählers wieder her, d. h. er kehrt an die gleiche Stelle im Programm zurück, an der er unterbrochen wurde. Theoretisch sollte der Interrupt-Handler den Inhalt der Mikrocontroller-Register nicht beschädigen, da diese möglicherweise Daten aus dem gerade ausgeführten Programm enthalten. Dazu werden zu Beginn des Interrupt-Handling-Unterprogramms die Inhalte der Mikrocontroller-Register auf dem Stack gespeichert und am Ende des Unterprogramms wiederhergestellt. Somit kann der Mikrocontroller nach dem Verlassen des Interrupts das Programm weiter ausführen, als ob nichts passiert wäre. Bei der Programmierung im Assembler schreibt der Programmierer selbst die Registerspeicherung vor, in C übernimmt dies der Compiler. Lassen Sie uns nun über den Timer sprechen. Der ATmega8535 verfügt über drei integrierte Timer/Zähler – zwei Acht-Bit-Timer (T0, T2) und einen Sechzehn-Bit-Zähler (T1). Wir werden einen 8-Bit-Timer/Zähler T0 verwenden. Dieser Timer besteht aus drei Registern – dem Steuerregister TCCR0, dem Zählregister TCNT0 und dem Vergleichsregister OCR0. Beim Starten des Timers erhöht das Zählerregister TCNT0 seinen Wert bei jeder Taktflanke um eins. Die Taktfrequenz wird aus mehreren möglichen Werten im Steuerregister TCCR0 ausgewählt. Außerdem wird über dieses Register die Betriebsart des Timers eingestellt. Der Timer T0 kann einen Interrupt auslösen, wenn ein „Überlauf“-Ereignis auftritt – das ist, wenn das Zählregister TCNT0 überläuft, und beim Auftreten eines „Koinzidenz“-Ereignisses – das ist, wenn der Wert des Zählregisters TCNT0 gleich wird Wert des Vergleichsregisters OCR0. Die Flags, die diese Interrupts aktivieren, befinden sich im TIMSK-Register. Nun zum Programm. Es ist nicht mehr möglich, das Programm Zeile für Zeile zu schreiben, deshalb gebe ich gleich den Text an. Im Folgenden werden wir alle Zeilen einzeln analysieren und alles wird klar. Auf Makros habe ich bewusst verzichtet, das Programm ist klein und ich möchte es nicht überladen. int hauptsächlich( Leere
) //Timer T0 einrichten //Interrupts aktivieren //Hauptprogrammschleife – Abfrage der Schaltfläche //Interrupt-Handler für Timer T0 Porteinstellungen In unserer Schaltung sind ein Taster und ein Piezo-Lautsprecher an Port D angeschlossen. Der Pin, an dem der Taster angeschlossen ist, muss als Eingang konfiguriert und der Pull-up-Widerstand eingeschaltet sein. Der Pin, an dem der Piezo-Lautsprecher angeschlossen ist, muss auf Ausgang eingestellt sein. DDRD = (0< Einstellen des Timers Der Betriebsmodus des T0-Timers ist CTC (Zurücksetzen bei Koinzidenz), das Taktsignal ist clk/8. Wir spiegeln dies im TCCR0-Register wider TCCR0 = (1< Für alle Fälle setzen wir das Zählregister TCNT0 zurück Schreiben Sie 0xc8 in das Vergleichsregister OCR0. Warum? Weil ich damit gerechnet habe Taschenrechner. Nun, auf dem Papier sieht diese Berechnung so aus. Eine detaillierte Beschreibung des T0-Timers finden Sie in der Dokumentation zum ATMega8535. Wir haben den Timer konfiguriert und ermöglichen mit der eingebauten Funktion einen allgemeinen Interrupt. __enable_interrupt();
Schaltfläche „Umfrage“. Wenn die Taste nicht gedrückt wird, wird der Ausgang des Mikrocontrollers über einen internen Pull-up-Widerstand mit Strom verbunden, d ist eine Null am Ausgang. Um festzustellen, ob eine Taste gedrückt wurde, müssen Sie den Inhalt des PIND-Registers lesen und den Wert des Nullbits überprüfen (eine Taste ist mit PD0 verbunden). Wir werden den Button in einer Endlosschleife abfragen. während
(1) Vergessen Sie nicht == ist kein Zuweisungsoperator =. Handhabung des Drückens/Loslassens der Taste Durch Drücken der Taste aktivieren wir die Unterbrechung des Timers T0 und durch Loslassen deaktivieren wir ihn. Dazu manipulieren wir das OCIE0-Bit des TIMSK-Registers TIMSK = (1< TIMSK = 0; //Unterbrechung deaktivieren Da wir nur einen Timer verwenden, ist es nicht erforderlich, einzelne Bits zu setzen oder zurückzusetzen. Die Interrupt-Funktion wird mit der Direktive #pragma vector= und einem Funktionswort angegeben __unterbrechen. Die Funktion muss vom Typ void sein und darf keine Parameter annehmen. #pragma-Vektor = Adresse Name– Funktionsname, wählen Sie nach unserem Ermessen Für unsere Aufgabe sieht die Interrupt-Handler-Funktion so aus #pragma vector = TIMER0_COMP_vect Nun, das ist alles. Ich hoffe, dass alles klar ist. Interrupt – ein Ereignis, das eine sofortige Reaktion des Prozessors erfordert. Die Reaktion besteht darin, dass der Prozessor die Verarbeitung des aktuellen Programms unterbricht ( unterbrochenes Programm) und fährt mit der Ausführung eines anderen Programms fort ( Programm unterbrechen), speziell für diese Veranstaltung konzipiert. Nach Abschluss dieses Programms kehrt der Prozessor zur Ausführung des unterbrochenen Programms zurück. Jedes Ereignis, das eine Unterbrechung erfordert, wird begleitet von Unterbrechungssignal, benachrichtigte den Computer darüber und rief an Unterbrechungsanforderung. Programmstatus stellt eine Menge von Zuständen aller Speicherelemente zum entsprechenden Zeitpunkt dar (z. B. nachdem der letzte Befehl ausgeführt wurde). Wenn ein Interrupt auftritt, speichert der Mikrocontroller den Inhalt des Programmzählers auf dem Stapel und lädt die Adresse des entsprechenden Interrupt-Vektors hinein. Der letzte Befehl der Interrupt-Serviceroutine muss ein Befehl sein, der zum Hauptprogramm zurückkehrt und den zuvor gespeicherten Programmzähler wiederherstellt. Während der Interrupt-Handler ausgeführt wird, können sich einige Informationen ändern. Daher ist es beim Wechsel zum Interrupt-Handler erforderlich, die geänderten Elemente zu speichern. Die Menge solcher Elemente ist Programmzustandsvektor. In diesem Fall sind andere Informationen über den Zustand der Speicherzellen nicht von Bedeutung oder können programmgesteuert wiederhergestellt werden. Anfangszustandsvektor enthält alle notwendigen Informationen für den ersten Start des Programms. In vielen Fällen enthält der Anfangszustandsvektor nur ein Element – die Startadresse des zu startenden Programms. Unterbrechungsvektor ist der Vektor des Anfangszustands des unterbrechenden Programms (Handler) und enthält alle notwendigen Informationen zum Wechseln zum Handler, einschließlich seiner Startadresse. Jeder Interrupt-Typ verfügt über einen eigenen Interrupt-Vektor, der die Ausführung des entsprechenden Handlers initiiert. Typischerweise werden Interrupt-Vektoren an speziell zugewiesenen festen Speicherplätzen mit kurzen Adressen gespeichert, die darstellen Interrupt-Vektortabelle. Um zum entsprechenden Interrupt-Programm zu springen, muss der Prozessor über einen Interrupt-Vektor und die Adresse dieses Vektors verfügen. An dieser Adresse steht in der Regel ein unbedingter Sprungbefehl zum Interrupt-Handling-Unterprogramm. Die Steuerung des Speicherns und Zurückgebens wird in der Regel dem Interrupt-Handler übertragen. In diesem Fall besteht der Handler aus drei Teilen – dem vorbereitenden (Prolog) und dem abschließenden (Epilog), die den Programmwechsel sicherstellen, und dem eigentlichen Unterbrechungsprogramm, das die von der Anfrage angeforderten Operationen ausführt. Die Reaktionszeit ist definiert als das Zeitintervall vom Eingang einer Interrupt-Anforderung bis zum Beginn der Ausführung des unterbrechenden Programms. Bei mehreren Anfragequellen muss eine bestimmte Reihenfolge zur Bearbeitung eingehender Anfragen festgelegt, genannt, werden vorrangige Beziehungen oder Servicedisziplin. Die Menge aller möglichen Prozessor-Interrupt-Typen ist Interrupt-System Mikrocontroller. Die Servicedisziplin legt fest, welche von mehreren gleichzeitig eingehenden Anfragen zuerst bearbeitet wird und ob dieser oder jener Interrupt-Handler das Recht hat, diese Anfrage zu unterbrechen. Wenn die Unterbrechungsanforderung nicht bearbeitet wird, wenn eine neue Anforderung von derselben Quelle (gleicher Priorität) eintrifft, dann Unterbrechen Sie die Systemsättigung. In diesem Fall gehen einige Interrupt-Anfragen verloren, was für den normalen Betrieb des Mikrocontrollers nicht akzeptabel ist. Eigenschaften des Interrupt-Systems Sind: Maskierung unterbrechen Wird verwendet, um den Mikrocontroller anzuweisen, auf jede Art von Interrupt zu reagieren oder ihn zu ignorieren. Die Interrupt-Maske stellt einen Binärcode dar, dessen Bits den Quellen der Interrupt-Anfrage zugeordnet sind. Das eine Bit im Binärcode weist den Mikrocontroller an, diese Art von Interrupt zu verarbeiten. Ein Nullbit hingegen erlaubt dem Mikrocontroller nicht, mit der Verarbeitung von Interrupts des angegebenen Typs fortzufahren. |
Lesen: |
---|
Beliebt:
Neu
- Unterbrechungen in atmega8. Trainingskurs. Das Konzept der Unterbrechung. Wir geben dem Mikrocontroller eine Stimme. Das Funktionsprinzip externer Interrupts im AVR
- Interessante Fakten und nützliche Tipps Laserpointer-Datenübertragungsdiagramm
- Kurze theoretische Informationen
- Wird die SPS ihre Position in der modernen Industrieautomation behaupten können?
- Retrovirus – was ist das?
- Blogger ist ein Beruf, der Ihnen Spaß machen wird
- Reform des Wohnungswesens und der kommunalen Dienstleistungen Fonds zur Unterstützung der Reform des Wohnungswesens und der kommunalen Dienstleistungen
- Datenübertragungsnetze in industriellen Steuerungssystemen Der Prozess der dezentralen Abfrage eines Subsystems
- Methoden zur parametrischen Identifizierung von Kontrollobjekten
- Relaisschutz elektrischer Energiesysteme