Forum: Mikrocontroller und Digitale Elektronik ATmega1284p - unerklärliche Phänomene


von Philipp K. (--phil--)


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.

von Spess53 (Gast)


Lesenswert?

Hi

Wie wäre es, mit sei() die Interrupts freizugeben. Und dann auch ADIE 
setzen.

MfG Spess

von Stefan E. (sternst)


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?

von Philipp K. (--phil--)


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.

von Philipp K. (--phil--)


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.

von Stefan E. (sternst)


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.

von Philipp K. (--phil--)


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
}

von Philipp K. (--phil--)


Lesenswert?

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!:
1
  ADCSRA = (1<<ADEN) | (1<<ADIF)  | (1<<ADATE);
2
  ADCSRA |= SampleRate;              
3
   ADCSRA |= (1<<ADSC);

oder haben wir aneinander vorbeigeredet?

von Stefan E. (sternst)


Lesenswert?

Und du sagst, er bleibt immer noch in der while-Schleife, die auf ADIF 
wartet, hängen?

von Spess53 (Gast)


Lesenswert?

Hi

>  ADCSRA = (1<<ADEN) | (1<<ADIF)  | (1<<ADATE);

Der ADC-Interrupt wird mit ADIE freigegeben.

MfG Spess

von Joachim .. (joachim_01)


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.

von Joachim .. (joachim_01)


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.

von Philipp K. (--phil--)


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?!

von Philipp K. (--phil--)


Angehängte Dateien:

Lesenswert?

im anhang noch die fuses

von Philipp K. (--phil--)


Lesenswert?

ich komme von dem ansatz nicht weg, dass es vielleicht auch damit 
zusammenhängen könnte, wie es bei dem usart-problem der fall ist:

Link:
http://www.seanet.com/~karllunt/1284pmemprob.html

???

von MWS (Gast)


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;

von Philipp K. (--phil--)


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.

von MWS (Gast)


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.

von MWS (Gast)


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

von Philipp K. (--phil--)


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

von Philipp K. (--phil--)


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 :/

von MWS (Gast)


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.

von holger (Gast)


Lesenswert?

Target Voltage 4.3V? Schon eine etwas merkwürdige Spannung.
Wenn der ADC nicht will könnte auch AVCC vergessen worden sein.

von Philipp K. (--phil--)


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

von MWS (Gast)


Lesenswert?

Simulier's und schau' Dir die Register an, dann weist Du's auch.

von holger (Gast)


Lesenswert?

Da ja schon beim Quellcode Verwirrung herrschte:
Bist du sicher das du die richtige HEX Datei gebrannt hast?

von Philipp K. (--phil--)


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.

von Volker (Gast)


Lesenswert?

Schalt doch mal den Oszillator auf full Swing, vielleicht bringt das 
was...

von Joachim .. (joachim_01)


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.

von Philipp K. (--phil--)


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.

von Joachim .. (joachim_01)


Lesenswert?

Und? Woran lag's?

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.