Forum: Mikrocontroller und Digitale Elektronik analog comparator interrupt probleme mit atmegas


von John I. (john_i)


Lesenswert?

Hallo zusammen,

bei einem Projekt brauche ich einen analog comparator interrupt. Dazu 
habe ich mir eine kleine Versuchsschaltung aufgebaut, die 2 Spannungen 
vergleicht und einer LED zur Anzeige. Das Programm dazu steht unten.

Jetzt ist folgendes Problem aufgetreten, da wo der interrupt auslösen 
sollte passiert nichts. Das interrupt flag im ACSR Register wird beim 
ersten wechsel der Spannung gesetzt und bleibt danach gesetzt, die 
interrupt routine wird aber nicht ausgeführt. Habe das ganze mit 2 
atmega168pu-pa und 2 atmega8a-pu ausprobiert, immer mit dem selben 
Ergebnis. Kann irgendjemand helfen?
1
.NOLIST
2
.include "m168def.inc"
3
.LIST
4
5
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
6
7
.org 0x0000
8
  rjmp RESTART
9
.org 0x002E
10
  rjmp ANA_COMP
11
  
12
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
13
14
RESTART:
15
;----------stack----------
16
  ldi r16, HIGH(RAMEND)
17
  out SPH, r16
18
  ldi r16, LOW(RAMEND)     
19
  out SPL, r16
20
;----------IOs------------
21
  ldi r16,0b00000001
22
  out DDRD,r16    ;Port D Pin 0 wird als Ausgang gesetzt
23
;-----------Comparator------------
24
  ldi r16, 0b01001000
25
  sts ACSR, r16    ;setze 1,3V an AIN0 und schalte comparator interrupt ein
26
;----------other------------
27
  clr r16
28
  clr r17
29
  clr r18
30
  
31
  sei
32
  
33
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
34
35
main:
36
  cbi PORTD, 0  ;led aus
37
  in r16, ACSR
38
  sbrs r16, 4  ;ueberspringe naechsten Schritt wenn bit 4 gesetzt ist
39
  sbi PORTD, 0  ;led an
40
  
41
  rjmp main  
42
43
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
44
;---------------Interrupt Analog Comperator------------------------------------------------------------------------------------------------------------------------
45
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
46
47
ANA_COMP:  
48
  sbi PORTD, 0    ;led an
49
  
50
START_LOOP:    ;Zeitschleife
51
  inc r17
52
  cpi r17, 0b11111100
53
  brlo START_LOOP
54
  clr r17
55
  inc r18
56
  cpi r18, 0b00001000
57
  brlo START_LOOP
58
  clr r17
59
  clr r18
60
61
  rjmp END
62
63
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
64
;---------------End-----------------------------------------------------------------------------------------------------------------------------------------------
65
;------------------------------------------------------------------------------------------------------------------------------------------------------------------
66
67
END:
68
  reti

von chris (Gast)


Angehängte Dateien:

Lesenswert?

ertsmal Tip zum schreiben

für 0bxxxxxxx kannst du auch
(0<<ACD|0<<ACBG|1<<ACI|1<<ACIE|0<<ACIC|1<<ACIS1|0<<ACIS0)
macht den Text übersichtlicher

denn setze hier entsprechend reti's ein
statt RJMP nutze er JMP

.org 0x0000
  rjmp RESTART
reti
reti
.
.
.
.org 0x002E
  rjmp ANA_COMP

bis die Adresse 2E erreicht ist.

siehe Datenblatt S.62

von S. Landolt (Gast)


Lesenswert?

Die Schreibweise ist in der Tat eine Herausforderung für den Lesenden.

>  sts ACSR, r16    ;setze 1,3V an AIN0

muss heißen  out ACSR,r16.

von I/O (Gast)


Lesenswert?

John I. schrieb:
>
1
>   sts ACSR, r16    ;setze 1,3V an AIN0 und schalte comparator interrupt 
2
>

Geht es mit " out ACSR, r16"?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

John I. schrieb:
> Jetzt ist folgendes Problem aufgetreten, da wo der interrupt auslösen
> sollte passiert nichts. Das interrupt flag im ACSR Register wird beim
> ersten wechsel der Spannung gesetzt und bleibt danach gesetzt, die
> interrupt routine wird aber nicht ausgeführt. Habe das ganze mit 2
> atmega168pu-pa und 2 atmega8a-pu ausprobiert, immer mit dem selben
> Ergebnis. Kann irgendjemand helfen?

 Erstens :
1
.org 0x002E
2
  rjmp ANA_COMP
 macht man nicht. Es ist nicht dieselbe Adresse beim M8 und M168 und
 es sollte auch nicht dasselbe Befehl sein (rjmp/jmp).
 MEGA8:
 0x010    rjmp ANA_COMP
 MEGA88:
 0x017    rjmp ANA_COMP
 MEGA168:
 0x002E   jmp ANA_COMP

 Dafur gibt es beim ATMEL so etwas wie:
.equ  ACIaddr  = 0x0010  ; Analog Comparator beim M8
und
.equ  ACIaddr  = 0x002e  ; Analog Comparator beim M168

 deswegen schreibt man:
1
.org ACIaddr
2
  rjmp ANA_COMP

 Zweitens :
 Irgendwelche Warteschleifen in der ISR sind ganz grosses NoNo.
 Setze irgendein Flag in der ISR, den du in der MAIN prufen kannst
 und das wars.

 Drittens :
John I. schrieb:
> main:
>   cbi PORTD, 0  ;led aus
>   in r16, ACSR
>   sbrs r16, 4  ;ueberspringe naechsten Schritt wenn bit 4 gesetzt ist
>   sbi PORTD, 0  ;led an
>
>   rjmp main

 So wie ich das sehe, muss deine LED, wenn einmal an, dauernd leuchten ?
 ACI wird in der ISR zuruckgesetzt, LED wird in der ISR eingeschaltet
 und nicht mehr ausgeschaltet (abgesehen von den 4 Takten in Main), aber
 ich bezweifle, dass du das merken kannst.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Vorschlag, nur zum Testen (ansonsten gilt 'zweitens' von Marc Veseley):
1
.equ  LED  = 0
2
.def  tmp0  = r16
3
4
.org 0
5
  rjmp restart
6
.org ACIaddr
7
  rjmp ana_comp
8
9
restart:
10
  sbi DDRD,LED
11
  ldi tmp0,(1<<ACBG)+(1<<ACIE)
12
  out ACSR,tmp0
13
  sei
14
15
main:
16
  cbi PORTD,LED
17
  in tmp0,ACSR
18
;  sbrs r16,ACI  ;ueberspringe naechsten Schritt wenn bit 4 gesetzt ist
19
;   sbi PORTD,LED
20
 rjmp main  
21
22
23
ana_comp:
24
  sbi PORTD,LED
25
  ldi XH,high(65000)
26
  ldi XL,low(65000)
27
   sbiw XL,1
28
  brne pc-1  
29
  reti

von S. Landolt (Gast)


Lesenswert?

> aber ich bezweifle, dass du das merken kannst.

Bei 8 MHz sehe ich tatsächlich nichts, bei 1 MHz kann ich gerade noch 
einen Unterschied an der LED erkennen.

von John I. (john_i)


Lesenswert?

Ich bedanke mich schon mal herzlich für die schnellen Antworten.

@chris, retis wurden eingesetzt und rjmp gegen jmp getauschst, hat aber 
leider keine Verbesserung gebracht.

@S. Landolt und I/O, out-Befehl geht nicht

@Marc Vesely, Mein Problem ist eher das die LED sofort nach ändern der 
spannung an AIN1 ausgeht und demzufolge die interrupt routine nicht 
ausgeführt wird. Und natürlich hatte ich für den atmega8 ein anderes 
Programm.

Interessant ist warum die routine nicht abgearbeitet wird obwohl 
interrupt flag gesetzt und interrupts global eingeschalten sind.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> @S. Landolt und I/O, out-Befehl geht nicht

Und was daran soll nicht gehen, gibt es eine Fehlermeldung, wie lautet 
diese?

von John I. (john_i)


Lesenswert?

@ S. Landolt, habe gerade dein Programm getestet und es funktioniert :).
Da muss ich schauen wo der Fehler bei mir ist, vielen dank.

Achso und dort funktioniert der out-Befehl, da hab ich wahrscheinlich 
irgendwie den Überblick verloren bei der Fehlersuche.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

John I. schrieb:

> da hab ich wahrscheinlich
> irgendwie den Überblick verloren bei der Fehlersuche

Nein.

Du hattest einfach zu keiner Zeit einen Überblick (im Sinne des 
Begreifens des Systems).

Und ich bin sicher: Du hast ihn auch jetzt noch nicht...

von S. Landolt (Gast)


Lesenswert?

Nachtrag zu meinem Vorschlag:
Bei dem alten ATmega8 muss der Stackpointer, wie im ursprünglichen 
Programm, explizit gesetzt werden.

> Und ich bin sicher: Du hast ihn auch jetzt noch nicht...
Das ist anzunehmen, wird sich aber mit der Zeit ändern, dafür gibt es ja 
das Forum.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

S. Landolt schrieb:
> Bei dem alten ATmega8 muss der Stackpointer, wie im ursprünglichen
> Programm, explizit gesetzt werden.

 LOL.
 Beim Mega168 nicht ?

von holger (Gast)


Lesenswert?

>> Bei dem alten ATmega8 muss der Stackpointer, wie im ursprünglichen
>> Programm, explizit gesetzt werden.
>
> LOL.
> Beim Mega168 nicht ?

Schon mal das Datenblatt gelesen? Nein, man muss nicht.

von MWS (Gast)


Lesenswert?

Marc Vesely schrieb:
> Beim Mega168 nicht ?

Nein. Musst Du Datenblatt lesen.

von S. Landolt (Gast)


Lesenswert?

> LOL.
> Beim Mega168 nicht ?

Was ist jetzt daran so lustig?

von chris (Gast)


Lesenswert?

Alle Adressen(Register) die größer als 003F sind werden mit STS und 
darunter mit OUT angesprochen. "REGISTERMAPPING"

Der OUT Befehl muss funktionieren da ACSR die Adresse 30Hex hat und 
somit der OUT-Befehl massgebend ist.

John I. schrieb:
> Interessant ist warum die routine nicht abgearbeitet wird obwohl
> interrupt flag gesetzt und interrupts global eingeschalten sind.

wenn du das AVRstudio6 nutzt siehe Bild blaue Makierung entsprechend 
ändern da sonst die INTS übersprungen werden

von I/O (Gast)


Lesenswert?

chris schrieb:
> wenn du das AVRstudio6 nutzt siehe Bild blaue Makierung entsprechend
> ändern da sonst die INTS übersprungen werden

Bild? Blaue Markierung? INTS übersprungen?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

holger schrieb:
>> LOL.
>> Beim Mega168 nicht ?
>
> Schon mal das Datenblatt gelesen? Nein, man muss nicht.

MWS schrieb:
> Nein. Musst Du Datenblatt lesen.

S. Landolt schrieb:
> Was ist jetzt daran so lustig?

 ATMEL:
 "The Stack in the data SRAM must be defined by the program before any
 subroutine calls are executed or interrupts are enabled. Initial Stack
 Pointer value equals the last address of the internal SRAM and the
 Stack Pointer must be set to point above start of the SRAM"

 Selbst Atmel sagt, dass der SP gesetzt werden muss, ob der jetzt beim
 Programstart zum Ende des RAMs oder ins Nirwana zeigt, ist eigentlich
 egal.
 Und nur weil sich Programm am Anfang befindet, heisst noch lange nicht,
 dass der SP auch dorthin zeigt, wo er zeigen soll.

von S. Landolt (Gast)


Lesenswert?

Beim ATmega168 steht der initial-value für SPH&SPL auf RAMEND.

von S. Landolt (Gast)


Lesenswert?

Ich gebe Ihnen Recht, wenn § restart im Wortsinne benutzt wird, das ist 
aber hier und auch meistens sonst nicht der Fall.
Und lustig finde ich das Ganze noch immer nicht.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

S. Landolt schrieb:
> Beim ATmega168 steht der initial-value für SPH&SPL auf RAMEND.

 Deswegen steht Ihr beim "P" vom Programmierer und ich bezweifle das
 Ihr jemals bis zum "r" kommt.

von chris (Gast)


Angehängte Dateien:

Lesenswert?

nachtrag bild

von I/O (Gast)


Lesenswert?

Marc Vesely schrieb:
> S. Landolt schrieb:
>> Beim ATmega168 steht der initial-value für SPH&SPL auf RAMEND.
>
>  Deswegen steht Ihr beim "P" vom Programmierer und ich bezweifle das
>  Ihr jemals bis zum "r" kommt.

Deine Argumentation wäre wohl anders gewesen, wenn du gewußt hättest, 
daß die Register schon richtig stehen. Mag sein, daß du mit deinem "P" 
recht hast, sehe ich aber hier nur als Ausrede. Schwach.

von S. Landolt (Gast)


Lesenswert?

an Marc Veseley
Jetzt verstehe ich gar nicht mehr, worauf Sie eigentlich hinaus wollen, 
ist mir aber letztlich auch egal.

Mein Anliegen war, John I. zu helfen, das scheint so zu sein - mir 
reicht's.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

I/O schrieb:
> Deine Argumentation wäre wohl anders gewesen, wenn du gewußt hättest,
> daß die Register schon richtig stehen. Mag sein, daß du mit deinem "P"
> recht hast, sehe ich aber hier nur als Ausrede. Schwach.

S. Landolt schrieb:
> an Marc Veseley
> Jetzt verstehe ich gar nicht mehr, worauf Sie eigentlich hinaus wollen,
> ist mir aber letztlich auch egal.

 Erst lesen, dann "argumentieren".

Marc Vesely schrieb:
> Und nur weil sich Programm am Anfang befindet, heisst noch lange nicht,
>  dass der SP auch dorthin zeigt, wo er zeigen soll.

 Als normaler (muss gar nicht so gut sein) Programmierer, stellt man
 am Anfang sicher, dass alle Register genau die Werte haben, die man
 auch möchte.
 Vor allem SP und Index Register. Da wird gar nichts "vorausgesetzt"
 und "normallerweise steht der SP auf RAMende und IndexRegister
 müssten eigentlich genau dorthin zeigen".

 Nach Ihrer Logik könnte der Compiler das auch beim M168/M328
 wegoptimieren, tut der aber nicht, was glaubt Ihr warum ?

 Dafür war mein LOL.

 Wer es immer noch nicht versteht, soll sich lieber ein anderes Hobby
 suchen.

von S. Landolt (Gast)


Lesenswert?

Marc Vesely schrieb:
> Dafür war mein LOL.

Ach so, Sie haben mich ausgelacht. Je nun, wenn Ihnen das etwas gebracht 
hat...
Dem Fragesteller in seinem jetzigen Stadium hat es vermutlich nicht 
geholfen.

Im Übrigen teile ich die Meinung nicht ganz; so wird es wohl seine 
Gründe haben, dass es überhaupt Anfangswerte gibt, und dass Atmel diesen 
für den Stackpointer bei den neueren Controllern sinnvoll setzt.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

S. Landolt schrieb:
> Ach so, Sie haben mich ausgelacht. Je nun, wenn Ihnen das etwas gebracht
> hat...

 Nein, ich habe niemanden ausgelacht.
 Ich habe nur über etwas, was mir unlogisch schien, gelacht.

S. Landolt schrieb:
> Dem Fragesteller in seinem jetzigen Stadium hat es vermutlich nicht
> geholfen.

 Ich glaube doch, denn: Was der Hänschen nicht lernt, lernt der Hans...


S. Landolt schrieb:
> Im Übrigen teile ich die Meinung nicht ganz; so wird es wohl seine
> Gründe haben, dass es überhaupt Anfangswerte gibt, und dass Atmel diesen
> für den Stackpointer bei den neueren Controllern sinnvoll setzt.

 Ja, nur hat ATMEL nirgendwo geschrieben, dass, wenn sich Programm auf
 Adresse 0x00 befindet, SP automatisch auf Speicherende zeigen muss.
 XMEGAs haben einen bit fur Hardware Reset aber MEGAs haben sowas (noch)
 nicht.
 Somit ist auch ein JMP nach 0x0000 nutzlos, Register- und Portinhalte
 werden nicht verändert.
 Aber mit einem Fehler im Loop, falsch berechnetem indirect jump o.ä.
 ist man ganz schnell den FLASH raufgefahren und wieder bei 0x0000
 angelangt.
 In der Zwischenzeit hat man einen Port auf Ausgang gestellt, sollte
 aber am Anfang Eingang sein, man verlässt sich halt auf ATMEL und
 schon gibt es einen Kurzschluss.
 Danach springt man ins Nirwana weil der SP nach deiner Meinung auf
 Speicherende zeigen muss.
 Danach... usw, usw.

 Alles, was bei mir irgendwie mit der Aussenwelt zu tun hat, wird am
 Anfang auf Eingang gestellt. Ebenso SP und Indexregister.
 Da kann ATMEL in seinem DaBla schreiben, was er will.
 Die paar Befehle tun bestimmt nicht weh.

von S. Landolt (Gast)


Lesenswert?

Ich bin anderer Meinung; bei einem davongelaufenen Programm würde ich 
die Ursache dafür finden wollen. Ich habe meine Erfahrungen, Sie die 
Ihren. Wenn ich das Konzept richtig verstehe, müssten zu Programmbeginn 
sämtliche SFRs gesetzt werden, sie könnten ja vom Amok laufenden 
Programm verstellt worden sein (immer in der Hoffnung, dass dieses auch 
wieder bei 0 aufsetzt).
Wie dem auch sein - ist doch aber alles noch lange kein Grund, uns 
gegenseitig die Befähigung zum Programmieren abzusprechen.

Bei meinem Vorschlag für John I. habe ich eben die Initialisierung des 
Stackpointers noch nachgetragen, als ich sah, dass er vielleicht das 
Programm auch auf dem ATmega8 laufen lässt. Die Reaktion darauf
> LOL.
> Beim Mega168 nicht ?
finde ich nach wie vor völlig unpassend; eine kurze Erläuterung statt 
des LOL hätte uns dieses jetzige Hin&Her erspart.

Und was hat das alles noch mit der Eingangsfragestellung zu tun? Nichts 
mehr, wie ich finde, und so wünsche ich allen eventuellen Mitlesern ein 
schönes Wochenende.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.