Forum: Compiler & IDEs analog comparator erkennt keine veränderte flanke


von Moritz S. (mollitz)


Lesenswert?

Hi,

Ich hab an meinem ATMega168 an ADC1 3,2 V angelegt und ADC0 auf masse 
gelegt.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
ISR(ANALOG_COMP_vect)
4
{
5
  PORTB = 0x00;
6
}
7
8
9
int main(void)
10
{
11
  DDRB = 0xff;
12
  PORTB = 0xff;
13
  ACSR |= (1<<ACIE) | (1<<ACIS1);
14
  sei();
15
  for(;;);
16
  return 0;
17
}
verbinde ich jetzt ADC0 mit 5V bleibt PORTB an. Soweit wär ja auch noch 
alles in ordnung. Lege ich ADC0 jetzt aber wieder auf Masse(fallende 
Flanke) bleibt PORTB immer noch an.

Weiß jemand was ich falsch gemacht hab?

Danke,

Moritz

von STK500-Besitzer (Gast)


Lesenswert?

Laut Tabelle 21-2 im Datenblatt muß man die Richtungserkennung der 
Flanke  umschalten.

von Moritz S. (mollitz)


Lesenswert?

Hi,

Von welchem Datenblatt reden wir?
In meinem ist das nämlich eine andere Tabelle: "Table 21-2.
Status codes for Master Transmitter Mode".
Ansonsten wird doch die Richtungserkennung umgeschalten.
ACSR |= (1<<ACIE) | (1<<ACIS1);
Das ACIS1-Bit sorgt dafür, dass ein Interrupt bei fallender Flanke 
ausgelöst wird.
EDit:
Ah bei mir ist Tabelle 22-2 wohl die richtige:
1
Table 22-2.
2
ACIS1
3
0
4
0
5
1
6
1
7
ACIS0
8
0
9
1
10
0
11
1
12
Interrupt Mode
13
Comparator Interrupt on Output Toggle.
14
Reserved
15
Comparator Interrupt on Falling Output Edge.
16
Comparator Interrupt on Rising Output Edge.
naja das dann halt als Tabelle denken.
Und ich hab ACIS0=0 ACIS1=1 bedeutet Comparator Interrupt on Falling 
Output Edge.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Der AC liegt beim ATmega*8 an Port D6 (AIN0) und D7 (AIN1). Teilweise 
kann man andere Pins verwenden, wenn der ADC inaktiv ist und men den 
ADC-Input-Multiplexer entsprechend nutzt. ADC0-ADC5, womöglich auch ADC6 
und ADC7.

Bit ACME in ADCSRB.

von Moritz S. (mollitz)


Lesenswert?

Aber nach meinem Sourcecode muss ich doch einfach an Port D6 (AIN0) und 
D7 (AIN1) anlegen oder?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ja, aber oben schriebst du was von ADC0 (Port C0) und ADC1 (Port C1)

von Moritz S. (mollitz)


Lesenswert?

Hi,

Stimmt, mein Fehler sorry. Habs aber an AIN0 und AIN1 angeschlossen.
Muss DDRD eigentlich irgendwie gesetzt sein?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Moritz Sch schrob:
> Muss DDRD eigentlich irgendwie gesetzt sein?

Ich würd es auf IN ohne Pullups setzen, also default nach Reset.

Versuch mal

Das ISQ-Flag nach Setzen von ACSR zu löschen, also:
1
   ASCR = (1 << ACIE) | (1 << ACIS1);
2
   ASCR = (1 << ACIE) | (1 << ACIS1) | (1 << ACI);

Ausserdem kannst du versuchen
-- Auf Toggle der Flanke zu regieren: ACIS[1..0] = 00
-- Mehr Informationen an Port B auszugeben, zB ACO, etc.

von Moritz S. (mollitz)


Lesenswert?

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
ISR(ANALOG_COMP_vect)
4
{
5
  PORTB = 0x00;
6
}
7
8
9
int main(void)
10
{
11
  DDRB = 0xff;
12
  PORTB = 0xff;
13
  ACSR = (1 << ACIE);
14
  ACSR = (1 << ACIE) | (1 << ACIS1) | (1 << ACI);
15
  sei();
16
17
  /* neverending loop */
18
  for(;;);
19
  return 0;
20
}
Soweit mein momentaner Code: Bringt nichts, PORTB bleibt an.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Nein, das ist nicht was ich oben schrieb.

Das IRQ-Flag nmuss nach Ändern der Flankensensitivität resettet 
werden.

von Moritz S. (mollitz)


Lesenswert?

Also im Interrupt?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Beim Initialisieren entweder
1
   ASCR = (1 << ACIE) | (1 << ACIS1);
2
   ASCR = (1 << ACIE) | (1 << ACIS1) | (1 << ACI);

oder
1
   ASCR = (1 << ACIE);
2
   ASCR = (1 << ACIE) | (1 << ACI);

Wobei ich erst mal Version 2 versuchen würde. Wenn's damit nicht klappt 
ist das Problem woanders: µC kaputt oder Fehler im Makefile, so daß du 
immer das gleiche, alte Programm brennst oder sowas.

von Moritz S. (mollitz)


Lesenswert?

Hi,

Sry hab mich wieder verschrieben. Meinte die 2. Version!
Es ist übrigends ACSR (nicht ASCR).
Ok nochmal zum Überprüfen ob ich das richtige verstanden hab.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
ISR(ANALOG_COMP_vect)
4
{
5
  PORTB = 0x00;
6
}
7
8
9
int main(void)
10
{
11
  DDRB = 0xff;
12
  PORTB = 0xff;
13
  ACSR = (1 << ACIE);
14
  ACSR = (1 << ACIE) | (1 << ACI);
15
  sei();
16
17
  /* neverending loop */
18
  for(;;);
19
  return 0;
20
}
Das Makefile ist in Ordnung (Wenn ich sinnlose Zeilen dazuschreiben wird 
die gebrannte byte-zahl größer).
Kann es sein, dass nur der comparator kaputt ist und der rest 
funktioniert?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

hmmm, ich weiß ja net, was du mit dem Ding alles angestellt hast...

Denkbar wäre auch, daß er verfust ist, zB WDT an ist und er immer einen 
WDT-Reset macht, so daß das kurze Verlöschen der LED nicht zu erkennen 
ist.

Ich hatte mal den Port eines Mega168 frittiert, der µC lief ansonsten 
tadellos, nur der eine Port ging eben nicht mehr. Und der µC wurde 
ziemlich warm dabei, was ich sonst bei AVR noch nie beobachtet habe.

von Moritz S. (mollitz)


Lesenswert?

Hi,

Hab noch nie was mit Fuse-Bits gemacht. Ich les mich mal kurz ein, was 
falsch gesetzt sein könnte.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Der WDT ist standardmässig aus, wenn du nix an den Fuses gedreht hast, 
fällt mir nichts mehr ein..

Vielleicht ne instabile Spannungsversorgung? Oder ein 
nicht-stabilisiertes Netzteil. Wenn da 5V draufstehen, liefert das im 
Leerlauf u.U. deutlich mehr. Und ein AVR zieht ja praktisch nichts an 
Strom.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
ISR(ANALOG_COMP_vect)
5
{
6
  PORTB &= ~(1 << PB1);
7
}
8
9
int main(void)
10
{
11
  DDRB  = (1 << PB1) | (1 << PB0);
12
  PORTB |= (1 << PB1);
13
14
  ACSR = (1 << ACIE);
15
  ACSR = (1 << ACIE) | (1 << ACI);
16
17
  sei();
18
19
  while (1)
20
  {
21
      if (ACSR & (1 << ACO))
22
         PORTB |= (1 << PB0);
23
      else
24
         PORTB &= ~(1 << PB0);
25
  }
26
}

Ob der AC überhaupt was macht siehst du an dem Code an Pin B0, ob die 
ISR aufgerufen wird an Pin B1.

Wie gesagt, mir gehen da langsam die Ideen aus...

von Moritz S. (mollitz)


Lesenswert?

Hier die Fuses:

Das kommt raus:
avrdude: Device signature = 0x1e9406
avrdude: safemode: lfuse reads as F7
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as 1

WDTON ist nicht gesetzt.

http://www.engbedded.com/cgi-bin/fc.cgi?P_PREV=ATmega168&P=ATmega168&V_LOW=F7&V_HIGH=DF&V_EXTENDED=1&O_HEX=Apply+user+values&M_LOW_0x3F=0x22&M_LOW_0x80=0x00&M_HIGH_0x07=0x07&M_HIGH_0x20=0x00&M_EXTENDED_0x06=0x00&B_CKDIV8=P&B_SPIEN=P&B_SUT0=P&B_CKSEL3=P&B_CKSEL2=P&B_BOOTSZ1=P&B_BOOTSZ0=P&B_CKSEL0=P

Dein Code tut leider auch nicht. Also PB0 bleibt immer aus und PB1 
bleibt immer an.

Spannungsversorgung ist konstant bei 4,87V.

von Johann L. (gjlayde) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich denke es ist ein Hardwareproblem.

Gehen denn sonstige Testprogramme? ZB Simple Warteschleife und LED 
blinken?

Wie hast du den Quarz angeschlossen?

Die Fuses sehen jedenfalls gut aus (falls ein Quarz etc dran ist)
1
#define F_CPU 8000000
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
int main(void)
7
{
8
    DDRB |= (1 << PB0);
9
10
    while (1)
11
    {
12
        uint8_t i;
13
        for (i=0; i < 100; i++)
14
            _delay_ms (10);
15
            
16
        PORTB ^= (1 << PB0);    
17
    }
18
}

von Moritz S. (mollitz)


Lesenswert?

Hi,

hab mit dem Ding schon alles mögliche gemacht(USART, Timer, blinkende 
LEDs).
Es ist ein 20 Mhz Quarz drann der soweit auch tut. (F_CPU ist auf 
20000000 und die warte-funktionen dauern so lang wies sein soll).
Hab jetzt auch mal alle möglichen Spannungen an AIN0 und AIN1 angelegt 
und geändert. Ich bin der Meinung mein Controller hat da ne Macke, werd 
mal bei gelgenheit einen anderen ausprobieren.

Aber danke für die Hilfe

Moritz

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.