Jede Interruptquelle besitzt eine bestimmte Adresse im Programmspeicher, die automatisch angesprungen wird, wenn der Interrupt lokal und global freigegeben war, zugeschlagen hat, und aufgrund seiner Priorität jetzt dran ist (also vereinfacht gesagt: abgearbeitet werden soll). Diese Adressen sind in der mit der $regfile-Direktive festgelegten Controller-Definitionsdatei (oder eben der Default-Einstellung bei den Options) hinterlegt, und insbesondere mit Namen für die Konstanten Adressen versehen.
Dieser Adressbereich, in der sich die ganzen Interrupt-Einsprungadressen wird als Interrupt Vektor Table bezeichnet. Da dort immer nur eine Instruktion reinpaßt, wird üblicherweise von dort in die eigentlichen Teilprogramme gesprungen, die den Interrupt behandeln sollen. Diese einzelnen Teilprogramme werden dann entsprechend als Interrupt Service Routine bezeichnet.
Der erste Parameter (in Deiner Frage
Der zweite Parameter (in Deiner Frage
Bei Bascom gibts dazu (inzwischen) zwei Möglichkeiten:
Entweder - wie hier bisher - ein Label (Die Zeilen mit dem Doppelpunkt am Ende) als Sprungziel, und ein Return am Ende der ISR.
Oder eine echte deklarierte Sobroutine, die durch Sub und End Sub eingeschlossen wird....
Den Namen dieses Teilprogrammes/Subroutine kannst Du beliebig wählen/festlegen. Aufruf und Ziel müssen natürlich übereinstimmen. Thomas verwendet klingende Namen, um gleich beim lesen des Codes zu sehen, worums geht.
So, der ADC ist - wie auch der UART oder die Timer - ein mehr oder weniger eigenständiges periphäres Hardware Modul im Controller. Wie bei alle periphären Modulen hat Dein Programm darauf nur über bestimmte I/O-Register zugriff.
Mit
(Nebenbemerkung: eine Hochsprache ist eben eine Ebene höher abstrahiert, kapselt Dich von tieferen Innereien ab. Manche Hochsprachen sind da strenger - bei Bascom darfst Du hingegen trotzdem die tieferen Innereien manipulieren. Insbesondere dann vorteilhaft, wenn der Hochsprachen-Befehl irgendeine exotische Möglichkeit eines Controllers eben nicht berücksichtigt).
In der Configurationszeile hatten wir bisher also den Vorteiler des ADC automatisch festlegen lassen (Bascom stellt den auf möglichst schnell aber maximal 200kHz ein), und die Referenz auf interne AVcc eingestellt, und daß der ADC immer nur 'ne Einzelmessung vornehmen soll. Dadurch wird der ADC selbst gestartet (enabled, der Takt liegt an, und die Referenz wird entsprechend aufgeschaltet, 'ne ggf gewählte interne Spannungsreferenz wird auch gestartet).
Das folgende
Der ADC ist "bereit".
Es wird also nach dem Start der eigentlichen Messung gewartet, bis der ADC ein Ergebnis hat.
Der ADC kann aber auch einen Interrupt auslösen, wenn er fertig ist.
Bleiben wir trotzdem erstmal im Einzel-Schuß-Modus.
Nach
Die eigentliche Messung wird dann durch setzen des ADSC-Bits (ADC Start Conversion) im ADCSRA-Register (ADC Control an Status Register) ausgelöst. (sollte beim Mega8 sogar mit
Neben dem Einzelschuß-Modus kann der ADC auch auf Dauerfeuer geschaltet werden. Nach einer Messung legt er das Ergebnis (wie immer) in seinem Ergebnis-Register ab, und startet sofort'ne neue Messung. Aus dem Ergebnis-Register ist also immer das aktuellste ergebnis ablesbar. Wenn immer nur derselbe Kanal gemessen werden soll, kann man dadurch auf Interrupts oder warten ganz verzichten, sondern schaut nur bei Bedarf ins Ergebnis-Register.
Auch im Dauerfeuer-Modus kann(!) natürlich der Interrupt bei fertig verwendet werden, zB um den Kanal für die nächste Messung zu wechseln und so...
Bei vielen aktuelleren Controllern gibt es außerdem noch einen "spezielleren" Einzelschuß-Modus, wo andere periphäre Hardware-Module auf den Auslöser drücken dürfen - die Timer, der Analog-Comperator, ein externer IRQ usw...
(im Prinzip eine Vorstufe des flexiblen Event-Systems der neuen X-Core-Controller).
Um mich mit dem Problem aus #416 zu beschäftigen fehlt mir gerade die Zeit...
Dieser Adressbereich, in der sich die ganzen Interrupt-Einsprungadressen wird als Interrupt Vektor Table bezeichnet. Da dort immer nur eine Instruktion reinpaßt, wird üblicherweise von dort in die eigentlichen Teilprogramme gesprungen, die den Interrupt behandeln sollen. Diese einzelnen Teilprogramme werden dann entsprechend als Interrupt Service Routine bezeichnet.
On blablabla
ist jetzt die Bascom Anweisung, die für einen bestimmten Interrupt das Sprungziel (also die Adresse der ISR) in der IVT einträgt.Der erste Parameter (in Deiner Frage
URXC
) muß also ein, im Regfile definierter Interrupt sein - also auch genau so geschrieben werden.Der zweite Parameter (in Deiner Frage
OnUartRx
) muß eine, irgendwo im Code folgende Subroutine sein.Bei Bascom gibts dazu (inzwischen) zwei Möglichkeiten:
Entweder - wie hier bisher - ein Label (Die Zeilen mit dem Doppelpunkt am Ende) als Sprungziel, und ein Return am Ende der ISR.
Oder eine echte deklarierte Sobroutine, die durch Sub und End Sub eingeschlossen wird....
Den Namen dieses Teilprogrammes/Subroutine kannst Du beliebig wählen/festlegen. Aufruf und Ziel müssen natürlich übereinstimmen. Thomas verwendet klingende Namen, um gleich beim lesen des Codes zu sehen, worums geht.
So, der ADC ist - wie auch der UART oder die Timer - ein mehr oder weniger eigenständiges periphäres Hardware Modul im Controller. Wie bei alle periphären Modulen hat Dein Programm darauf nur über bestimmte I/O-Register zugriff.
Mit
Config ADC ....
legst Du also fest, was Bascom für Dich in die Register des ADC-Moduls schreiben soll. Prinzipiell könntest Du aber auch selbst die Register beschreiben.(Nebenbemerkung: eine Hochsprache ist eben eine Ebene höher abstrahiert, kapselt Dich von tieferen Innereien ab. Manche Hochsprachen sind da strenger - bei Bascom darfst Du hingegen trotzdem die tieferen Innereien manipulieren. Insbesondere dann vorteilhaft, wenn der Hochsprachen-Befehl irgendeine exotische Möglichkeit eines Controllers eben nicht berücksichtigt).
In der Configurationszeile hatten wir bisher also den Vorteiler des ADC automatisch festlegen lassen (Bascom stellt den auf möglichst schnell aber maximal 200kHz ein), und die Referenz auf interne AVcc eingestellt, und daß der ADC immer nur 'ne Einzelmessung vornehmen soll. Dadurch wird der ADC selbst gestartet (enabled, der Takt liegt an, und die Referenz wird entsprechend aufgeschaltet, 'ne ggf gewählte interne Spannungsreferenz wird auch gestartet).
Das folgende
Start ADC
sollte somit unnötig sein.Der ADC ist "bereit".
Zielvariable=Getadc(Kanal)
schaltet jetzt erstmal den gewählten Kanal auf den ADC (ADC-Multiplexer), löst dann eine Conversion aus, wartet bis die Messung fertig ist (25 Takte des vorgeteilten Taktes), liest des Ergebnis-I/O-Register aus, und weist dieses Ergebnis der Zielvariable zu.Es wird also nach dem Start der eigentlichen Messung gewartet, bis der ADC ein Ergebnis hat.
Der ADC kann aber auch einen Interrupt auslösen, wenn er fertig ist.
Bleiben wir trotzdem erstmal im Einzel-Schuß-Modus.
Nach
Config ADC = ...
ist der ADC also bereit. Getadc könne wir nicht verwenden - das würde ja warten. Wir müssen also noch selbst den zu messenden Kanal auf den Multiplexer schalten (ADMUX). Wenn sich der Kanal nicht ändern soll, muß das natürlich nur einmal gemacht werden.Die eigentliche Messung wird dann durch setzen des ADSC-Bits (ADC Start Conversion) im ADCSRA-Register (ADC Control an Status Register) ausgelöst. (sollte beim Mega8 sogar mit
SBI ADCSRA, ADSC
gehen). Wenn die Messung fertig ist, soll nun ein Interrupt erfolgen, der das Ergebnis ausliest und zuweist.Neben dem Einzelschuß-Modus kann der ADC auch auf Dauerfeuer geschaltet werden. Nach einer Messung legt er das Ergebnis (wie immer) in seinem Ergebnis-Register ab, und startet sofort'ne neue Messung. Aus dem Ergebnis-Register ist also immer das aktuellste ergebnis ablesbar. Wenn immer nur derselbe Kanal gemessen werden soll, kann man dadurch auf Interrupts oder warten ganz verzichten, sondern schaut nur bei Bedarf ins Ergebnis-Register.
Auch im Dauerfeuer-Modus kann(!) natürlich der Interrupt bei fertig verwendet werden, zB um den Kanal für die nächste Messung zu wechseln und so...
Bei vielen aktuelleren Controllern gibt es außerdem noch einen "spezielleren" Einzelschuß-Modus, wo andere periphäre Hardware-Module auf den Auslöser drücken dürfen - die Timer, der Analog-Comperator, ein externer IRQ usw...
(im Prinzip eine Vorstufe des flexiblen Event-Systems der neuen X-Core-Controller).
Um mich mit dem Problem aus #416 zu beschäftigen fehlt mir gerade die Zeit...