Für Andy und alle anderen die's interessiert, sorry dass es doch so lange gedauert hatte (ich hatte letzte Woche kaum Zeit), aber jetzt habe ich einen kleinen Beispielcode geschrieben, wie man bei einem ATMEL AVR Mega8 den AD-Wandler anspricht und in einer Interruptroutine alle sechs Eingänge des Wandlers durchscannt
Wie üblich konfiguriere und verwende ich in diesem Beispiel die entsprechenden Register des Chips selbst und verwende nicht die AD-Wandler-Befehle von BASCOM (dies bietet mehr Optionen und ist sicherer, wenn man sich mit der Architektur eines AVR entsprechend auskennt
Alle weiteren Erklärungen sind im Code selbst.
Gruss
Neni
Code: Alles auswählen
' Beispiel einer suzzesiven AD-Wandlung aller sechs Kanäle eines mega8, mega48,
' mega88 oder mega168 mittels Interruptroutine (asynchron und unabhängig vom
' Hauptprogramm). Die Interruptroutine wird immer dann wieder aufgerufen, wenn
' der AD-Wandler eine Wandlung durchgeführt hat.
' Interner RC-Oszillator bei 8MHz kann verwendet werden.
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 64
$swstack = 64
$framesize = 64
' Benötigte Vaiablen definieren
Dim Channel As Byte , Werte(6) As Byte , Index As Byte
' Port B Initialisierung
' Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
' State7 = P State6 = P State5 = P State4 = P State3 = P State2 = P State1 = P State0 = P
Portb = &HFF
Ddrb = &H00
' Port C Initialisierung
' Analogeingangspins auf In und hochohmigen Zustand, also Pullups ausschalten
' Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
' State6=P State5=T State4=T State3=T State2=T State1=T State0=T
Portc = &H40
Ddrc = &H00
' Port D Initialisierung
' Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
' State7 = P State6 = P State5 = P State4 = P State3 = P State2 = P State1 = P State0 = P
Portd = &HFF
Ddrd = &H00
' ADC Initialisierung
' ADC Clock Frequenz: 62.500 kHz -> ca. 208µs pro Wandlung pro Kanal
' ADC Referenzspannung: AREF pin (ADMUX) -> Am AREF Pin kann man die Spannung vorgeben, welche dem max. Wandlungswert entsprechen soll
' Werte linksbündig: so muss man für 8 Bit Auflösung nur ADCH lesen
' Einzelwandlung einstellen (keine Dauerwandlung)
' ADC Interrupt erlauben
' Kanal 0 wählen (ADMUX)
Admux = &H20
Adcsra = &H8F
On Adc Adc_isr Nosave 'interrupt service routine mit Nosave definieren (nicht automatisch alle Register auf dem Stack sichern)
Channel = 0 'Kanal am Anfang auf 0 setzen
sei 'Global: Interrupts erlauben (Assembler-Befehl)
Adcsra = Adcsra Or &H40 'ADC Wandlung starten ohne andere Einstellungen zu verändern
Do
' Ca. 800 mal in der Sekunde werden nun die Variablen Werte(1) bis Werte(6) mit neuen Wandlungswerten (0 - 255)
' der entsprechenden Analogeingänge upgedatet. Das sollte auch für eine gute Pegelanzeige reichen.
' In dieser Do ... Loop Schleife (Hauptprogramm) kann man nun diese Werte mit If Then oder Select Case etc.
' abfragen und aufgrund der Vergleiche bestimmte Aktionen (ev. Unterprogramme) ausführen.
' Man kann aber auch einen Wert direkt in LED-Zeilen-Information (praktisch als Wert-Anzeige) etc. umwandeln.
' Falls Aktionsunterprogramme aufgerufen werden, welche eine bestimmte Zeit dauern und man während dieser
' Zeit sowieso keine Werte abfragt, sollte man am Anfang des Unterprogramms mit CLI alle Interrupts blockieren,
' damit die Interruptroutine nicht unnötigerweise ausgeführt wird. Vor dem Ende des Unterprogrammes muss
' man dann mit SEI wieder die Interrupts erlauben.
Loop
' Hier folgt nun die Interrupt-Routine, welche suzzessive die Wandlungsergebnisse der Kanäle 0 bis 5 in die Variablen Werte(1) bis Werte(6) schreibt
Adc_isr:
' zunächst werden ein paar wenige Register (wir verändern in der Routine kaum welche) mittels Assembler-Befehlen auf dem Stack gespeichert
push r26
push r27
push r24
in r24,sreg
push r24
push r25
Index = Channel + 1 'index ist Kanal + 1, da die Array-Indizes in BASCOM bei 1 anfangen
Werte(index) = Adch 'Wandlungswert in die entsprechende Werte-Variable (mit dem korrekten Index) schreiben
Incr Channel 'Kanal um 1 erhöhen
If Channel > 5 Then Channel = 0 'nach Kanal 5 wieder bei Kanal 0 beginnen
Admux = &H20 Or Channel 'ADMUX auf neuen Kanal setzen ohne andere Einstellungen zu verändern
Waitus 10 '10 µs warten bis Spannungswert am Eingang nach Umschaltung valid
Adcsra = Adcsra Or &H40 'neue ADC Wandlung starten
' vor der Rückkehr aus der Routine die gespeicherten Register wieder rücksetzen
pop r25
pop r24
!out sreg,r24 'out ist auch ein BASCOM-Befehl, deshalb das Ausrufezeichen (weist Compiler an, dass Assembler-Befehl folgt) vor out
pop r24
pop r27
pop r26
Return




