ATmega1284p - unerklärliche Phänomene

OP #2817785
Lesenswert?

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
int main(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
  return 0;
14
}
selbes Beispiel mit Watchdog, löst kein Reset aus (allerdings ist die 
Lösung für mich nicht tragbar):
1
int main(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
  return 0;
23
}
Das zweite Problem (innerhalb einer Schleife auf ein Signal warten) 
betrifft die ADC-Konvertierung:
1
int16_t ADC_Read(uint8_t channel)
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_t tmp = ADCW-32768;
14
  ADCSRA = 0;
15
  return tmp;
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.
#2817823
Lesenswert?

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?
OP #2817830
Lesenswert?

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.
OP #2817834
Lesenswert?

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.
#2817842
Lesenswert?

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.
OP #2817845
Lesenswert?

bevor die Frage aufkommt hier noch der ADC-Init, welcher VOR dem 
eigentlichen Read ausgeführt wird ...:
1
#define sampleRate_4k8    128      // 111 = 128 ==> 125 kHz (@ 16 MHz Takt)    4,8 kHz im FreeRun (á 13 Zyklen)
2
#define sampleRate_9k6    64      // 110 = 64  ==> 250 kHz (@ 16 MHz Takt)    9,6 kHz im FreeRun (á 13 Zyklen)
3
#define sampleRate_19k2    32      // 101 = 32  ==> 500 kHz (@ 16 MHz Takt)   19,2 kHz im FreeRun (á 13 Zyklen)
4
#define sampleRate_38k4    16      // 100 = 16  ==> 1,0 MHz (@ 16 MHz Takt)   38,4 kHz im FreeRun (á 13 Zyklen)
5
#define sampleRate_76k8    8      // 011 =  8  ==> 2,0 MHz (@ 16 MHz Takt)   76,8 kHz im FreeRun (á 13 Zyklen)
6
#define sampleRate_153k6  4      // 010 =  4  ==> 4,0 MHz (@ 16 MHz Takt)  153,6 kHz im FreeRun (á 13 Zyklen)
7
#define sampleRate_307k2  2      // 001 =  2  ==> 8,0 MHz (@ 16 MHz Takt)  307,2 kHz im FreeRun (á 13 Zyklen)
1
// ADC initialisieren
2
int16_t ADC_Init(void) 
3
{
4
  // A/D-Kanal wählen
5
  if(Filter.LM) chADC = adcLMAMP;        // ADC6
6
  if(Filter.MAX292) chADC = adcLPBESSEL;    // ADC2
7
  if(Filter.BPB) chADC = adcBPBFILTER;    // ADC4
8
  if(Filter.BPA) chADC = adcBPAFILTER;    // ADC5
9
  if(Filter.MAX293) chADC = adcLPBUTTERWORTH;  // ADC7
10
  if(Filter.NO) chADC = adcNOFILTER;      // ADC3
11
  
12
  // Frequenzvorteiler festlegen
13
  SampleRate = sampleRate_19k2;
14
  
15
  // interne Referenzspannung als Refernz für den ADC wählen + Kanal
16
  if(!Filter.ADC_Ref)
17
    ADMUX = (1<<REFS0) | (1<<ADLAR);
18
  // externe Spannung als Refernz für den ADC wählen + Kanal
19
  if(Filter.ADC_Ref)
20
    ADMUX = (1<<ADLAR);
21
          
22
  // Kanal waehlen, ohne andere Bits zu beeinflußen
23
  ADMUX = (ADMUX & ~(0x1F)) | (chADC & 0x1F);
24

25
  ADCSRA |= (1<<ADIF) | (1<<ADSC) | (1<<ADATE);  // FreeRun
26
  ADCSRA |= SampleRate;              // Frequenzvorteiler
27
   ADCSRA |= (1<<ADEN);              // ADC aktivieren
28

29
   // Dummy-Messung ~ Warte solange ADIF nicht "1" ist
30
  while(!(ADCSRA & (1<<ADIF)));    
31
  int16_t tmp = ADCW-32768;
32
  ADCSRA = 0;
33
  return tmp;
34
}
#2817859
Lesenswert?

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.
#2817865
Lesenswert?

>  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.
OP #2817871
Lesenswert?

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?!
Gast #2817887
Lesenswert?

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;
OP #2817902
Lesenswert?

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.
Gast #2817910
Lesenswert?

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.
Gast #2817917
Lesenswert?

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
OP #2817922
Lesenswert?

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
OP #2817932
Lesenswert?

kann den ursprünglichen post leider nicht mehr bearbeiten, also hier der 
nachtrag:
1
// Frequenzvorteiler für ADC (ADPS2..ADPS0)
2
#define sampleRate_4k8    7      // 111 = 128 ==> 125 kHz (@ 16 MHz Takt)    4,8 kHz im FreeRun (á 13 Zyklen)
3
#define sampleRate_9k6    6      // 110 = 64  ==> 250 kHz (@ 16 MHz Takt)    9,6 kHz im FreeRun (á 13 Zyklen)
4
#define sampleRate_19k2    5      // 101 = 32  ==> 500 kHz (@ 16 MHz Takt)   19,2 kHz im FreeRun (á 13 Zyklen)
5
#define sampleRate_38k4    4      // 100 = 16  ==> 1,0 MHz (@ 16 MHz Takt)   38,4 kHz im FreeRun (á 13 Zyklen)
6
#define sampleRate_76k8    3      // 011 =  8  ==> 2,0 MHz (@ 16 MHz Takt)   76,8 kHz im FreeRun (á 13 Zyklen)
7
#define sampleRate_153k6  2      // 010 =  4  ==> 4,0 MHz (@ 16 MHz Takt)  153,6 kHz im FreeRun (á 13 Zyklen)
8
#define sampleRate_307k2  1      // 001 =  2  ==> 8,0 MHz (@ 16 MHz Takt)  307,2 kHz im FreeRun (á 13 Zyklen)

das passiert wenn man in einer solution 2 projekte hat :/
Gast #2817935
Lesenswert?

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.
OP #2817940
Lesenswert?

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
OP #2818001
Lesenswert?

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.
#2818100
Lesenswert?

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.
OP #2819344
Lesenswert?

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.

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