UART mit ATMega644 liest falsche Daten ein

Gast #1627120
Lesenswert?

Hallo,
ich habe folgendes Minimalbeispiel gemacht um nur den UART des ATMega644 
zu testen. Der Interrupt wird ausgelöst, aber er empfängt kein Byte 170. 
Mit einem ATMega32 in der identischen Schaltung funktioniert es 
einwandfrei. Der Logicanalyzer bestätigt auch dass Bytes 170 ankommen, 
aber der ATMega644 erkennt es nicht. Die Frage ist natürlich wo der Code 
noch falsch ist. Was habe ich übersehn? Bin schon drei Tage dabei das 
irgendwie zum laufen zu kriegen, aber ich komm einfach nicht dahinter.
1
#include <avr/interrupt.h>
2
#define F_CPU 14745600L 
3
#include <util/delay.h>
4
#define BAUD 115200L
5

6
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)      //clever runde
7
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //reale Baudrate
8

9
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)      //Fehler in Promille
10

11
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
12
#error Systematischer Fehler in der Baudrate größer 1% und damit zu hoch!
13
#endif
14

15
#define HOME_ADDR 2
16

17
volatile uint8_t FlagProcessRXByte = 0;
18
volatile uint8_t RXB;
19

20

21
ISR (USART0_RX_vect) {
22
  RXB = UDR0;
23
  FlagProcessRXByte = 1;
24
  PORTA ^= (1<< PA3);
25
}
26

27
void ProcessRXByte(void){
28
  if (RXB == 170) PORTA ^= (1<< PA4);
29
}
30

31

32

33
int main(void)
34
{
35
  _delay_ms(300);
36
  // Ausgänge definieren
37
  DDRA = (1<<PA2) | (1<<PA3) | (1<<PA4); //LED's User-Taste1 Home, Enter
38
  DDRC = (1<<PC2) | (1<<PC4);  // LED Usr-Taste3, LED Usr-Taste2
39
  DDRD = (1<<PD1) | (1<<PD3) | (1<<PD4) | (1<<PD7); //TX an MAX, externer Signalgeber, DE/RE von MAX, OC2 für internen Summer
40
  //Pullups der Tasterausgänge aktivieren
41
  PORTA = (1<<PA1) | (1<<PA5) | (1<<PA6);  // Enter, Usr1, Home
42
  PORTB = (1<<PB1);
43
  PORTC = (1<<PC1) | (1<<PC3);  // Usr3, Usr2
44

45
  UBRR0H = UBRR_VAL >> 8;
46
  UBRR0L = UBRR_VAL & 0xFF;
47
   
48
  UCSR0A = 0;
49
  UCSR0B = (1<<RXEN0)|(1<<TXEN0)| (1 << RXCIE0);      //UART TX einschalten
50
  UCSR0C = (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);      //8 data, 2 stop bits
51

52
  _delay_ms(100);
53
  sei();  
54
  
55
  while (1)
56
  {
57
    if (FlagProcessRXByte == 1){
58
      FlagProcessRXByte = 0;
59
      ProcessRXByte();   
60
    }
61
  }
62

63
  return 0;                     
64
}
#1627135
Lesenswert?

Tobias schrieb:
> Mit einem ATMega32 in der identischen Schaltung funktioniert es
> einwandfrei.

Ich überfliege gleich mal den Code aber das riecht schon nach:
a) falscher Quarz oder
b) richtiger Quarz aber falsche Fusebit Einstellungen

Edit: Code schaut ansich in Ordnung aus. Die Delays sind zwar sinnlos 
und die Aufgabe von ProcessRXByte() kann man gleich in der RXC0 ISR 
erledigen aber Fehler konnte ich jetzt keinen entdecken. Ich penn aber 
auch gleich ein :)
#1628099
Lesenswert?

Hast du eine Möglichkeit, dir anzeigen zu lassen, was du anstelle der 
0xAA empfängst?

Hast du ausprobiert, was passiert, wenn du vom µC weg sendest. Empfängt 
ein angeschlossenes Terminal dann richtig?
Wenn nicht, wäre das ein Indiz dafür, dass mit der Baudrate/Taktfrequenz 
noch irgendetwas nicht stimmt.
Gast #1628486
Lesenswert?

nein, ich kompilier natürlich schon extra für den 644.

Das empfangene Byte ansehen, sowie senden ist in der Schaltung beides 
ziemlich aufwendig. Wird also etwas dauern bis ich da mehr sagen kann, 
wenn es etwas gibt was ich vorher ausprobieren kann würde ich das gerne 
tun.
Gast #1642393
Lesenswert?

so, nachdem ich jetzt nochmal Zeit hatte ein paar Sachen auszuprobieren:

Das Problem ist ja dass das Byte 170 nicht erkannt wird.
Bei einem Testprogramm das nur das Byte 170 sendet, kommt das bei einem 
Empfänger auch so an. Sprich am Takt von µC/Bus kann es nicht liegen.
Wenn ich nun das Byte 170 an den ATMega644 sende und dieser sendet das 
empfangene Byte zurück, dann kommt 192 an.

In Binar:
170:  10101010
192:  11000000

also auch nicht invertiert oder ähnliches. Und es kommt auch konstant 
die 192 zurück.
Gast #1642401
Lesenswert?

Der Kondensator Cmax ist rechter Unsinn. Auch wenn diese Hardware in der 
anderen Schaltung funktioniert, so ist sie doch recht schrottig.

Für den Fall, daß der Ausgang des Max hochohmig ist, ist kein Pegel für 
den RX-Eingang definiert. Häng lieber einen Pull-Up-Widerstand rein.
Gast #1642625
Lesenswert?

an den beiden Pins hängen bloss 2 "Debug"-LEDs dran.

Cmax ist zugegebenermaßen unkonventionell, hat aber Probleme gelöst. 
Ohne den hatte ich des öfteren Resets des µC und hier im Forum habe ich 
von gleichen Problemen gelesen mit eben diesem Lösungsvorschlag.
Gast #1642638
Lesenswert?

Hi

>Ohne den hatte ich des öfteren Resets des µC und hier im Forum habe ich
>von gleichen Problemen gelesen mit eben diesem Lösungsvorschlag.

Das ist nur ein herumdoktern an Symptomen. Ein passender 
Abblockkondensator am Max ist mit Sicherheit hilfreicher. MAXIM gibt 
einen Wert von 3,1µ an.

MfG Spess
Gast #1642669
Lesenswert?

Hallo,

ein Abblock-Kerko am MAX-IC zwischen VCC und GND direkt am IC ist 
anzuraten (im Schaltplan sehe ich keinen) ...  (Ich nehme meist 100nF.)
Womöglich ist dann Cmax überflüssig. Ich habe bei RS485 bisher noch nie 
irgendeinen Kondensator an RxD gebraucht.

spess53 schrieb:
> MAXIM gibt (für den Abblock-C) einen Wert von 3,1µ an.

Woher hast du diese Information? Im Datenblatt finde ich nichts dazu ...

Ich schalte immer den internen Pull-Up für diesen Pin ein.
Das Einschalten dieses Pull-Ups an RxD beugt Störungen bei offenem 
RxD-Pin vor, wenn der Empfänger im MAX-IC nicht aktiv ist; es hält den 
Pin auf (inaktivem) High-Level.

Tobias schrieb:
> an den beiden Pins hängen bloss 2 "Debug"-LEDs dran.

Hoffentlich mit den notwendigen Vorwiderständen (das wird leider öfter 
fälschlicherweise nicht gemacht), sonst handelt man sich ohne sie wieder 
neue Probleme ein ...
Gast #1643032
Lesenswert?

ich hab jetzt mal Kanal A und B vorm Max ans Oszi angeschlossen und 
voneinander abgezogen. Die Flanken sind schön steil, aber bei z.B. dem 
Byte 170 (binär 10101010) wechselt der Pegel schön von 5V zu -5V wieder 
zu 5V etc, aber mitten im Byte ist er 2 Bits lang auf 0V. Warum...noch 
nicht die geringste Idee.
Dieser 0V Pegel ist auch bei jedem anderem Byte enthalten.
Leider kann ich keinen Screenshot davon machen.

Normal würde ich ja vermuten dass der Sender das "verbricht", allerdings 
funktioniert die Übertragung mit dem ATMega32 ja einwandfrei.

Auch ist dieser 0V Pegel während der Zeit in der keine Übertragung statt 
findet vorhanden. Sollte da normalerweise nicht eine Different von 5V 
oder -5V sein? (Der Sender ist übrigens eine SPS die auch Pullup und 
PullDown Widerstände verwendet.)

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