Mega32 AnalogComparator Interrupt löst nicht aus

OP #3719924
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
}
#3719946
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.
OP #3720458
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.
OP #3720474
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
#3720486
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;
Gast #3720491
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
OP #3720496
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 =)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren