Was auch immer, um wirksam zu sein, muss das heissen
DDRB &= ~(1<<PB3);
ACSR &= ~(1<<ACD);
schaut pervers aus, is aber eben C, um einzelne Bits auf 0 zu setzen
Hallo,
ich bin gerade dabei, den Analog Comparator meines Atmega32 ein zu
stellen.
ich habe mit dem Befehl
ACSR =(1<<ACBG);
den AIN0 auf innere Referenz (2,56V) umgeschaltet.
Danach mit
DDRB =(0<<PB3);
den AIN1 als Eingang definiert.
Laut AVR Tutorial würde der AC immer parallel zum Controller mitlaufen,
man müßte ihn sogar explizit ausschalten wenn man ihn nicht benötigt, um
Strom zu sparen.
Damit er AC auch wirklich eingeschaltet ist, sag ich dem ACSR noch:
ACSR = (0<<ACD);
Die Allgemeinen Interrupts werden mit
sei();
eingeschaltet
Über einen Spannungsteiler gebe ich nun die Vergleichsspannung auf den
Eingang AIN1.
Nun kommt das Problem:
Egal wie hoch die Vergleichsspannung ist, der AC gibt mir immer auf ACO
ein High heraus, er sagt also, die innere Referenzspannung sei höher als
die Vergleichsspannung.
Selbst wenn die Vergleichsspannung bei +5V liegt, meint der ACO, die
Referenzspannung sei aber immer noch höher.
Habe ich irgendetwas vergessen?
Ich habe da so ein Gerücht gehört, der AC des Atmega32 würde in der DIL
Version nicht funktionieren? Hat da jemand schon so etwas gehört, oder
ähnliche Erfahrungen gemacht?
Grüße von
Sylvia
Was auch immer, um wirksam zu sein, muss das heissen
DDRB &= ~(1<<PB3);
ACSR &= ~(1<<ACD);
schaut pervers aus, is aber eben C, um einzelne Bits auf 0 zu setzen
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
Hallo Robert,
ich habe den Code abgeändert, es funktioniert trotzdem nicht.
Aber danke für deine Antwort
Sylvia
Ich hab mal das Datenblatt angeschaut.
Folgende Register müssen mit Werten befüllt werden:
SFIOR
ACSR
Wenns über Interrupts Laufen soll müssen diese auch enabled sein - Rätselhaft.
MCUCR ist auch eine beliebte Fehlerquelle, hat aber soweit ich sehe kein Bit für den Comperator und die Interrupts hast Du mit #asm("sei"); ja auch freigegeben.
Das die JTAGEN Fuse ist auch ein beliebter Fehler, betrifft aber nur den Port C
Ich habe nun mit
SFIOR &= ~(1<<ACME);
ACME auf 0 gesetzt, damit laut Datenblatt AIN1 mit dem negativen Eingang des AC verbunden wird, aber.........
est verändert sich immer noch nichts.
Das JTAGEN Fuse ist gesetzt,
bei MCUCR wüsste ich jetzt nicht, was ich setzen soll.
Grüße von
Sylvia
Was ich jetzt nachgelesen habe, sollte sein
ehrlich gesagt, mehr weiss ich im moment auch nichtCode:ACSR &= ~(1<<ACD) ' comp aktiv ACSR |= (1<<ACBG) ' intern. referenz SFIOR &= ~(1<<ACME) ' AIN1 immer als Ref neg. Input DDRB &= ~(1<<PB3); ' PB3 als Input PORTB &= ~(1<<PB3); ' sicherheitshalber Pullup abschalten. ' kann nicht schaden
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
Habe den Code genauso geflasht, geht aber immer noch nicht.
Vielen Dank trotzdem!
Gruß
Sylvia
Ich will mir nicht deinen Zorn zuziehen, aber vielleicht hat's doch was mit deinem Programm.
Sei doch mal so gut und zeig dein Programm mal her.
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
Der Code ist in ein größeres Programm eingebunden,
prinzipiell sieht er so aus:
Code:/* * Der ATMEGA 32 wird als Slave konfiguriert, und wartet auf die Anweisungen des Masters. * * Bekommt er eine 11 geschickt, soll der seine Lämpchen blinken lassen, bei einer 00 soll das Lauflicht * * gestartet werden. Unterschreitet die Spannung am AC 2,5V, soll aus dem Programm ausgestiegen werden */ #include <avr/io.h> #ifndef F_CPU #define F_CPU 160000000UL #endif #include <util/delay.h> #include <inttypes.h> #include <avr/interrupt.h> #include "outpin.h" // Lib um Pins ein und aus zu schalten #include "i2csylvia.h" // Lib für die I2C übertragung #include <avr/interrupt.h> // Externe Interrupts outpin_t led2; outpin_t led3; outpin_t led4; outpin_t led5; uint16_t i; uint8_t Spannung_weg; //Variable zur Betriebsspannungs anzeigen int befehl; void lauflicht(void) { ....Code für ein Lauflicht } void blinklicht(int n, int ms) { .....Code für Blinklicht } // den Befehl ausführen void takeorder() { TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); // Clear TWINT to start tranmission, send ACK to receive mor Bits while (!(TWCR & (1<<TWINT))); // Wait for TWIN flag is set.This indicates that // Data byte has been received, and ACK/NACK has been returned befehl = i2cReadData(); switch(befehl) { case 11: blinklicht(2,200); // wird eine 11 geschikt : 2x langsam blinken break; case 00: lauflicht(); // bei einer 00 : 2 x lauflicht break; //default : blinklicht (4,100); // wird etwas anderes geschickt: schnelles Fehlerblinken break; } } int main (void) { DDRB &= ~(1<<PB3); // AIN1 als Eingang initialisieren PORTB &=~(1<<PB3); // Sicherheitshalber Pullup abschalten outpin_init(&led2,'A',7); // Initialisierung der LED`s 2-3 auf Port Ausgänge 3-7 outpin_init(&led3,'A',6); outpin_init(&led4,'A',4); outpin_init(&led5,'A',3); sei(); // set enable interrupt --> global interrupts einschalten i2cinit(16); uart_init(); ACSR |= (1<<ACBG); // AC Auf Interne Referenzspannung (2,56V) umschalten ACSR &= ~(1<<ACD); // AC explizit einschalten SFIOR &= ~(1<<ACME); // AIN1 wird mit dem Invertierten Eingang des Comperators verbunden TWAR = 0x40; // Die Slave Adresse wird auf "64" festgelegt TWCR = (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO); // Das Senden der Bestätigungsbits (ACK) zulassen,Start und Stop auf 0 setzen TWCR =(1<<TWIE); // Interrupts zulassen blinklicht(3,1000); // 3x langsam Blinken als optische bestätigung, das der Slave wartet while(1) // In einer Endlosschleife auf die Befehle des Masters warten { Spannung_weg = ACO; // Comperator auslesen, sobald die Spannung am Testwiderstand 2,56V unterschreitet, ist ACO auf High (1) if(Spannung_weg ==1) //Wenn die Betriebsspannung weg ist, aus dem Programm ausssteigen { blinklicht(1,1000); break; } takeorder(); // Den gesendeten Befehl ausführen } }
Au weia. Sollte heissen:
Zur Erläuterung:Code:Spannung_weg = ACSR & (1<<ACO); // ACO aus ACSR rausfummeln if(Spannung_weg != 0) { blinklicht(1,1000);
ACO hat den festen Wert 5
Daher ist
Spannung_weg = 5
Und
if (Spannung_weg == 1)
geht nie auf
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
Lesezeichen