Forum: Mikrocontroller und Digitale Elektronik Mega32 AnalogComparator Interrupt löst nicht aus


von J. T. (chaoskind)


Lesenswert?

MoinMoin

ich hab mal wieder ein kleines Problem, ich möchte mit dem 
Analogkomparator eine Spannung messen.

Meine Spannung gebe ich auf PinA0, den Komp habe ich auf interne 
Bandgabreferenz gestellt, und den Multiplexer eingeschaltet. Per polling 
hat das auch alles wunderbar geklappt, Spannung größer Bandgap --> LED 
an und andersrum. Dann hab ich versucht, das ganze per Interrupt zu 
lösen, jeddoch wird mein Interrupt nicht ausgelöst. ACO wechselt aber je 
nachdem, ob ich positivere oder negativere Spannung an PinA0 geb, das 
sehe ich per OCD. Globale Interrupts sind auch aktiviert, in einem alten 
Beitrag hab ich gelesen, das es auf die Reihenfolge ankommt, in der man 
den AC initialisiert. Also hab ichs wie dort gemacht, ACD ein, 
Einstellungen machen, ACO wieder aus, und dann ACIE (die 
Komparatorinterrupts) an. Auch erfolglos....

Das ganze läuft auf nem Mega32, wie oben schon erwähnt.

Für weiterführende Hinweise wäre ich sehr dankbar,

MfG Chaos =)

Hier noch der Quelltext
1
/*
2
 * Lueftercontroller.c
3
 *
4
 * Created: 09/07/2014 21:35:30
5
 *  Author: Ich
6
 */ 
7
8
9
#include <avr/io.h>
10
#include <avr/interrupt.h>
11
#include <inttypes.h>
12
13
ISR(ANA_COMP_vect)
14
{
15
  uint8_t Arbeitsreg = 0;
16
  
17
  Arbeitsreg = ACSR & (1 << ACO);
18
  
19
  if (Arbeitsreg == 0)
20
  {
21
    PORTB &= ~(1 << PB0);
22
  }
23
  
24
  if (Arbeitsreg == ACO)
25
  {
26
    PORTB |= (1<< PB0);
27
  }
28
}
29
30
31
void init(void);
32
33
34
35
int main(void)
36
{
37
  init();
38
  
39
    while(1)
40
    {
41
       uint8_t i = 0;    //um zu sehen, ob etwas passiert 
42
     i = PORTC;
43
     i++;
44
     PORTC = i;     
45
  }
46
}
47
48
49
50
51
52
void init(void)
53
{
54
  TCCR0 = (1<<WGM00) | (1<<WGM01) | (1<<COM00) | (1<<COM01) | (1<<CS01); //Timer0 init auf FastPWM Inverting Mode, Prescaler 1
55
  DDRB = (1<<PB3) | (1<<PB0);  //auf Ausgang setzen, um den Ausgangstreiber vom OC-Pin zu aktivieren
56
  DDRC = 255;
57
  ACSR |= (1<<ACD);
58
  ACSR |= (1<<ACBG); //AnalogComparator auf interne Referenz am +Eingang
59
  SFIOR |= (1<<ACME); //AnaCompMultiplexer aktivieren
60
  ACSR &= ~(1<<ACD);
61
  ACSR |= (1<<ACIE);
62
  sei();
63
}

von H.Joachim S. (crazyhorse)


Lesenswert?

199
2503Q–AVR–02/11
ATmega32(L)
Analog Comparator
Control and Status
Register – ACSR
• Bit 7 – ACD: Analog Comparator Disable
When this bit is written logic one, the power to the Analog Comparator 
is switched off.

edit sagt: weiter unten schaltest du es ja wieder aus.

>> if (Arbeitsreg == ACO)

tut nicht, was du erwartest.

: Bearbeitet durch User
von J. T. (chaoskind)


Lesenswert?

ja ich schalte das ACD bit ein, damit der der AC ausgeschaltet ist, 
stelle ihn dann ein, und dann schalte ich ihn wieder ein, indem ich das 
ACD-bit lösche. So stand es in dem Thread.

Aber auch ohne das Aus- und wieder Einschalten geht es nicht.....

von J. T. (chaoskind)


Lesenswert?

und nochmal, der AC an sich geht ja, ich sehe ja, wie sich das ACO-Bit 
ändert, wenn ich die Spannung höher oder tiefer setze als die 
Bandgapspannung. Nur der Interrupt wird halt nicht ausgelöst

von J. T. (chaoskind)


Lesenswert?

Noch etwas, ich habe mir nun mal klugerweise einen Breakpoint in den 
Interrupt gesetzt, und siehe da, er springt ihn doch an. Seltsamerweise 
funktionieren zb der Timer und UART-IRQ auch im SingleStepModus, weiß 
zufällig wer, warum das beim AC_IRQ nicht so ist?

Nun verstehe ich aber auch den Hinweis

>> >> if (Arbeitsreg == ACO)

>> tut nicht, was du erwartest.

Egal wie ACO gerade steht, es wird immer if(Arbeitsreg == 0) ausgeführt, 
wenn ich aber if(Arbeitsreg = 0) schreibe, dann führt er immer den 
Else-Zweig aus.

von ich (Gast)


Lesenswert?

=        !=           ==
Zuweisung         Prüfen auf gleichheit
Mit feundlichen Gruß

von J. T. (chaoskind)


Lesenswert?

nächster Versuch
1
  if (Arbeitsreg == 0)
2
  {
3
    PORTB &= ~(1 << PB0);
4
  }
5
  
6
  else if (Arbeitsreg == 0b00100000)
7
  {
8
    PORTB |= (1 << PB0);
9
  }
10
  
11
  else
12
  {
13
    PORTB = (1 << PB1)
14
  }

Das funktioniert wie erwartet. Vermutlich ist das ACO also nicht 32 
sondern 5. Naja selber denken führt auch zum Ziel.
Dank an Crazyhorse für den Gedankenanstoss =)

MfG Chaos

von J. T. (chaoskind)


Lesenswert?

@ ich

heißt das, wenn ich if(Arbeitsreg = x) wird das Arbeitsreg auf x 
gesetzt?

Und was ist dann die Bedingung, dafür das die Schleife ausgeführt wird? 
Ob das Arbeitsregister überhaupt da, also 1 ist? oder wird der If-Zweig 
ausgeführt, solange x != 0?

von H.Joachim S. (crazyhorse)


Lesenswert?

j. t. schrieb:
> ISR(ANA_COMP_vect)
> {
>   uint8_t Arbeitsreg = 0;
>
>   Arbeitsreg = ACSR & (1 << ACO);
>
>   if (Arbeitsreg == 0)
>   {
>     PORTB &= ~(1 << PB0);
>   }
>
>   if (Arbeitsreg == ACO)
>   {
>     PORTB |= (1<< PB0);
>   }
> }
{
if (ACSR & (1 << ACO))   // ACO gesetzt?
   {
   }
   else {
        }
}
reicht doch, oder?

Ich persönlich finde ja die Biterweiterungen von CodeVision sehr 
praktisch:

PORTB.0=ACSR.ACO;

von ich (Gast)


Lesenswert?

Der IF-Zweig wird ausgeführt wenn die bedingung Wahr ist. Hier das 
Register GLEICH 0 (Nicht NULL ich unterscheide beides da es für mich zum 
lesen leichter ist, einmal wert und einmal ein Pointer mit Null).
Das Arbeitsregister wird tatsächlich auf x gesetzt.
Eine schleife kann ich (außer der üblichen while(1) Schleife) nicht 
sehen.
Diese wird ausgeführt solange der Ausdruck wahr ist (in C also !=0).
MfG
ich

von J. T. (chaoskind)


Lesenswert?

Da haste Recht, das würde reichen, das war nur im Testwahn so entstanden 
*gg

Auhja, das sieht komfortabel aus! Was is denn dieses CodeVision? auch 
eine IDE?

von J. T. (chaoskind)


Lesenswert?

ich schrieb:
> Der IF-Zweig wird ausgeführt wenn die bedingung Wahr ist. Hier das
> Register GLEICH 0 (Nicht NULL ich unterscheide beides da es für mich zum
> lesen leichter ist, einmal wert und einmal ein Pointer mit Null).
> Das Arbeitsregister wird tatsächlich auf x gesetzt.
> Eine schleife kann ich (außer der üblichen while(1) Schleife) nicht
> sehen.
> Diese wird ausgeführt solange der Ausdruck wahr ist (in C also !=0).
> MfG
> ich

Ja schleife war der falsche Begriff, der kam mir nur in den Kopf, weil 
ich genau an diese ominöse while(1)-Geschichte denken musste.

Danke euch beiden nochmal, wieder ein kleines Stückchen mehr C 
verstanden =)

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.