PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Interrupt



Stefan_84
20.06.2008, 13:17
Guten Tag!
Ich arbeite gerade an einer Schaltung die Akkus bis zu einer bestimmten Spannung entladen soll. Der ATMEGA8515, überwacht dabei die Spannung und schaltet ein Relais zum Entladewiderstand ein und aus. Später soll noch ein Display dazu kommen wo man die wichtigsten Werte ablesen kann.

Mein Problem ist das sich die Schaltung nach einer unbestimmten Zeit einfach abschaltet.

Ich verwende 2 Timer, einer zum Entprellen der Ein/Aus-Taste und einmal einen Sekundenzähler der ca. 30 Sekunden warten soll sobald die min.Spannung erreicht wurde und dann nochmals entladen soll.

Hab das Programm jetzt Zeile für Zeile verfolgt und mir ist aufgefallen das wenn ein Timer-Interrup ausgelöst wird und der Rücksprung zufällig auf einen Branch-Befehl trifft, dieser Branch-Befehl ausgeführt wird, obwohl laut dem Compare-Befehl kein Branch stattfinden sollte.

Gibt es dafür irgendeine Lösung?

mfg
Stefan

Ceos
20.06.2008, 13:33
hast du eventuell vergessen irgendwelche register zu sichern ? sodass sie nach dem interrupt falsche werte tragen ? zur not kurz vor dem branch das interruptenable flag löschen und kurz danach wieder setzen ...

Besserwessi
20.06.2008, 13:57
Das hört sich an als würde der Interrupt das Stautsflag verändern. In der Interruptroutine muß man das Statusbyte sichern und am Ende wieder herstellen.

Stefan_84
20.06.2008, 15:04
Erstmal danke für die Antworten!
Das mit den Interrupts funktioniert jetzt mal grundsätzlich. Warum weiß ich leider nicht? Hab den ganzen Quellcode in ein neues Projekt kopiert und das Problem war weg.

Leider schaltet die Schaltung immer noch ab, auch wenns jetzt noch etwas länger dauert. Also genauer gesagt springt das Programm in die Funktion die aufgerufen wird man die Stop-Taste drückt. Passiert auch nicht immer zur selben Zeit. Muss aber erst genauer schauen wo jetzt noch ein Problem sein könnte. Passiert halt immer nach ca. 1.000.000 Cycles +/- 200.000. Daher ist es fast nicht möglich das solange Zeile für Zeile anzuschauen.

Ich meld mich wenn ich was weiß!!

Trotzdem danke erst mal.

Stefan

The Man
21.06.2008, 11:36
Hi da,
am besten, du postest mal deinen Code

mfg

Stefan_84
22.06.2008, 11:19
Mach ich!
Muss euch aber warnen, mir wurde schon öfter gesagt das ich einen katastrophalen Programmierstil hab.



;************************************************* ****************************
;*
;* DATEINAME: entlader.asm
;* TITEL :
;* DATUM : 16.6.08
;* AUTOR : STK
;* VERSION : 1.0
;*
;*
;************************************************* ****************************

.include "m8515def.inc"

;--KONSTANTENDEKLARATION---------------------------------------------
; status register bits
.equ CarryFlag = 0
.equ ZeroFlag = 1
.equ NegativeFlag = 2
.equ TwosFlag = 3
.equ SignFlag = 4
.equ HalfCarryFlag = 5
.equ TransferFlag = 6
.equ GlobalFlag = 7
.equ Frequenz = 4000000
.equ Teiler = 4000

;--VARIABLENDEKLARATION----------------------------------------
.def tmp = R16 ;Temp. Variable
.def tmp2 = R17
.def sek_zaehler = R18
.def spg = R19
.def entprell = R20






.CSEG
.org 0x0000

rjmp MAIN ;Reset
rjmp UnusedInt_ISR ;Ext. Int0
rjmp UnusedInt_ISR ;Ext. Int1
rjmp UnusedInt_ISR ;Timer1 Capture Event
rjmp timer ;Timer1 Compare Match A
rjmp UnusedInt_ISR ;Timer1 Compare Match B
rjmp UnusedInt_ISR ;Timer1 Overflow
rjmp UnusedInt_ISR ;Timer0 Overflow
rjmp UnusedInt_ISR ;Serial Transfer Complete
rjmp UnusedInt_ISR ;USART Rx Complete
rjmp UnusedInt_ISR ;USART Data Reg. Empty
rjmp UnusedInt_ISR ;USART Tx Complete
rjmp UnusedInt_ISR ;Analog Comperator
rjmp UnusedInt_ISR ;Ext. Int Request 2
rjmp pause ;Timer0 Compare Match
rjmp UnusedInt_ISR ;EEPRom Ready
rjmp UnusedInt_ISR ;Store Program memory ready
UnusedInt_ISR: reti


;--Hauptprogramm------------------------------------------------
MAIN:
;Stackpointer initialisieren
ldi tmp,low (RAMEND) ; RAMEND ist eine im include file vorgegebene Konstante,
out SPL,tmp
ldi tmp, high(RAMEND)
out SPH,tmp

rjmp init

Main_loop:
;Hauptprogramm
;Akku angesteckt?
in tmp2, pina
ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;Akku ist angeschloßen
cp tmp2,tmp
brsh akku_an
;Akku ist nicht angeschloßen
cp tmp2, tmp
brlo akku_ab

rjmp Main_loop;



;--Unterprogramme-----------------------------------------------------


akku_ab:
;Ausgabe auf Display
;"Akku"
;"anhängen"
rjmp main_loop

akku_an:
;Ausgabe auf Display
;SPG:x,xx
;Entl:x,x
;Warte auf Start-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq start ;Ist Bit gesetzt, Spring in die Start- Fkt.

;Warte auf Entladespg senken:

;Warte auf Entladespg erhöhen
rjmp main_loop

start:
;Akku wurde erkannt und die Starttaste gedrückt
;Start-Taste entprellen
clr entprell
wh1:
ldi tmp, 0b00000010
cp entprell, tmp
brlo wh1
clr sek_zaehler
;Entladevorgang starten
rjmp entladen_ein


entladen_ein:
;Kontrolle ob der Akku noch angeschloßen ist
;Wenn nicht ins Startmenü zurück springen

in tmp, pinc
ori tmp, 0b00000001 ;Relais aktivieren
out portc, tmp

;in tmp2, pina
;ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;cp tmp2, tmp
;brlo entladen_aus

;Akkuspg. überwachen
;Wenn zu niedrig Entladevorgang abbrechen
in tmp2, pina
ldi tmp, 0b10000000
cp tmp2, tmp
brlo entladen_aus

;Warte auf Stop-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq entladen_stop ;Ist Bit gesetzt, Spring in die Start- Fkt.

;Ausgabe auf Display
;A: x,xx
;00:00
rjmp entladen_ein


entladen_aus:
;Entladevorgang stoppen weil die Akkuspannung unter
;einem bestimmter Wert gefallen ist
in tmp, pinc
andi tmp, 0b11111110
out portc, tmp
clr sek_zaehler
rcall automatik
rjmp akku_an

automatik:
;Nach 30 Sekunden soll der Entladevorgang erneut
;gestartet werden
ldi tmp, 0b00011110
cp sek_zaehler,tmp
brsh start

;Schreibe auf Display
;Beendet
;WH in xx

;Warte auf Stop-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq akku_an

in tmp2, pina
ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;Akku ist nicht angeschloßen
cp tmp2, tmp
brlo main_loop

rjmp automatik

entladen_stop:

clr entprell
wh2:
ldi tmp, 0b00000010
cp entprell, tmp
brlo wh2


;Entladevorgang abbrechen
in tmp, pinc
ldi tmp2, 0b00000001
sub tmp, tmp2
out portc, tmp

rjmp main_loop



init:
ldi spg, 0b01010000 ;vorderen 4 Bit vor Komma, hinteren 4 Bit nach Komma

clr sek_zaehler

;Ausgänge setzen
ser tmp
out ddrc, tmp

;Eingänge setzen
clr tmp
out ddra, tmp
out ddrd, tmp


;Timer1 setzen
clr tmp
out tccr1a, tmp
ldi tmp, 0b00001001 ;nur zu Testzwecken (normal 0b00001101)
out tccr1b, tmp

ldi tmp, 0b01100001 ;Timer Einstellungen
out tIMSK, tmp


ldi tmp, HIGH(Frequenz / Teiler)
out ocr1ah, tmp

ldi tmp, LOW(Frequenz / Teiler)
out ocr1al, tmp
;Timer0 setzen
ldi tmp, 0b00000001 ;nur zu Testzwecken (normal 0b00000101)
out tccr0, tmp
ldi tmp, 0b01001110
out ocr0, tmp

sei
rjmp main_loop

;*********Interrupt***********
;Zähler für die Sekundenzählung
timer:
inc sek_zaehler
reti
;Zähler für die Entprellung
pause:
inc entprell
reti



Danke
Stefan

The Man
22.06.2008, 11:58
Hi Stefan,

wie meine Vorgänger schon sagten, du musst das Status Register retten.
Ich will dir nicht auf den Schlips treten wenn ich frage ob du weißt, was das ist?
Ich hab die entsprechenden Zeilen in den ISR´s geändert und das bei den Registerdefinitionen eingefügt : .def sreg_save = r21

Schon einfache Operationen auf Register "effecten" das Statusregister, was einen vor der ISR gemachten Vergleich verfälschen kann.
Z.B. wird das Statusbit "S" verändert, das für manche branches als Initiator dient.

mfg,
The Man




;************************************************* ****************************
;*
;* DATEINAME: entlader.asm
;* TITEL :
;* DATUM : 16.6.08
;* AUTOR : STK
;* VERSION : 1.0
;*
;*
;************************************************* ****************************

.include "m8515def.inc"

;--KONSTANTENDEKLARATION---------------------------------------------
; status register bits
.equ CarryFlag = 0
.equ ZeroFlag = 1
.equ NegativeFlag = 2
.equ TwosFlag = 3
.equ SignFlag = 4
.equ HalfCarryFlag = 5
.equ TransferFlag = 6
.equ GlobalFlag = 7
.equ Frequenz = 4000000
.equ Teiler = 4000

;--VARIABLENDEKLARATION----------------------------------------
.def tmp = R16 ;Temp. Variable
.def tmp2 = R17
.def sek_zaehler = R18
.def spg = R19
.def entprell = R20
.def sreg_save = r21






.CSEG
.org 0x0000

rjmp MAIN ;Reset
rjmp UnusedInt_ISR ;Ext. Int0
rjmp UnusedInt_ISR ;Ext. Int1
rjmp UnusedInt_ISR ;Timer1 Capture Event
rjmp timer ;Timer1 Compare Match A
rjmp UnusedInt_ISR ;Timer1 Compare Match B
rjmp UnusedInt_ISR ;Timer1 Overflow
rjmp UnusedInt_ISR ;Timer0 Overflow
rjmp UnusedInt_ISR ;Serial Transfer Complete
rjmp UnusedInt_ISR ;USART Rx Complete
rjmp UnusedInt_ISR ;USART Data Reg. Empty
rjmp UnusedInt_ISR ;USART Tx Complete
rjmp UnusedInt_ISR ;Analog Comperator
rjmp UnusedInt_ISR ;Ext. Int Request 2
rjmp pause ;Timer0 Compare Match
rjmp UnusedInt_ISR ;EEPRom Ready
rjmp UnusedInt_ISR ;Store Program memory ready
UnusedInt_ISR: reti


;--Hauptprogramm------------------------------------------------
MAIN:
;Stackpointer initialisieren
ldi tmp,low (RAMEND) ; RAMEND ist eine im include file vorgegebene Konstante,
out SPL,tmp
ldi tmp, high(RAMEND)
out SPH,tmp

rjmp init

Main_loop:
;Hauptprogramm
;Akku angesteckt?
in tmp2, pina
ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;Akku ist angeschloßen
cp tmp2,tmp
brsh akku_an
;Akku ist nicht angeschloßen
cp tmp2, tmp
brlo akku_ab

rjmp Main_loop;



;--Unterprogramme-----------------------------------------------------


akku_ab:
;Ausgabe auf Display
;"Akku"
;"anhängen"
rjmp main_loop

akku_an:
;Ausgabe auf Display
;SPG:x,xx
;Entl:x,x
;Warte auf Start-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq start ;Ist Bit gesetzt, Spring in die Start- Fkt.

;Warte auf Entladespg senken:

;Warte auf Entladespg erhöhen
rjmp main_loop

start:
;Akku wurde erkannt und die Starttaste gedrückt
;Start-Taste entprellen
clr entprell
wh1:
ldi tmp, 0b00000010
cp entprell, tmp
brlo wh1
clr sek_zaehler
;Entladevorgang starten
rjmp entladen_ein


entladen_ein:
;Kontrolle ob der Akku noch angeschloßen ist
;Wenn nicht ins Startmenü zurück springen

in tmp, pinc
ori tmp, 0b00000001 ;Relais aktivieren
out portc, tmp

;in tmp2, pina
;ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;cp tmp2, tmp
;brlo entladen_aus

;Akkuspg. überwachen
;Wenn zu niedrig Entladevorgang abbrechen
in tmp2, pina
ldi tmp, 0b10000000
cp tmp2, tmp
brlo entladen_aus

;Warte auf Stop-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq entladen_stop ;Ist Bit gesetzt, Spring in die Start- Fkt.

;Ausgabe auf Display
;A: x,xx
;00:00
rjmp entladen_ein


entladen_aus:
;Entladevorgang stoppen weil die Akkuspannung unter
;einem bestimmter Wert gefallen ist
in tmp, pinc
andi tmp, 0b11111110
out portc, tmp
clr sek_zaehler
rcall automatik
rjmp akku_an

automatik:
;Nach 30 Sekunden soll der Entladevorgang erneut
;gestartet werden
ldi tmp, 0b00011110
cp sek_zaehler,tmp
brsh start

;Schreibe auf Display
;Beendet
;WH in xx

;Warte auf Stop-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq akku_an

in tmp2, pina
ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;Akku ist nicht angeschloßen
cp tmp2, tmp
brlo main_loop

rjmp automatik

entladen_stop:

clr entprell
wh2:
ldi tmp, 0b00000010
cp entprell, tmp
brlo wh2


;Entladevorgang abbrechen
in tmp, pinc
ldi tmp2, 0b00000001
sub tmp, tmp2
out portc, tmp

rjmp main_loop



init:
ldi spg, 0b01010000 ;vorderen 4 Bit vor Komma, hinteren 4 Bit nach Komma

clr sek_zaehler

;Ausgänge setzen
ser tmp
out ddrc, tmp

;Eingänge setzen
clr tmp
out ddra, tmp
out ddrd, tmp


;Timer1 setzen
clr tmp
out tccr1a, tmp
ldi tmp, 0b00001001 ;nur zu Testzwecken (normal 0b00001101)
out tccr1b, tmp

ldi tmp, 0b01100001 ;Timer Einstellungen
out tIMSK, tmp


ldi tmp, HIGH(Frequenz / Teiler)
out ocr1ah, tmp

ldi tmp, LOW(Frequenz / Teiler)
out ocr1al, tmp
;Timer0 setzen
ldi tmp, 0b00000001 ;nur zu Testzwecken (normal 0b00000101)
out tccr0, tmp
ldi tmp, 0b01001110
out ocr0, tmp

sei
rjmp main_loop

;*********Interrupt***********
;Zähler für die Sekundenzählung
timer:
in sreg_save,SREG
inc sek_zaehler
out SREG,sreg_save
reti
;Zähler für die Entprellung
pause:
in sreg_save,SREG
inc entprell
out SREG,sreg_save
reti

Ceos
22.06.2008, 12:12
kann es sein das start und stopp-taste bei dir ein und dasselbe sind ? beide liegen auf bit 0 von PIND ???

brsh start
weis ja nicht genau was das bewirkt, bis kein assemlberspezi, ist in deiner automatikschleife, womöglich änderst du irgendwo deine "entprell" in der startfunktion ungewollt ? tut mir echt leid, ich kann kein assembler(VIEL ZU LANG HER) aber wenn ich so drübergehe sind mir die 2 sachen halt aufgefallen

Stefan_84
22.06.2008, 16:05
Ja das mit dem Taster stimmt. Es soll nur einen Taster für Start und Stop geben.

Ich vermute mal du meinst den "brsh start"-Befehl in der Automatik- Funktion.
Da wird die Variable in der die Sekunden hochgezählt werden mit einem von mir festgelegten Wert (30) vergliechen. Sobald der Sekundenzähler gleich oder höher (brsh) ist springt das Programm zurück zum Start der Entladefunktion um noch einen Entladeversuch durch zu führen

mfg

Stefan_84
22.06.2008, 23:48
Hab das mal eine weile Laufen lassen. Nicht nur das es in die Stop-Funktion springt, es springt später auch wieder in die Start-Funktion.
Die Branch-Befehle werden aus irgend einem mir noch unklaren Grund ausgeführt obwohl die Bedingung nicht erfüllt werden.

Hab es weiter eingegrenzt. Es passiert nur wenn der Timer1 Interrupt aktiv ist!!
Ich versteh aber einfach nicht warum!

Stefan_84
23.06.2008, 18:10
Ich denke es liegt daran dass das SREG - Register bei einem Interrupt verändert wird.
Kann das ein Grund dafür sein? Und kann man das irgendwie verhindern?

The Man
23.06.2008, 18:25
Hi Stefan,

guck mal ein paar Posts weiter oben, da hab ich was zu dem Statusregister hinterlassen.

Stefan_84
23.06.2008, 18:48
Oh, das ist mir jetzt aber peinlich. Das hab ich ganz übersehen, Sorry!!

Nein hab keine Ahnung was ich da überhaupt mache! Wir haben das mal theoretisch in der Schule gelernt, praktisch jedoch nie viel gemacht.

Werds mir gleich mal anschauen!!

Danke nochmals, war echt keine absicht!

mfg

Stefan_84
23.06.2008, 19:04
ES FUNTKIONIERT!!

Vielen Dank!

Sorry das ich so auf der Leitung stand.

The Man
26.06.2008, 09:41
Hi Stefan,

ich hab da noch ne Frage zu deinem Code, was passiert hier:?



;in tmp2, pina
;ldi tmp, 0b01001101 ;Akku erkennung ab 3V
;cp tmp2, tmp
;brlo entladen_aus


und das


;Warte auf Stop-Taste
in tmp2, pind ;Liest Eingangsport ab
andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen
ldi tmp, 0b00000001
cp tmp2,tmp
breq entladen_stop ;Ist Bit gesetzt, Spring in die Start- Fkt.


ich nehme an, du schaltest mit dem Taster einen Pullup an den PIN?

kannst du schneller mit sbic = skip if bit in I/O is cleared machen. Skip´s überspringen immer nur den nächsten Befehl und man muss immer etwas auf die Logki aufpassen.
Dafür würdest du den Programteil "entladen_stop" mit einem rcall entladen_stop und "ret" in eine Subroutine setzten.

mfg,
The Man

Stefan_84
26.06.2008, 22:30
Hallo!
Find ich prima das sich da noch wer den Kopf zerbricht. Bin immer dankbar für neue Tipps und Tricks.

Im ersten Programmteil den du gepostet hast wird kontorlliert ob überhaupt noch ein Akku an der Schaltung angeschloßen ist. Ich möchte das wenn der Akku abgeschloßen wird, das Programm zurück ins Hauptmenü springt damit dann am Display das noch folgen soll wieder da steht "Bitte Akku anschließen".
Der Schaltungsaufbau sieht dabei wie folgt aus:
Die halbe Akkuspg wird über einen ADW mit einer Referenzspg von 5V umgewandelt. Daher ergeben sich für 5V am Akku der Binärcode 10000000 nach dem ADW, und bei 3V am Akku der Binärwert 01001101.

Hab den Teil der kontorlliert ob der Akku noch dran hängt übrigens inzwischen in die Funktion "Automatik" verschoben.
So wird die Abfrage erst gemacht wenn die Akkuspannung unter den eingestellten Vergleichswert gefallen ist, was ja logischerweiße auch passiert wenn der Akku abgeschloßen wird. Hab da aber gerade einen Fehler entdeckt und muss da nochmal ran.
Der Vergleichswert bei der von mir geposteten Version ist ja noch mit 5V fest eingestellt, kann man aber mittlerweile mit einem Taster auswählen ob man den Entladevorgang bei 4, 5 oder 6V beenden möchte. Angezeigt wird die Ausgewählte Vergleichsspannung mittels 2 LED's.



Zum zweiten Programmteil. Also das es nur einen Ein/Aus-Taster gibt ist eh schon bekannt. Am Pin hängt ein Wiederstand (ca. 10k) gegen Masse. Wird der Taster gedrückt, verbindet man dann die +5V mit dem Pin.
Also wenn die Akkuspannung unter die Vergleichsspannung fällt soll von der Schaltung nach einer bestimmten Zeit nochmals weiter entladen werden.
Wird aber die Stop-Taste gedrückt soll die Schaltung komplett mit dem Entladen aufhören und wieder in das Hauptmenü zurück springen und dort bleiben bis wieder die Start-Taste gedrückt wird.

Deinen Befehl durchschau ich noch nicht so ganz, werd mich aber mal mit den Skip- Befehlen befassen.
Ich hab mir ganz am Anfang als ich mit dem Programm begonnen hab überlegt nehm ich Branch oder Skip, hab mich dann für Branch-Befehle entschieden da mir vorgekommen ist dass, damit das Programm übersichtlicher bleibt.

Danke
mfg Stefan

The Man
27.06.2008, 07:36
Hi,

was ich vervollständigend sagen wollte, es ist gut sich Gedanklich über den Zusammenhang von branch, skip und rjmp Befehlen klar zu werden.
Dabei ist eines nicht offensichtlich: eine Abfolge von skip und dann rjmp ist im Prinzip das selbe wie der Einsatz eine branches. Nur wenn man nicht 100% sicher ist, welche werte im Register sind, muss man erstmal maskieren (hast du ja auch gemacht) und dieses maskieren ist mit skip unnötig, da man immer nur das eine Bit testet.

Das du in dem einen Teil eine ADC vor hast dachte ich mir schon fast, wollte mal sehen, was du schreibst. Um ADC´s zu machen muss man die interne Hardware nehemen und eben initialisieren, also entsprechende Steuerbits setzten, die die Funkrion steueren. Zusätzlich muss man auf Statusbits achten, die einem sagen, ob eine Conversion fertig ist. An manchen Stellen ist da Vorsicht geboten, weil manche Bits dadurch gelöscht werden, dass sie per Software gesetzt werden. Is ja auch logisch ne^^? Steht dann im Datenblatt.
Womit wir auch schon beim Thema sind. Das Ding erschlägt einen zwar mit ca.300 Seiten erstmal, aber dann sieht man, dass man immer nur die Seiten braucht, die sich mit der Hardware befassen, die man nutzten will - Puh, nochmal Schwein gehabt! Da wir Assembler machen ist das Datenblatt in sofern gut, als dass man HAARGENAU das macht was da steht und die Kiste läuft. Das nennt man dann Maschienennah.

Was die ADC´s angeht gibt es hier https://www.roboternetz.de/wissen/index.php/ADC_%28Avr%29
einen ersten Blick darauf. Ich würde aber auf jeden noch das Datenblatt lesen. Das macht man am besten mit ner Tasse Kaffe - willkommen in der Welt der Bastler ;-) (nicht weils ewig dauert, sondern weils dazu gehört...)

Wenn´s garnicht gehen will, such ich bei mal nen entsprechenden Code.

Was ich am Anfang auch gemacht, habe war, an einen ADC Kanal einen Poti anschließen, an einen PORT der das ermöglicht 8 LEDS, und zusehen, dass man das ADC Ergebnis mal ausgibt, dann sieht man gleich, ob´s klappt. Und wenn man will kann man auch jedes andere Register sehen - sehr hilfreich! Außerdem sind LED´s immer hilfreich, um sie zum Fehlersuchen zu nehmen. Mann kann sie im Prog an bestimmten Stellen setzten lassen, um zu sehen, ob es da überhaupt ankommt. Mach ich bis jetzt immer so.

Greez.

oberallgeier
27.06.2008, 09:16
Hallo Stefan_84,

weiss nicht ob Dir mein C-Code hilft, aber die Initialisierung (m)eines mega168 und (D)eines mega8515 ist IM PRINZIP sicher ähnlich und der Code ist doch etwas Assemblernah . . . Mit der folgenden Routine initialisiere ich den ADC und lese ihn in der ISR aus. Übrigens repräsentiert der Wert "ADC" in meiner ISR zum Auslesen des ADC die Befehle zum Auslesen des Low- und danach des High-Bytes. Dabei ist die Reihenfolge des Auslesens wichtig! Das steht auch im doc. Vielleicht ist das Beispiel eine Hilfe für Dich?


/* >>
Auszug aus ...C1..\m168D_10\m168D_iir_10x35.h
================================================== =================================
================================================== ============================== */

// .........................

/* ================================================== ===============================
##### Hier ISR und ISR - Initialisierung(en)
================================================== =============================== */
/* ================================================== ============================ */

// Auszug aus *com*.h
volatile uint16_t adc3_dat; // ADC-Wandlung des Sharp GP2D120: adc3_dat=ADC;

// .........................

/* ================================================== ============================ */
/* === Initialisierung fuer ADC mega168 MIT Interrupt ========================
// ISR(ADC_vect) vgl. iomx8.h // Interrupt- Vektor 21
ADC3/PC3 auf 10 Bit, Wandlung #####>>>>> Interrupt ausgelöst */
void ADC3_10_init_irupt(void) //
{
ADMUX |= (1<<MUX1)|(1<<MUX0); // Wandlung mit ADC3
ADMUX |= (1<<REFS0); // Referenzspannung ist Vcc doc S 256 und
// https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=287602#287602
ADCSRA |= (1<<ADPS2)|(1<<ADPS0); // ADC Prescaler = clock/32 S258
// ... das ergibt aus der 4,88-kHz-Motor-PWM 152,5 Hz
ADCSRB |= (1<<ADTS1)|(1<<ADTS0); // ADATE Trigger=TC0-cmpmatchA S259
ADCSRA |= (1<<ADATE); // Auto Triggering Enable, doc S 247 (257)
ADCSRA |= (1<<ADIE); // ADC Interrupt Enable, doc S 258
ADCSRA |= (1<<ADEN); // AD Enable
ADCSRA |= (1<<ADSC); // starte gleich die erste Wandlung
}
/* ================================================== ============================ */
/* === Initialisierung fuer ADC mega168 OHNE Interrupt =====================
// 26mai2008 Diesen Code übernommen aus 22dzms168-regel-x13.c
// ISR(ADC_vect) vgl. iomx8.h // Interrupt- Vektor 21 , KEIN Interrupt enabled
ADC3/PC3 auf 8 Bit, Wandlung "auf Abruf", es wird kein Interrupt ausgelöst */
/* ################# ADC3_10_init ausgeblendet Anfang
void ADC3_10_init(void) //
{
// ADMUX |= (1<<ADLAR); // 8bit-left-adjusted (doc S256)
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // ADC Prescaler clock/128 S258
ADMUX |= (1<<MUX1)|(1<<MUX0); // Wandlung mit ADC3
ADCSRA |= (1<<ADEN); // AD Enable
ADCSRA |= (1<<ADSC); // starte erste Wandlung
} ############ ADC3_10_init ausgeblendet Ende */
/* ================================================== ============================ */


/* ================================================== ============================ */
/* ==== Initialisierungsroutinen sind zu Ende - es folgen die ISR=============== */
/* ================================================== ============================ */

// ..........................................

/* ================================================== ============================ */
/* === Nicht unterbrechbare ISR für ADC3 auf Pin 26/PC3/mega168 =============== */
/* Routine übernimmt ADC-Wert. */
ISR(ADC_vect) // _VECTOR(21)
{
adc3_dat = ADC; // Hole Wert
ADCSRA |= (1<<ADSC); // starte nächste Wandlung
}
/* ================================================== ============================ */


/* ================================================== ============================ */
/* ================================================== ============================ */




Viel Erfolg

Stefan_84
27.06.2008, 09:55
Hallo!
Der 8515 hat doch gar keinen intergrierten ADW, hab dafür ein ADC0804 verwendet. Daher lies ich einfach die Werte die an einem Port anleigen ein und rechne um was das dann für eine Spannung ist.

Mit dem ADW hab ich mich bei einem Bastelprojekt von vor ein paar Monaten beschäftigt. Da wollte ich die Akkuspg. während eines Entladevorganges in den PC einlesen und eine Kennlinie machen. Hab das mit dem Poti damals auch gemacht. Jetzt ist halt statt der Parallelen Schnittstelle des PC's der Portc des 8515 angeschloßen.
Das aktuelle Projekt ist somit also eine weiterführung des ersten Projektes. Das Entladegerät soll ebenfalls dann eine Schnittstelle zum PC hin bekommen, jedoch kann es auch ohne PC verwendet werden und als normales Entladegerät arbeiten.

Das man die Datenblätter benötigt um etwas zu machen hab ich schon gelernt. Hab vor mir am Schreibtisch ne dicke Mappe liegen, voll mit Datenblättern, Anleitungen und Schlatungsbeispielen die ich im laufe der Zeit mal irgendwo gefunden habe.

Hab das Entladegerät auch schon am Steckbrett aufgebaut und es funktioniert auch schon so halbwegs.

mfg
Stefan

oberallgeier
27.06.2008, 12:16
... Der 8515 hat doch gar keinen intergrierten ADW ...Uuuups - ich bin beim Nachgucken/Lesen in die Zeile darunter geraten, die ist für den 8535.

Besserwessi
27.06.2008, 18:59
Einen Mega8515 mit einem externen AD Wandler (0804) zu kombinieren ist keine besonders gute Lösung. Besser wäre da schon ein Mega8 / Mega 88, da ist ein besserer AD schon drin. Außerdem ist der Mega8515 schon wegen der weit auseinanderliegenden Pins für GND und Vcc nicht gut.