Atmega324 UART: Senden vom PC zum µC klappt nicht

OP #7583100
Lesenswert?

Guten Morgen zusammen!

Mein Aufbau sieht wie folgt aus: Ich habe einen Atmega324 an dem ein Max232 hängt. Verbunden sind Rx, Tx (beide gekreuzt) und GND. Der Atmega hat einen externen Quarz mit 10Mhz und die UART Einstellungen habe ich aus dem Tutorial und Datenblatt übernommen (Baud 9600 8N2). Aktiviert ist ferner, dass beim Empfang von Zeichen ein Interrupt ausgelöst wird.

Am PC verwende ich HTerm.

Wenn ich Zeichen vom µC zum PC sende, klappt das einwandfrei. Das Senden vom PC zum µC hingegen klappt nicht - es wird kein Interrupt ausgelöst.

Ich habe dann einmal eine Brücke zwischen Tx und Rx vom Max232 gesetzt. Dann habe ich im HTerm die gesendeten Zeichen gesehen. Als nächstes habe ich Tx und Rx vom µC gebrückt und daraufhin wurde der Interrupt ausgelöst.

Prinzipiell scheint das Empfangen vom µC also zu funktionieren. Aber wenn ich über HTerm sende, kommt einfach nichts im µC an. Die Kabel habe ich natürlich auch schon mal gewechselt.

Gibts vielleicht irgendwelche Ideen, woran das liegen könnte?

Moderator (Firma: Titel) Persönliche Seite #7583104
Lesenswert?

Troll A. schrieb:

Gibts vielleicht irgendwelche Ideen, woran das liegen könnte?

Weil du das ja alles sicher schon mit dem Oszilloskop kontrolliert und dort auch die beiden Timings (Baudrate) verglichen hast (das sollte man bei seriellen Schnittstellen generell), liegt es mit höchster mit höchster Wahrscheinlichkeit am Programm.

es wird kein Interrupt ausgelöst.

Wie sieht es mit Polling aus, wenn schon der Interrupt nicht kommt?

OP #7583115
Lesenswert?

Rahul D. schrieb:

Der Fehler ist in Zeile 42 deines geheimen Quellcodes.

Ich habe alles in mehreren Dateien gesplittet, aber hier mal die wichtigsten Funktionen:

Init

1
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
2
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
3
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
4

5
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
6
#error BAUD not valid
7
#endif
8

9
void uart_init()
10
{
11
  UBRR0H = UBRR_VAL >> 8;;
12
  UBRR0L = UBRR_VAL & 0xFF;
13
  
14
  UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
15
  
16
  //8data 2stop bit
17
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
18
}

Interrupt

1
volatile uint8_t uart_string_complete = 0;
2
volatile uint8_t uart_string_count = 0;
3
volatile char uart_string[UART_MAX_STRING_LENGTH + 1] = "";
4

5
ISR(USART0_RX_vect)
6
{
7
  unsigned char nextChar;
8

9
  nextChar = UDR0;
10
    
11
  //Append new char only if string is not complete, else the main loop has to process the string first
12
  if(uart_string_complete == 0) 
13
  {
14
    uint8_t finishString = 0;
15
    
16
    if(nextChar == '\n' || nextChar == '\r' || uart_string_count == UART_MAX_STRING_LENGTH) 
17
    {
18
      finishString = 1;
19
    }
20
    else
21
    {
22
      uart_string[uart_string_count] = nextChar;
23
      uart_string_count++;      
24
      
25
      if(nextChar == ';')
26
        finishString = 1;
27
    }
28
      
29
    if(finishString == 1)
30
    {
31
      uart_string[uart_string_count] = '\0';
32
      uart_string_count = 0;
33
      uart_string_complete = 1;
34
    }
35
  }
36
}

Selbst wenn ich bei jedem Interrupt uart_string_complete auf 1 setzte, erhalte ich nichts.

Lothar M. schrieb:

Weil du das ja alles sicher schon mit dem Oszilloskop kontrolliert

Habe ich leider nicht zur Verfügung...

Lothar M. schrieb:

Wie sieht es mit Polling aus, wenn schon der Interrupt nicht kommt?

Schlecht. Mit

1
if ( UCSR0A & (1<<RXC0) )
2
    {
3
      // Zeichen wurde empfangen, jetzt abholen
4
      uint8_t c;
5
      
6
      while (!(UCSR0A & (1<<RXC0)));
7
      c = UDR0;
8
      
9
          lcd_gotoxy(0,1);
10
          lcd_putc(c);
11
    }

in der Main Loop bekomme ich leider auch keine Ausgabe.

Ich verstehe es irgendwie nicht, da ja das Senden vom µC zum PC einwandfrei klappt...

Moderator (Firma: Titel) Persönliche Seite #7583154
Lesenswert?

Troll A. schrieb:

Ich habe einen Atmega324 an dem ein Max232 hängt.

Dann musst du dessen Funktion wenigstens mal statisch kontrolliert? 9V-Batterie am RS232-RX-Eingang mal so und mal andersrum gepolt und dann am RX-Ausgang des MAX gemessen, welche Pegel rauskommen?

Ich habe dann einmal eine Brücke zwischen Tx und Rx vom Max232 gesetzt.

Auf welcher Seite? Auf der RS232 Seite oder der TTL-Seite?

Als nächstes habe ich Tx und Rx vom µC gebrückt und daraufhin wurde der Interrupt ausgelöst.

Von wo aus wurde da gesendet? Der MAX war dabei noch angeschlossen?

Troll A. schrieb:

Lothar M. schrieb:

Weil du das ja alles sicher schon mit dem Oszilloskop kontrolliert

Habe ich leider nicht zur Verfügung...

Würde ich ändern. Serielle Schnittstellen bekommt man nur mit einem "Deserializer" wie einem Oszi oder einem Logicanalyzer sicher in den Griff. Ein Oszi ist besser, weil man damit auch die Signalqualität (Pegel, Flanken) bewerten kann.

Denn das Debuggen von seriellen Schnittstellen ohne Oszi ist wie Autofahren nach Gehör: man merkt Probleme immer erst dann, wenn es schiefgegangen ist.

(Firma: L-E-A) #7583161
Lesenswert?

Troll A. schrieb:

Das Senden vom PC zum µC hingegen klappt nicht - es wird kein Interrupt ausgelöst.

Du bist Dir sicher, dass der PC sendet? Brücke doch mal versuchsweise am PC TxD und RxD, dann sollte das Terminalprogramm ein Echo empfangen.

Auch schadet es nichts, die Handshakeleitungen am PC zu brücken. RTS mit CTS verbinden sowie DCD mit DSR und DTR verbinden.

Grüßle, Volker

(Firma: L-E-A) #7583181
Lesenswert?

Harald K. schrieb:

Volker B. schrieb:

Du bist Dir sicher, dass der PC sendet? Brücke doch mal versuchsweise am PC TxD und RxD, dann sollte das Terminalprogramm ein Echo empfangen.

Hat er wohl gemacht:

Troll A. schrieb:

Ich habe dann einmal eine Brücke zwischen Tx und Rx vom Max232 gesetzt. Dann habe ich im HTerm die gesendeten Zeichen gesehen.

Sorry, das hab' ich überlesen. Dann hilft wohl nur noch ein Oszilloskop.

Nachtrag: Die Berechnung der Baudrate ist korrekt? Nicht dass der Compiler dafür 16-Bit-Zahlen verwendet.

Grüßle, Volker

Beitrag #7583183 wurde von einem Moderator gelöscht.
#7583193
Lesenswert?

Ich habe dann einmal eine Brücke zwischen Tx und Rx vom Max232 gesetzt. Dann habe ich im HTerm die gesendeten Zeichen gesehen. Als nächstes habe ich Tx und Rx vom µC gebrückt und daraufhin wurde der Interrupt ausgelöst.

Also für mich folgt daraus, dass die Verbindung vom MAX232 zum ATmega324.PD0 nicht in Ordnung ist.

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