PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Alias für Timer und externe Interrupts



Mitch64
03.09.2016, 10:10
Hallo zusammen,

ich habe mal eine Frage zum Alias in Bascom.
Alias ist doch ein ErsatzBezeichnung?

In der Bascom-Hilfe steht etwa, dass man damit Pins/Ports einen Namen verpassen kann. Ist auch logisch und funktioniert.
Beispiel: LED Alias PortB.1

Damit kann ich LED (also den Alias) anstelle der Port-Bezeichnung verwenden. Alles gut.

Nun hatte ich das Problem bei einer Lib schreiben, die einen externen Interrupt verwenden soll, dass ich nicht vorhersehen kann, welchen externen Interrupt (INT0/INT1) der Benutzer letztendlich verwendet.

Kurzum wollte ich für den externen Interrupt einen Alias verwenden. Gleiches gilt auch für einen 8-Bit Timer, den ich in der Lib verwende.
Auch hier weiß ich nicht, ob der Timer vom Anwender nicht bereits verwendet wird und man auf den Anderen Timer ausweichen muss.

Also dachte ich, ich verwende einfach einen Alias für den externen Interrupt (MyInterrupt) und auch einen Alias für den Timer (MyTimer).
Der Alias funktioniert leider nur beim Timer, nicht aber beim Interrupt.

Ich habe hier ein kleines Demo geschrieben für BascomAVR (2.0.7.8), welches genau den Sachverhalt demonstriert.


' Demo,
' Alias für Timer und externe Interrupts verwenden

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 32

MyInterrupt Alias INT0 ' Alias für ext. Interrupt setzen (INT0|INT1)
MyTimer Alias Timer0 ' Alias für 8-Bit Timer (TIMER0|TIMER2)

' Alias mit Timer geht offensichtlich
Config MyTimer = Timer , Prescale = 8 ' geht!

' Alias mit Interrupt geht nur teilweise
Config MyInterrupt = Rising ' geht!
On MyInterrupt ISR_INTn ' geht wohl nicht
Enable MyInterrupt ' geht wohl auch nicht

Enable Interrupts ' Global Interrupts zulassen

Do
' nichts zu tun
Loop

ISR_INTn:
' Interrupt-Routine
Return



Könnt ihr mir sagen, warum das nicht geht?
Oder muss ich das anders machen?
Der Compiler meckert jedenfalls.

Danke für eure Tips.

Micha

Sauerbruch
04.09.2016, 12:31
Moin Micha,

das ist ja wirklich erstaunlich. Erst dachte ich es läge daran, dass der Befehl Alias sich immer nur auf Variablen beziehen kann (so steht´s in der Bascom-Hilfe jedenfalls geschrieben). "Timer0" könnte Bascom ja noch als eine Variable im weiteren Sinne auffassen, nämlich als das Register TCNT0. Interessanterweise setzt Bascom unter Verwendung des Timer-Alias aber auch das Timer-Control-Register (TCCR0) korrekt, nämlich auf &b00000011, was einem Prescaler von 8 entspricht.

Kurzum - ich kann Dir nicht sagen, weshalb das mit dem Alias beim Timer0 so gut funktioniert, aber beim INT0 nicht.

Aber vielleicht mal ´ne kurze Gegenfrage: Was wäre denn mit dem Alias gewonnen? Irgendwann müsstest Du doch auch für diesen Workaround wissen, welcher Interrupt denn nun Myinterrupt sein soll. Und wenn Du das weißt, kannst Du doch gleich den Interrupt direkt konfigurieren - das muss ja nur ein einziges mal vor der Do-Loop-Schleife passieren!

Gruß,

Daniel

Mitch64
04.09.2016, 14:18
Hallo Sauerbruch,
eigentlich ist die Frage schon oben erklärt.
Aber gut ich versuchs mal genauer zu erklären.

Nehmen wir an, ich habe vor Urzeiten schon einmal eine Library für Bascom geschrieben, die Ebenfalls INT0 verwendet.
Und nun nehme ich diese von oben für ein Projekt hinzu, dann wollen beide INT0 und das geht nicht.

Daher wollte ich meine Lib flexibler halten und dem Programmierer überlassen, welchen Interrupt er nehmen möchte.

Ähnliches gibt es auch bereits bei den Bascom-Befehlen:
CONFIG RC5 = pin [,TIMER=2] [,WAIT=value] [,MODE=BACKGROUND]


Hier läßt sich beispielsweise per Configuration der Timer auswählen.
Ich finde auch, dass das Sinn macht. Schließlich haben die Timer meist Differenzen in den Eigenschaften.
Output Compare Match als Beispiel bei Atmega 8 sind Different.

Konnte ich deine Frage beantworten?

Micha.

peterfido
04.09.2016, 14:21
Hallo,

"on MyTimer" geht auch nicht.

Am besten #IF und #ENDIF nutzen.

Mitch64
04.09.2016, 14:28
Vielleicht ist das der einzigste Weg mit Compiler-Direktiven,

nur umständlich, wenn dann jemand eine MCU nimmt, die dann auch noch INT2, INT3 etc unterstützt.
Das lässt sich kaum alles abfangen.

Gits noch eine Möglichkeit?

Micha.

peterfido
04.09.2016, 14:31
Hallo,

evtl. mal den Programmierer (oder in seinem Forum) fragen.

' Demo,
' Alias für Timer und externe Interrupts verwenden

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 32

const MyTimer=0
const MyIRQ=0


' Alias mit Timer geht offensichtlich
#if MyTimer=0
Config Timer0 = Timer , Prescale = 8
on Timer0 ISR_MYTimer
#endif

#if MyTimer=1
Config Timer1 = Timer , Prescale = 8
on Timer1 ISR_MYTimer
#endif

#if MyIRQ=0
Config INT0 = Rising
on INT0 ISR_INTn
enable int0
#endif

#if MyIRQ=1
Config INT0 = Rising
on INT0 ISR_INTn
enable int1
#endif


Enable Interrupts ' Global Interrupts zulassen

Do
' nichts zu tun
Loop

ISR_INTn:
' Interrupt-Routine
Return

ISR_MYTimer:

return

Mitch64
04.09.2016, 14:38
ich seh schon, offensichtlich gibt es keine andere Möglichkeit.
Danke für die Code-Ausführung, aber die Umsetzung war mir soweit schon klar.

Habe übrigens noch einen Bascom-Befehl gefunden, der Interrupt-Nr. annimt.

Schau mal bei
CONFIG HITAG = prescale, TYPE=tp, DOUT = dout, DIN=din , CLOCK=clock, INT=int

CONFIG HITAG = prescale, TYPE=tp, DEMOD= demod, INT=@int

Wie funktioniert das intern?