Hallo liebe Forengemeinde!
Ich stehe vor einem Rätsel...
Ursprünglich habe ich ein Programm geschrieben, welches problemlos auf
nem ATmega32 lief ... da ich mit den Ressourcen am Ende war, aber noch
einiges umsetzen wollte bin ich zum ATmega1284p gewechselt.
Interruptvektoren, Register etc. angepasst... das ist alles nicht das
Thema.
Dazu sollte ich vielleicht noch erwähnen, dass ich mit Sicherheit nicht
mehr grün hinter den Ohren bin, wenn's ums Programmieren geht.
Ich verwende:
- AtmelStudio 6 Version: 6.0.1843
- AVR Toolchain 8 Bit Version: 3.4.0.663
- AVR-GCC Version: 4.6.2
- AVR ISP mkII
Das Problem:
Der Controller resettet, sobald ein Delay ins Spiel kommt, oder auf ein
Signal gewartet wird (innerhalb einer while-Schleife etc)... es liegt
eigentlich auf der Hand ~> Watchdog.
Nur ist das Watchdog-Fuse nicht gesetzt und im Programm habe ich den
Watchdog nicht drin.
Erste Lösungsansätze:
Beispiel, die einen Reset auslösen:
1
intmain(void)
2
{
3
DDRC=0xFF;
4
PORTC=0xFF;
5
6
while(1)
7
{
8
PORTC=0xF0;
9
_delay_ms(100);// <~ RESET
10
PORTC=0x0F;// wird nie erreicht
11
_delay_ms(100);
12
}
13
return0;
14
}
selbes Beispiel mit Watchdog, löst kein Reset aus (allerdings ist die
Lösung für mich nicht tragbar):
1
intmain(void)
2
{
3
DDRC=0xFF;
4
PORTC=0xFF;
5
6
while(1)
7
{
8
PORTC=0xF0;
9
10
wdt_enable(WDTO_8S);
11
_delay_ms(100);
12
wdt_reset();
13
wdt_disable();
14
15
PORTC=0x0F;
16
17
wdt_enable(WDTO_8S);
18
_delay_ms(100);
19
wdt_reset();
20
wdt_disable();
21
}
22
return0;
23
}
Das zweite Problem (innerhalb einer Schleife auf ein Signal warten)
betrifft die ADC-Konvertierung:
1
int16_tADC_Read(uint8_tchannel)
2
{
3
// Kanal wählen
4
ADMUX=(ADMUX&~(0x1F))|(channel&0x1F);
5
6
ADCSRA=(1<<ADIF)|(1<<ADSC)|(1<<ADATE);// FreeRun
7
ADCSRA|=SampleRate;// Frequenzvorteiler
8
ADCSRA|=(1<<ADEN);// ADC-Konv. starten
9
10
// Warte solange ADIF nicht "1" ist
11
while(!(ADCSRA&(1<<ADIF)));// <~ HÄNGER
12
13
int16_ttmp=ADCW-32768;
14
ADCSRA=0;
15
returntmp;
16
}
Da ADIE nicht gesetzt wird, löst der Interrupt nicht aus ~ ADIF kann
also als Signal verwendet werden, um den Abschluß der Konvertierung
abzufragen (?! ~ steht zumindest so im Datenblatt)... funktioniert
allerdings auch nicht, wenn man ADIE setzt und den Interrupt mit
entsprechendem Vektor in ISR()/SIGNAL() "abfängt". auch das warten auf
ADSC = 0 macht keinen Unterschied ~> entweder hängt sich die Büchse in
der while-Schleife auf, oder eben der Watchdog greift...
Stand schonmal jemand vor einem derartigen Problem oder hat noch nen
SINNVOLLEN Ansatz, um den Fehler einzugrenzen? Habs auch schon mit nem
anderen Controller versucht ~ das Ergebnis ist identisch... dazu muss
ich allerdings sagen, dass ich die Controller als Samples bei atmel
geordert habe ... die "Werkseinstellungen" der Fuses waren schon
unterschiedlich... (ich weis nicht, ob es sich um Neuware oder
Gebrauchtgut handelt ... daher möchte ich HW-Defekte nicht ausschließen
~ nur wie testen?) und wie bereits erwähnt: auf dem mega32 hatte ich nie
derartige Probleme.
Ich hoffe mir kann jemand noch nen Rat geben ~ bin mit meinem Latein am
Ende.
Philipp Kl. schrieb:> Der Controller resettet, sobald ein Delay ins Spiel kommt, oder auf ein> Signal gewartet wird (innerhalb einer while-Schleife etc)... es liegt> eigentlich auf der Hand ~> Watchdog.>> Nur ist das Watchdog-Fuse nicht gesetzt und im Programm habe ich den> Watchdog nicht drin.
Dir ist aber schon klar, dass wenn der Watchdog einmal aktiv war (und du
hast ja offenbar auch Varianten mit Watchdog-Aktivierung im Code
probiert), er nach einem Reset automatisch wieder aktiv ist, oder? Du
musst den Controller schon von der Versorgung trennen, um den Watchdog
dann wieder los zu werden.
Philipp Kl. schrieb:> entweder hängt sich die Büchse in> der while-Schleife auf
Eine Wandlung starten zu wollen (ADSC) bevor der ADC überhaupt
eingeschaltet ist (ADEN), scheint mir auch irgendwie nicht sinnvoll. Und
warum überhaupt Free-Run?
die interrupts werden mittels sei() aus der main heraus freigegeben...
den main-part habe ich mir bei dem adc-problem erspart zu posten.
mittlerweile bin ich aber schon einen kleinen schritt weiter ~ habe den
eeprom nochmal "nackt" gemacht ~ dadurch ist zumindest das delay-problem
behoben - warum auch immer... werde hier mal noch ein wenig
recherchieren.
Stefan Ernst schrieb:> Eine Wandlung starten zu wollen (ADSC) bevor der ADC überhaupt> eingeschaltet ist (ADEN), scheint mir auch irgendwie nicht sinnvoll. Und> warum überhaupt Free-Run?
FreeRun, um bei Vorteiler 32 á 13 Zyklen @ 16Mhz auf 38,4kS zu kommen.
Macht es nicht eher mehr Sinn, den ADC erstmal zu "konfigurieren", bevor
ich ihn starte?! ~ Wobei auch hier kein Unterschied feststellbar ist.
Philipp Kl. schrieb:> Macht es nicht eher mehr Sinn, den ADC erstmal zu "konfigurieren", bevor> ich ihn starte?!
Der vorgesehen Weg ist es, den ADC erst einzuschalten und zu
konfigurieren, und dann erst eine Wandlung zu starten.
Philipp Kl. schrieb:> Wobei auch hier kein Unterschied feststellbar ist.
Da du keinen Code gepostet hast, an dem man sehen kann, was "auch hier"
nun konkret bedeutet, kann man dazu schlecht was sagen.
Stefan Ernst schrieb:> Da du keinen Code gepostet hast, an dem man sehen kann, was "auch hier"> nun konkret bedeutet, kann man dazu schlecht was sagen.
damit habe ich diesen Versuch gewagt
EDIT!:
Poste doch mal die Fuse-Bits. Hab hier nen 1284P an dem ich seit Monaten
fast täglich böse Sachen dran teste. So nen Fehler hatte ich noch nie.
Nur einmal, ganz am Anfang hat ich nen Prob mit dem JTAG-Fuse welches
den PIN als Reset/JTAG konfiguriert. Vielleicht liegt da ja ungefähr
exakt dort der Hund begraben.
Halt mich auf dem Laufenden.
> ADCSRA = (1<<ADEN) | (1<<ADIF) | (1<<ADATE);>Der ADC-Interrupt wird mit ADIE freigegeben.
Ja schon, aber für seinen Fehler ist das egal. Er prüft ja nicht auf
Interrupt-Funktionalität an sich, sondern er will wissen warum das
Interrupt-Flag per se nicht kommt. ADIE ist unabhängig von ADIF.
Spess53 schrieb:> Der ADC-Interrupt wird mit ADIE freigegeben.
ADIE will ich ja nicht... lt. Datenblatt kann man mit ADIF ohne ADIE das
ConversationComplete-Ereignis für den FreeRun abfragen, ohne dass der
Interrupt auslöst, welchen man noch mit ISR(ADC_vect) abarbeiten muss...
das will ich so auch nicht.
Der Spaß funktioniert nach diesem Prinzip ganz gut so ~ habe ich schon
mit mehreren Megas so umgesetzt ... glaub nicht, dass der 1284p da jetzt
ne Ausnahme macht?!
Philipp Kl. schrieb:> Der Spaß funktioniert nach diesem Prinzip ganz gut so ~ habe ich schon> mit mehreren Megas so umgesetzt ... glaub nicht, dass der 1284p da jetzt> ne Ausnahme macht?!
Kann ich mir nicht vorstellen, allein schon die merkwürdige
Initialisierung ein ADSC vor einem ADEN zu machen.
Das hier ist ja auch Käse:
> SampleRate = sampleRate_19k2;
Per Define sind das die tatsächlichen Teiler, die müssen aber für
ADPS2..0 an Bit2..0 entsprechend umgesetzt werden und können nicht
einfach so mit ADCSRA verodert werden. Damit werden dann andere Bits in
ADCSRA überschrieben.
> ADCSRA |= SampleRate;
MWS schrieb:> Das hier ist ja auch Käse:>>> SampleRate = sampleRate_19k2;>> Per Define sind das die tatsächlichen Teiler, die müssen aber für> ADPS2..0 an Bit2..0 entsprechend umgesetzt werden und können nicht> einfach so mit ADCSRA verodert werden. Damit werden dann andere Bits in> ADCSRA überschrieben.>>> ADCSRA |= SampleRate;
Schlag mich, wenn ich falsch liege... ABER dafür funkioniert das mit dem
Mega32 super.
ADCSRA |= 0b111;
ist mindestens genauso verodert wie
ADCSRA |= SampleRate;
... wenn SampleRate = sampleRate_4k8 (aus meinem Beispiel)
ADCSRA ist ein Byte ... die Bits ADPS2..ADPS0 stehen an den ersten
Stellen, somit brauch auch nix geschoben werden... wenn es dir nicht
gefällt ist es dein Part, das tut der Funktion aber keinen Abbruch.
Die ADC_Init() wurde gepostet, bevor ich den Ansatz von Stefan in
Betracht gezogen habe.
SampleRate wird bei 19k2 mit 32 verodert, damit wird ADATE erneut auf 1
gesetzt, was allein noch nichts machen würde, aber damit bleibt ADPS2..0
auf 0, somit ADC-Prescaler = 2 (wenn das Datenblatt stimmt) und das wird
zu hoch sein.
Der höchste Wert für ADPS2..0 ist 7, Du würdest dagegen per Define bis
zu 128 damit verodern, das geht natürlich nicht.
Philipp Kl. schrieb:> wenn es dir nicht> gefällt ist es dein Part, das tut der Funktion aber keinen Abbruch.
Der Spruch ist jetzt ein wenig unangebracht angesichts der Tatsache ich
mir Gedanken um Dein Problem gemacht und Dir den Fehler genannt hab'.
Es ist auch weniger so, dass es mir nicht gefällt, es ist eher so dass
es dem ATM1284 nicht passt :D
MWS schrieb:> SampleRate wird bei 19k2 mit 32 verodert, damit wird ADATE erneut auf 1> gesetzt, was allein noch nichts machen würde, aber damit bleibt ADPS2..0> auf 0, somit ADC-Prescaler = 2 (wenn das Datenblatt stimmt) und das wird> zu hoch sein.>> Der höchste Wert für ADPS2..0 ist 7, Du würdest dagegen per Define bis> zu 128 damit verodern, das geht natürlich nicht.
sorry, grad gemerkt was du meinst... oben sind die falschen defines
gepostet ~ die oben geposteten sind zur Frequenzbandberechnung für
LCD-Anzeige, welche auf nem anderen Controller läuft ... hab an falscher
Stelle COPY+PASTE angesetzt
Ahh, eine Überraschung...
Wichtig ist welches Define der Compiler tatsächlich zum verodern der
Samplerate verwendet. Deine Defines nennen sich gleich und sind auch vom
Kommentar her passend.
Ich würd' den Ansatz verfolgen, alle ADC-relevanten Register per
einmaliger Zuweisung zu setzen, auch ADCSRB, nicht dass da noch anderer
Code daran rumgepfuscht hat.
Und dann nochmal testen.
MWS schrieb:> Ahh, eine Überraschung...> Wichtig ist welches Define der Compiler tatsächlich zum verodern der> Samplerate verwendet. Deine Defines nennen sich gleich und sind auch vom> Kommentar her passend.> Ich würd' den Ansatz verfolgen, alle ADC-relevanten Register per> einmaliger Zuweisung zu setzen, auch ADCSRB, nicht dass da noch anderer> Code daran rumgepfuscht hat.> Und dann nochmal testen.
Das sind 2 eigenständige Projekte innerhalb einer Solution ~ es wird
jedes Projekt für sich kompiliert und erstellt... hinten raus hab ich
dann meine 2 HEX-Files. Abhängigkeiten zueinander habe ich keine
festgelegt...
Werd aber mal die ganzen Geschichten umbenennen ~ Hoffnung stirbt ja
bekanntlich zuletzt :D
holger schrieb:> Da ja schon beim Quellcode Verwirrung herrschte:> Bist du sicher das du die richtige HEX Datei gebrannt hast?
Ja, das passt.
MWS schrieb:> Simulier's und schau' Dir die Register an, dann weist Du's auch.
Hab mich hingesetzt und den ganzen Spaß nochmal überarbeitet/umbenannt
... hat leider aber auch nichts gebracht.
Werde es für heute erstmal sein lassen... mir fällt nichts mehr ein.
Hm. So schlecht sieht der Code für den ADC ja jetzt nicht aus. Selbst
wenn er Mist mißt muß mindestens ADIF kommen.
Irgendwie... hab ich das Gefühl, das Prob kommt nicht aus dem ADC
sondern vom Watchdog. Hastn Oszi? Schau doch mal (nur so aus Spass) ob
dein Oszillator bei dem Halt überhaupt noch läuft oder ob aus
Stromspargründen zB der Oszillator abgeschaltet wurde. Irgendwas ist an
deiner Büchse oberfaul.
Und, ja, wirf doch mal nen Blick auf den assemblierten Code, vielleicht
macht der GCC ja böse Sachen; der optimiert gerne mal was weg.
Joachim ... schrieb:> Hm. So schlecht sieht der Code für den ADC ja jetzt nicht aus. Selbst> wenn er Mist mißt muß mindestens ADIF kommen.>> Irgendwie... hab ich das Gefühl, das Prob kommt nicht aus dem ADC> sondern vom Watchdog. Hastn Oszi? Schau doch mal (nur so aus Spass) ob> dein Oszillator bei dem Halt überhaupt noch läuft oder ob aus> Stromspargründen zB der Oszillator abgeschaltet wurde. Irgendwas ist an> deiner Büchse oberfaul.> Und, ja, wirf doch mal nen Blick auf den assemblierten Code, vielleicht> macht der GCC ja böse Sachen; der optimiert gerne mal was weg.
Ich selbst nutze nur eine umgebaute soundkarte als oszi... Aber ein
richtiges leihweise zu beschaffen sollte nicht das thema sein ~ werd's
mal prüfen. Danke.