Forum: Mikrocontroller und Digitale Elektronik Atmega324 UART: Senden vom PC zum µC klappt nicht


von Troll A. (trollator)


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?

von Rahul D. (rahul)


Lesenswert?

Der Fehler ist in Zeile 42 deines geheimen Quellcodes.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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?

: Bearbeitet durch Moderator
von Troll A. (trollator)


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...

von Εrnst B. (ernst)


Lesenswert?

Global hast du die Interrupts schon enabled?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Martin H. (horo)


Lesenswert?

Lothar M. schrieb:
> oder einem Logicanalyzer

Für kleines Geld gibt es die "Salae-Kompatiblen", als SW empfehle ich 
sigrok, das erlaubt intensives Analysieren serieller Kommunikation. 
Verfügbar auch für Windows.

https://sigrok.org

von Volker B. (Firma: L-E-A) (vobs)


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

von Oliver S. (oliverso)


Lesenswert?

Troll A. schrieb:
> UBRR0H = UBRR_VAL >> 8;;
> UBRR0L = UBRR_VAL & 0xFF;

Hat zwar nichts mit deinem eigentlichen Problem zu tun, daher nur so als 
Hinweis: die Verwaltung der 8-Bit-Register bei einem 16-Bit-Register 
macht der Compiler für dich.
1
UBRR0 = UBRR_VAL;

Oliver

von Harald K. (kirnbichler)


Lesenswert?

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.

von Volker B. (Firma: L-E-A) (vobs)


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

: Bearbeitet durch User
Beitrag #7583183 wurde vom Autor gelöscht.
von S. L. (sldt)


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.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

S. L. schrieb:

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

Das ließe sich ja auch einfach prüfen: An der MCU RxD und TxD brücken 
und die MCU im Reset halten. Dann sollte der PC sein Echo empfangen.

Grüßle,
Volker

: Bearbeitet durch User
von Hannes (taurus16)


Lesenswert?

Bau mal ein

sei();

als letzte Zeile in deine Uart-Init.

von Mario P. (mario_71950c)


Lesenswert?

Wie sind die Schnittstelleneinstellungen von HTerm?
Arbeitet HTerm mit 2 Stoppbits (Baud 9600 8N2)?

: Bearbeitet durch User
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.