Forum: Mikrocontroller und Digitale Elektronik UART1 problem beim ATMEGA128


von Henrik (Gast)


Lesenswert?

Hallo zusammen,
nach Stunden der Fehlersuche mit meinem ATMEGA128 weiß ich nicht mehr 
weiter.
Folgende Situation:
Ich betreibe mit einem ATMEGA128 beide UARTS. UART0 läuft einwandfrei. 
UART1 sendet Daten, ist aber nicht in der Lage Daten zu empfangen.
Beide Schnittstellen laufen auf 9600B 8N1, beide Schnittstellen werden 
gepollt betrieben.
Für UART1 habe ich auch eine Interrupt- Variante ausprobiert. Auch hier 
keine Regung.
Die Gegenstelle ist geprüft und sendet die Antworten korrekt zurück an 
UART1( per Oszi direkt am RxD1 Pin des ATMega128 gemessen).
M103C Fuse ist nicht gesetzt.

Hier der Code zum versenden und empfangen eines Befehls.
1
int Modul_on (void){
2
3
com2_puts_P(OM_Modul_ON);
4
  
5
  //Antwort des Moduls
6
  if (getModulAnswer()==FALSE)
7
    {com1_puts_P(ERR_Modul_ON);
8
    return FALSE;
9
    }
10
  }
11
return TRUE;
12
}


hier die getModulAnswer() zum Empfang der Antwort.
1
uint8_t getModulAnswer(){
2
  ModulPortValue=0;
3
  i_lsr=0;
4
  LSRTimeOut = TIMEOUTLSR;
5
  
6
  
7
    
8
  while (ModulPortValue != 0x0d)  //auf Carriage return warten
9
    {
10
    //auf zeichen warten
11
    while( (!(UCSR1A & (1<<RXC1))) || (LSRTimeOut!=0) ) 
12
      {//Timeout
13
      _delay_ms(10);
14
      LSRTimeOut--;
15
      }
16
    
17
18
    //war es ein Timeout?
19
    if (LSRTimeOut==0)
20
      {
21
      return FALSE;
22
      }
23
    else {LSRTimeOut = TIMEOUTLSR;}
24
  
25
    //Empfangenes Zeichen speichern
26
    ModulPortValue = UDR1;
27
    
28
          
29
    if (ModulPortValue == 0x0d) com2Buffer[i_lsr]=0;
30
    else com2Buffer[i_lsr]=ModulPortValue;
31
    i_lsr++;
32
    }
33
  return TRUE;
34
}

Schon mal vor ab Danke für jeden Tip!

Gruß,
Henrik

von Huch (Gast)


Lesenswert?

Mir persönlich bereitet die Rückkehr mit Return aus einer while-Schleife 
heraus Bauchschmerzen, aber naja.

Dein Code ist nicht nützlich. Zwar könnte da theoretisch auch ein Fehler 
liegen, aber wesentlich ist erstmal der eigentliche Datenempfang, die 
Initialisierung der UARTs die Du hier nicht zeigst und die Hardware.
Das aber prüfst Du am besten mit einem Minimslprogramm, das die 
empfangenen Zeichen zurücksendet.

von Andreas V. (tico)


Lesenswert?

Hast Du die Versorgungsspannung an allen entsprechenden Pins korrekt 
angeschlossen? Insbesondere auch an AVCC (Pin 64) ?

Gruss
Andreas

von Henrik (Gast)


Angehängte Dateien:

Lesenswert?

Das geht ja schnell... Danke.
zur Vervollständigung der Infos:
Init der Schnittstelle
1
void com2_Init(uint32_t baudRate, uint32_t quarzClock) {
2
3
  // Baud Rate setzen
4
  UBRR1H = (uint8_t)(((quarzClock)/((baudRate)*16l)-1)>>8);
5
  UBRR1L = (uint8_t)((quarzClock)/((baudRate)*16l)-1);
6
  
7
         UCSR1B = 0x18;
8
9
  //asynchronous 8N1
10
  UCSR1C = 0x06;  
11
12
  UCSR1A = 0x00;
13
}

Der  eigentliche Datenempfang befindet sich in der Funktion
getModulAnswer(); siehe oben :
1
//auf zeichen warten
2
    while( (!(UCSR1A & (1<<RXC1))) || (LSRTimeOut!=0) ) 
3
      {//Timeout
4
      _delay_ms(10);
5
      LSRTimeOut--;
6
      }
LSRTimeOut ist ein Timeout- Counter der hier die Endlosschleife 
verhindern soll. Ansonsten wird auf Receive completed des UCSR1A 
Registers gepollt.
Das Verhalten ist also stand jetzt immer ein Timeout.
Der Timeout wird pro Zeichen rückgesetzt und liegt bei 250ms. Per Oszi 
habe ich ermittelt, dass die Antwort des Zielsystems innerhalb von 
10-20ms erfolgt (timeout sollte somit ausreichen).

@Huch: Mit dem Return in der Schleife geb ich dir recht, is unsauber. 
Werde den Timeout ebenfalls in die äußere Schleife setzen und den 
Rücksprung bedingt außerhalb der Schleifen durchführen. Als 
Fehlerursache kann ich es mir jedoch nicht vorstellen, habe zuvor auch 
ohne Timeout gearbeitet, was einen Dead Lock zur folge hatte.

Nochmal zur erläuterung des Fehlerverhaltens:
UART1 sendet --> OK
Zielsystem reagiert --> OK
Zielsystem antwortet --> Ich sehen die zeichen auf dem Scope 
ankommen,wenn ich an PIN27 (PD2/RxD1) von meinem ATMEGA128 messe!
-->RXC1 wird trotzdem nie gesetzt.

In sachen Hardware:
an UART0 --> PC, Hyperterinal
an UART1 --> weitere MC basierte Elektronik. Dieses System ist ein 
Kaufteil und bereits öfters im Einsatz. Kann ich leider nicht als 
mögliche Fehlerursache anführen.
Beide Rx und Tx leitungen sind vom ATMEGA128 auf ein MAX232ACSE geführt. 
Betriebsspannung des MAX und Kondensatorwerte des Prototypboards sind 
überprüft.
Schalplanauszug ist beigefügt.

@Andreas: Im Schaltplan ist er Angeschlossen. Messung am Pin64,52,21 
ergab leider jeweils auch +5V.

Gruß,
Henrik

von holger (Gast)


Lesenswert?

Eigentlich sieht alles gut aus. Ist PD2 auf Eingang gesetzt?

von holger (Gast)


Lesenswert?

Erst lesen dann schreiben;)

The Receiver will override normal port
operation for the RxDn pin when enabled.

Vergiss meine Frage.

Allerdings sieht es dann fast so aus als
ob der Portpin tot ist.

von Henrik (Gast)


Lesenswert?

Ok, dann wird jetzt der Lötkolben geschwungen....bzw. Morgen. Habe eben 
Ersatz bestellt.
Nochmal Danke an alle für eure Antworten.
Werde nach Tausch des Chips das Ergebnis posten... Freu mich jetzt schon 
aufs TQFP löten...
Bis dahin....

Gruß,
Henrik

von Werner B. (werner-b)


Lesenswert?

Vielleicht ist ja nur der MAX hinüber; oder du hat einen Kurzschluss auf 
einen ander Pin.
Erst einmal mit einem Oskar vor und hinter dem Pegelwandler prüfen ob 
überhaupt etwas ankommt.

von Andreas V. (tico)


Lesenswert?

Henrik schrieb:
> while( (!(UCSR1A & (1<<RXC1))) || (LSRTimeOut!=0) )
>       {//Timeout
>       _delay_ms(10);
>       LSRTimeOut--;
>       }
>
>
>     //war es ein Timeout?
>     if (LSRTimeOut==0)
>       {
>       return FALSE;

Ähm, ja, schau doch bitte nochmal genau hin. Wenn ich nicht blind bin, 
läuft diese while-Schleife immer solange, bis LSRTimeOut==0 ist. Und 
dann lieferst Du false zurück, ganz egal, ob da zwischendurch was 
empfangen wurde, oder nicht.

Gruss
Andreas

von Sebastian (Gast)


Lesenswert?

das sehe ich auch so:

entweder: while (!0 || ....) => !0 ist true, also wird gleich in die 
Schleife gegangen.

oder: while (!1 || LSRTimeOut!=0) => !1 ist fals, also wird der zweite 
teil der oder-verknüpfung analysiert, da ist der LSRTimer aber noch >0 
=> x!=0 wird als true ausgewertet => while schleife wird ausgeführt...

ergo while wird IMMER ausgeführt, bis LSRTimeOut null ist.

Oder hab ich da jetzt einen denkfehler?

von Henrik (Gast)


Lesenswert?

Hallo Andreas, Hallo Sebastian,
möchte mich mal so ausdrücken:
ARGLÄRGS! Da guckste Stundenlang auf den kram und siehst die olle 
Logikfalle nicht!!!

Da sach ich tausend Dank, Männer!

Sowas passiert, wenn man 'Knüppel aus dem Sack'- Logig wie:
'Entweder was empfangen OOOODEEERRR Timeout' einfach blind in den Code 
hackt... ich Idiot.


Das Leben ist wieder schön mit der korrekten logischen Verknüpfung.
Richtig muss es heißen:
1
while( (!(UCSR1A & (1<<RXC1))) && (LSRTimeOut!=0) )


Und kaum macht man's richtig, schon geht's!

... und ich hatte beinahe schon den Lötkolben inner Hand.

Verneige mich!

Gruß,
Henrik

von Sebastian (Gast)


Lesenswert?

;)

Wenn das Leben bloß immer so einfach wär... :)
So long, viel Spaß mit deiner UART!

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.