Hallo zusammen,
ich komm nicht mehr weiter bei der ADC Schnittstelle.
Ich bin gerade dabei mich in die ADC Schnittstelle des ATmega32
einzuarbeiten. Leider sind da einige Fragen noch offen.
Ich kapier einfach nicht wie das vorgehen ist bei der sog. Single
Conversation und dem Free Running Mode bzw. der Interrupthandhabung.
Single Conversation starten kommt Messwert -> Interrupt wird ausgelöst
O.K soweit verstanden aber bei Free Running Mode wird dauernd gelesen
was heißt das wird da immer ein Interrupt ausgelöst.
D.h Prozzessor wär nur mit ADC beschäftigt wenn z.B ein Analog Wert
anliegt.?? Bei Free Running ist da ADSC Bit dann dauern auf 1 ? Oder
wird zwischendrin wie bei Single Conversation nach Umwandlung des
Empfangswertes dieses Bit (ADSC) auf 0 gesetzt?
Wer kann mir in dieser Problematik weiterhelfen, lese schon dauern die
Spec werd aber in diesen und vielen anderen Punkten nicht schlau...
Vielen Dank im Voraus
Peter
Weiß jemand einen Source Code in Assembler indem man die grundlegende
Handhabung des ADC (evtl mit single und free Running mode , Interrupt)
nachvollziehen kann . Oder in irgend einem Tutorial ?
Vielen Dank
Wenn du mal guckst, was die maximale Samplezahl pro Sekunde ist
(15kSps), wirst du feststellen, dass dir genug Zeit bleibt, um zwischen
den einzelnen Interrupts selbst bei 1MHz noch komplexere Aufgaben zu
erledigen. (Bei voller A/DC Frequenz bei 8MHz bleiben etwa 500
Taktzyklen, um den AD-Wert zu verarbeitn und anderes zu machen. Aber
ich denke mal, dass du den A/D-Wandler nicht mit voller Frequenz
betreiben mußt, oder?)
Wie das mit dem Bit ist, weiß ich nicht, aber das steht alles im
Datenblatt. (Ich weiß: "...lese schon dauern die
Spec werd aber in diesen und vielen anderen Punkten nicht schlau...".
Trotzdem, lesen bildet!)
Hallo,
ich habe bisher nur am Mega8 mit dem ADC gearbeitet, denke aber, dass
es prinzipiell gleich ist.
Während beim Single-Conversion das ADSC wieder auf Null gesetzt wird,
bleibt es im Free-Running mode auf Eins, d.h. es wird nur einmal am
Beginn vom Programm gesetzt.
Wenn der Interrupt aktiviert ist, dann wird er immer am Ende einer
Wandlung ausgelöst, sei es jetzt Single-Conv. oder Free-Running. Der µC
wird also in diesem Sinne nur beschäftigt, wenn ein Wert fertig ist. Es
ist allerdings zu beachten, dass im Free-Running auch weiter gewandelt
wird, wenn das Interrupt-Flag nicht gelöscht wird. Wenn also dein
Programm nicht jeden Interrupt vom ADC auswertet (oder auswerten kann)
dann würden Werte verloren gehen.
Viele Grüße
Hallo Peter,
Source Code kann ich dir heute abend suchen - aber wahrscheinlich hat
bis dahin schon jemand anderes welchen geschickt ;-)
Ansonsten würde ich empfehlen nochmal bei www.avrfreaks.net
nachschauen, da gibt's einen Haufen Tutorials.
Viele Grüße
Hallo Peter,
und nochmal ;-)
Ganz vergessen hatte ich die App. Notes direkt von www.atmel.com
Dort werden viele Einzelproblematiken gut beschrieben. Kann sein, dass
da was über ADC bei ist.
Viele Grüße
Danke Thomas für Deine Hilfe,
leider bin ich noch kein bisschen vorangekommen.
Kann jemand mal über den Sourcecode schauen was faul ist ?
ich will an ADC0 eine Spannung anlegen die dann gewandelt am Port A
(Low Byte) auch ausgegeben werden soll (Ich weiß 1 Bit fehlt wegen des
Eingangspins)
Leider tut sich nichts an den LEDs ; Bei Single Step springt Programm
immer auf TIM0_OVERFLOW dann auf ADR 0 -> Srung auf main ????
Vielen Dank
Peter
rjmp main ; Reset Handler
reti ; EXT_INT0 ; IRQ0 Handler
reti ;EXT_INT1 ; IRQ1 Handler
reti ;EXT_INT2 ; IRQ2 Handler
reti ;TIM2_COMP ; Timer2 Compare Handler
reti ;TIM2_OVF ; Timer2 Overflow Handler
reti ;TIM1_CAPT ; Timer1 Capture Handler
reti ;TIM1_COMPA ; Timer1 CompareA Handler
reti ;TIM1_COMPB ; Timer1 CompareB Handler
reti ;TIM1_OVF ; Timer1 Overflow Handler
reti ;TIM0_COMP ; Timer0 Compare Handler
reti ;TIM0_OVF ; Timer0 Overflow Handler
reti ;SPI_STC ; SPI Transfer Complete Handler
reti ;USART_RXC ; USART RX Complete Handler
reti ;USART_UDRE ; UDR Empty Handler
reti ;USART_TXC ; USART TX Complete Handler
rjmp ADC ; ADC Conversion Complete Handler
reti ;EE_RDY ; EEPROM Ready Handler
reti ;ANA_COMP ; Analog Comparator Handler
reti ;TWI ; Two-wire Serial Interface Handler
reti ;SPM_RDY ; Store Program Memory Ready Handler
main:
;Initialisierung des Stack Pointers ->notwendig bei Interrupt
Sprüngen
ldi stack,LOW(RAMEND);Initiate Stackpointer
out SPL,stack ; wegen Interrupts und Unterprogr.
ldi stack,HIGH(RAMEND)
out SPH,stack
;Stackpointerinitialisierung ende
ldi ll,0x00
out ADMUX,ll
ldi ll,0xFB
out ADCSR,ll ;Reg ADCSRA beschrieben
ldi port_direction, 0xfe
out DDRA, port_direction ;PortB auf Ausgang schalten
sei ;Set Global Interrupt Enable this means bit7 in Status Register
is set to 1.
loop: ;ldi kk,0xDB
;out ADCSR,kk ;Reg ADCSRA beschrieben-> Neue Konversation
eingeleitet
rjmp loop
ADC:
in mp,ADCL
in tr,ADCH
out PORTA,mp
;out PORTA,tr
reti
Hi,
warum setzt du das ADIF Bit?
Im Anhang is nen kleines ADC Programm, momentan als Free runnning, der
Programmteil für Single Conversion ist auch dabei
Bis denn
Hallo Christoph,
danke für dein Programm, aber auch mit deinem Programm rührt sich
nichts, was kann ich noch alles probieren. Kann es daran liegen das ich
Eingang und Ausgang den Port A benutze? Aber ich schalte doch um, bzw.
hab einen Pin als Eingang definiert.
Dein Programm indem ich in der ISR den PortA setze...
Übrigens das Interrupt Flag hab ich nur aus sicherheitsgründen
gelöscht, damit ich weiß daß auf jeden Fall kein Interrupthandling
während dieses Abschnittes vorkommt.
Danke
Peter
rjmp main ; Reset Handler
reti ; EXT_INT0 ; IRQ0 Handler
reti ;EXT_INT1 ; IRQ1 Handler
reti ;EXT_INT2 ; IRQ2 Handler
reti ;TIM2_COMP ; Timer2 Compare Handler
reti ;TIM2_OVF ; Timer2 Overflow Handler
reti ;TIM1_CAPT ; Timer1 Capture Handler
reti ;TIM1_COMPA ; Timer1 CompareA Handler
reti ;TIM1_COMPB ; Timer1 CompareB Handler
reti ;TIM1_OVF ; Timer1 Overflow Handler
reti ;TIM0_COMP ; Timer0 Compare Handler
reti ;TIM0_OVF ; Timer0 Overflow Handler
reti ;SPI_STC ; SPI Transfer Complete Handler
reti ;USART_RXC ; USART RX Complete Handler
reti ;USART_UDRE ; UDR Empty Handler
reti ;USART_TXC ; USART TX Complete Handler
rjmp ADC ; ADC Conversion Complete Handler
reti ;EE_RDY ; EEPROM Ready Handler
reti ;ANA_COMP ; Analog Comparator Handler
reti ;TWI ; Two-wire Serial Interface Handler
reti ;SPM_RDY ; Store Program Memory Ready Handler
main:
;Initialisierung des Stack Pointers ->notwendig bei Interrupt
Sprüngen
ldi stack,LOW(RAMEND);Initiate Stackpointer
out SPL,stack ; wegen Interrupts und Unterprogr.
ldi stack,HIGH(RAMEND)
out SPH,stack
;Stackpointerinitialisierung ende
ldi ll,0xb00100000
out ADMUX,ll
ldi ll,0x0b11101101
out ADCSR,ll ;Reg ADCSRA beschrieben
ldi port_direction, 0xfe
out DDRA, port_direction ;PortB auf Ausgang schalten
sei ;Set Global Interrupt Enable this means bit7 in Status Register
is set to 1.
loop: ;ldi kk,0xDB
;out ADCSR,kk ;Reg ADCSRA beschrieben-> Neue Konversation
eingeleitet
jmp loop
ADC:
in mp,ADCL
in tr,ADCH
out PORTA,tr
;out PORTA,tr
ldi port_direction, 0xfe
out DDRA, port_direction ;PortB auf Ausgang schalten
reti
Hallo Peter,
ich hab zwar noch nicht mit dem ADC beim Mega32 gearbeitet, was mir
aber Aufgefallen ist, ist das deine IRQ-Vectoren ins leere laufen.
Beim Mega32 ist jeder Vector 4 und nicht 2 Byte(wie bei den "alten"
AVR's) gross. Sprich du müsstes 2 reti pro Vector eintragen, oder
besser mit .org-Anweisungen arbeiten.
Kleines Beispiel:
.org 0
rjmp start ; Reset Handle
.org INT0addr
rjmp Int0Interrupt
.org INT1addr
rjmp Int0Interrupt
.org OVF1addr
reti
Gruß
-=jens=-
Hallo Jens,
danke für deinen Hinweis, Du hast recht!
Ich hab noch nicht mit org gearbeitet
Ist das so richtig
Interrupt kommt->MC springt auf die entsprechende Adr. in der z.B
.org 0x0010 steht -> was heist das dann genau bzw. der darauffolgende
Befehl mit rjmp Name von ISR Label...
Kannst du mir das bitte noch erklären?
Danke Peter
Hallo Peter,
erstmal ist es am besten (übersichtlichsten) wenn du bei den .org
Anweisungen mit symbolischen Adressen arbeitest, also für deinen
ADC-Interrupt nicht: .org $20, sondern .org ADCCaddr.
Dies kennzeichnet die Adresse in der Vector-Sprungtabelle, die durch
den ADC-Interrupt Angesprungen wird. Der dort stehende Code wird direkt
ausgeführt, deshalb springt man von dort zur eigentlichen
Interruptroutine. Achtung, wenn dein Programm größer wird gibt es
Probleme mit dem rjmp Befehl, da der nur eine Sprungweite von +-2kB
schaft. In diesem Fall musst du den jmp Befehl verwenden.
Zur Addressierung der Interruptvectoren schau dir mal die m32def.inc
Datei an, dort sind ganz am Ende die Zuweisungen für die
Vectoradressen
Gruß
-=jens=-
Hallo Jens,
aber was sagt genau folgendes
-----------------------------
.org ADCCaddr
rjmp ADC_HANDLING
ADC_HANDLING:
...
------------------------------
wann wird .org ausgeführt bzw. was macht er dann, und wann wird
rjmp ausgeführt...?
bisher habe ich das nur mit den direkten Interrupteinsprungadressen
gemacht da hab ich gewußt bei Interrupt ... springt er auf Adr. z.B
0x020 in meinem Fall und dort habe ich einen rjmpt gesetzt, die anderen
Interrupteinsprungstellen habe ich mit reti belegt das ist mir klar
aber das mit org .?? Sorry hab noch nicht so viel Erfahrung
Danke Peter
Hallo Peter,
der .org ist nur ne Compileranweisung die dafür sorgt, das der Code an
eine definierte Adresse kommt. Ansonsten ist dein Vorgehen richtig.
Wie gesag der Unterschied zwischen dem Mega32 und den kleineren AVRs
ist, das die Sprungtabelle jeweils 4 Byte für jeden Vector groß ist
(damit man per jmp den gesammten Adressraum ansprechen kann).
Wenn du jetzt die Tabelle mit .org Anweisungen aufbaust liegen die
Sprungbefehle automatisch auf der richtigen Adresse, unabhängig vom
eingesetzten AVR.
Gruß
-=jens=-
AHHH, Jetzt glaub ich hab ichs,
die Anweisung
.org ADCCaddr
rjmp ADC_HANDLING
setzt den rjmp Befehl auf die Adr. $0020 richtig ?
Ich glaube schon...
Vielen Dank
Peter
PS: Weist du vielleicht ob es eine Besonderheit beim Atmega32 gibt.
Ich hab nämlich ein ganz triviales Programm geschrieben das auf PORTA
nur high pegel ausgeben soll -> es funktioniert > programmier ich aber
das ganze auf den PortC um so leuchten nur 4 der 8 LEDs (4 High Pegel)
-> Weist Du rat ??
Peter
Zu meiner letzten Fragen bzgl. Ausgabe an Port C habe ich jetzt nach
Stundenlanger Suche den Fehler gefunden -> Die JTAG Schnittstelle war
enabeld... damit war eine Anzeige nicht auf allen Ports möglich
So gehen die Stunden ins Land...
Grüße
Peter