Forum: Mikrocontroller und Digitale Elektronik UART Kommunikationsproblem


von RichieRich (Gast)


Lesenswert?

Hallo,

ich versuche zwei Mikrocontroller (Atmega32 mit 8 MHz und Atmega 169 an 
einem AVR Butterfly mit 32kHz RC oscillator) zu verbinden und nutze 
dabei ein einfaches Testprogramm.

Aber es funktioniert einfach nicht, auch wenn ich TX messe und dabei 
eine "1" sende, sehe ich keine digitale 1.

Vielleicht hatte jemand schon ein ähnliches Prolem und könnte mir da 
weiterhelfen, ich wäre sehr dankbar!



Transceiver Code:
1
#define FOSC 32000        // Clock Speed
2
#define BAUD 9600
3
#define MYUBRR FOSC/16/BAUD-1
4
5
#include <avr/io.h>
6
#include <util/delay.h>
7
8
9
10
void USART_Init(unsigned int ubrr)
11
{
12
  /* Set baud rate */
13
  UBRRH = (unsigned char)(ubrr >> 8);
14
  UBRRL = (unsigned char)ubrr;
15
16
  /* Enable receiver and transmitter */
17
  UCSRB = (1 << RXEN) | (1 << TXEN);
18
19
  /* Set frame format: 8data, 1stop bit */
20
  UCSRC = (3 << UCSZ0);
21
}
22
23
24
void USART_Transmit(unsigned char data)
25
{
26
  /* Wait for empty transmit buffer */
27
  while ( !( UCSRA & (1<<UDRE)) )
28
  ;
29
  /* Put data into buffer, sends the data */
30
  UDR = data;
31
}
32
33
34
35
void main(void)
36
{
37
  USART_Init(MYUBRR);
38
39
  while(1)
40
  {
41
    for(int i=0; i<10; ++i)
42
    {
43
      _delay_ms(100);
44
    }
45
      USART_Transmit("1");
46
  }
47
}




Receiver Code:
1
#include <avr\io.h>
2
#include <util/delay.h>
3
4
#define BAUDRATE 9600 
5
#define F_CPU 8000000
6
7
8
void uart_init()
9
{
10
    uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUDRATE) - 1);
11
 
12
    UBRRH = (uint8_t)(ubrr >> 8);
13
    UBRRL = (uint8_t)ubrr;
14
 
15
    // UART Receiver und Transmitter anschalten 
16
    // Data mode 8N1, asynchron 
17
    UCSRB = (1 << RXEN) | (1 << TXEN);
18
    UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
19
}
20
21
22
void USART_Transmit(unsigned char data)
23
{
24
  /* Wait for empty transmit buffer */
25
  while ( !( UCSRA & (1<<UDRE)) );
26
27
  /* Put data into buffer, sends the data */
28
  UDR = data;
29
}
30
31
32
unsigned char USART_Receive(void)
33
{
34
  /* Wait for data to be received */
35
  if( UCSRA & (1<<RXC) )
36
    return UDR;
37
38
  else
39
    return 0;
40
}
41
42
43
44
void main(void)
45
{
46
  uart_init();
47
  DDRD = (1 << PB5) | (1 << PB6);
48
49
  while(1) 
50
  {
51
    unsigned char data = USART_Receive();
52
53
    if(data)
54
    {
55
      PORTD ^= (1 << PB5) | (1 << PB6); // LED toggle
56
    }
57
  }
58
}


Thanks!

von Stefan E. (sternst)


Lesenswert?

1
#define FOSC 32000        // Clock Speed
2
#define BAUD 9600
3
#define MYUBRR FOSC/16/BAUD-1

Du willst also in UBRR einen negativen Wert schreiben.
Das ist ja auch mal ein toller Trick.

von ... (Gast)


Lesenswert?

Ein Word ist nie negativ. Teilen tut's immer.

von Stefan E. (sternst)


Lesenswert?

... schrieb:
> Ein Word ist nie negativ. Teilen tut's immer.

Blödsinn. Ob ein Word negativ ist oder nicht, ist nur eine Frage wie man 
den Wert darin interpretiert. Und was meinst du eigentlich mit "Teilen 
tut's immer"?

Auf jeden Fall aber ergibt die Berechnung oben keinen UBRR Wert, der 
auch nur ansatzweise für 9600 Baud zu gebrauchen wäre. Mit einem 
Systemtakt von 32 kHz lassen sich 9600 Baud höchstens durch Zauberei 
erzeugen.

von spess53 (Gast)


Lesenswert?

Hi

Wie kommst du eigentlich darauf, das der Butterfly mit 32kHz läuft. Das 
ist lediglich der Quartz für den RTC.

MfG Spess

von Otto (Gast)


Lesenswert?

auf jeden Fall wird das mit:

#define FOSC 32000        // Clock Speed

nichts.....

von RichieRich (Gast)


Lesenswert?

Vielen Dank für den Hinweis mit dem UBRR Register!

Jetzt habe ich den internen Oszillator auf 6 MHz umgestellt mit der 
größten Einschwingzeit. Und sende alle 100ms eine "5" --> 101, aber 
irgendwie sieht das Signal trotzdem nicht wie gewünscht aus.

Könnte der USART defekt sein?

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

... falls jemand sich das Signal anschauen möchte, es ist im Anhang.

von Andreas V. (tico)


Lesenswert?

RichieRich schrieb:
> Jetzt habe ich den internen Oszillator auf 6 MHz umgestellt mit der

Das glaube ich nicht.
Man kann den internen RC beim ATmega32 nämlich nur auf 1,2,4 oder 8 MHz 
einstellen.

von RichieRich (Gast)


Lesenswert?

Das ist ein ATMega169 an einem AVR Butterfly.

von Christopher G. (cbg)


Lesenswert?

RichieRich schrieb:
> ...
> void USART_Transmit(unsigned char data) {
>  ...
> }
> ...
> void main(void) {
> ...
>       USART_Transmit("1");
> ...
> }
Denke zwar nicht, dass es daran liegt aber genau genommen ist 
USART_Transmit("1"); kein gültiger Aufruf für deine Funktion, 
USART_Transmit('1'); wäre hingegen korrekt.

von RichieRich (Gast)


Lesenswert?

ATmega169 ist der Sender und ATmega32 empfängt die Daten.

von Amir B. (sticky)


Lesenswert?

Vielleicht hilft dir die Checkliste weiter?
http://www.mikrocontroller.net/articles/AVR_Checkliste

von Andreas V. (tico)


Lesenswert?

RichieRich schrieb:
> Das ist ein ATMega169 an einem AVR Butterfly.

Wenn Du das Butterfly nicht umgebaut hast, verwendet es entweder den 
externen 32,768kHz Quarz, oder den internen RC vom ATmega169, der mit 8 
MHz arbeitet und per Fuse auf 1 MHz geteilt werden kann.
Wo Du 6 MHz herhaben willst, ist mir schleierhaft.

von RichieRich (Gast)


Lesenswert?

@Andreas Vogt: Ja es stimmt es arbeitet mit 8 MHz.

Ich habe jetz auch versucht anstatt "1", eine '1' zu senden, klappt 
trotzdem nicht. Fuse bits & Co. scheinen richtig zu sein, also keine 
Ahnung wo der Fehler sein könnte.

Übrigens ich habe gemerkt, dass im AVR Studio für AtMega169 device, 
rechts wo die Ganze Portübersicht ist USART0 bzw. UDR0 anstatt USART 
bzw. UDR verwendet wird. Einen UDR0 konnte ich auch im Datasheet nicht 
finden.
Dabei benutze ich die letzte Version von AVR Studio, ist es ein Programm 
bug?

von Karl H. (kbuchegg)


Lesenswert?

RichieRich schrieb:

> Ich habe jetz auch versucht anstatt "1", eine '1' zu senden, klappt
> trotzdem nicht. Fuse bits & Co. scheinen richtig zu sein, also keine
> Ahnung wo der Fehler sein könnte.

Dann fang an, systematisch an die Fehlersuche ranzugehen
Frage 1:
Wer verbockts. Der Sender oder der Empfänger?

Da man das keinem der Prozessoren ansehen kann, musst du mal einen der 
beiden durch einen anderen Computer austauschen von dem du 100% weißt, 
das er seine serielle Schnittstelle richtig bedient.

Tausche als mal den Empfänger gegen einen PC aus.

Der Sender soll "1" oder '1' an den PC senden (auf dem natürlich ein 
entsprechendes Terminal-Programm läuft). Taucht dort das Gewünschte auf? 
Wenn ja, dann wird wohl dein Sender richtig senden aber der Empfänger 
empfängt was Falsches.
Wenn nein ... jetzt sollte das Spielchen schon klar sein, wies weiter 
geht.

von RichieRich (Gast)


Lesenswert?

@ Karl heinz Buchegger: Leider habe ich keinen RS232 Kabel hier um es an 
dem PC auszuprobieren.

@Christopher G.: Du hattest Recht mit den Klammern. Durch einen Aufruf 
mit "1", kommt nur Mist raus. Dagegen wenn ich '1' sende, sieht es schon 
besser aus.

Aber ich habe jetzt einige Messungen durchgeführt, das Ergebnis sieht 
viel besser aus und dennoch, schein mir das Signal "unsauber" zu sein, 
ob es an der Genauigkeit des Oszis liegt ?!


Ein Problem war, dass in den Makros, die Taktfrequenz und die Baudrate 
nicht als unsigned long (UL) definiert, deshalb gab es einen Überlauf.

Im folgenden habe ich das Signal für '0', '1', '2', '3', '4' und '5' 
fotografiert. Die Baudrate liegt auf den Photos bei 9600 Bit/s --> 104,2 
us pro ein einzelnes Bit.

Aber trotzdem erkenne ich keine sauberen Start, Stopbits und Datenbits 
oder sieht es jemand anders?

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

USART_Transmit('0');

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

USART_Transmit('1');

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

USART_Transmit('2');

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

USART_Transmit('3');

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

USART_Transmit('4');

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

USART_Transmit('5');

von RichieRich (Gast)


Angehängte Dateien:

Lesenswert?

Und so soll es aussehen ...

von Stefan E. (sternst)


Lesenswert?

Deine Bitmuster sehen vollkommen ok aus. Du misst anscheinend hinter dem 
Pegelwandler, daher ist es invertiert. Wo siehst du da einen 
entscheidenden Unterschied zu dem "so soll es aussehen"?

PS: Baudrate habe ich jetzt nicht kontrolliert, weil ich nicht sehe was 
da jetzt genau die Zeitbasis ist.

von RichieRich (Gast)


Lesenswert?

Die Zeitbasis ist 250 us.

von Stefan E. (sternst)


Lesenswert?

RichieRich schrieb:
> Die Zeitbasis ist 250 us.

Also ca. 850 µs für 9 Bit = ca 10600 Baud.

Du wirst den internen Oszillator kalibrieren müssen, sonst wird das 
nichts.

von RichieRich (Gast)


Lesenswert?

Ja das mit der Kalibration habe ich mir auch gedacht, dass der interne 
Oszilllator wohl zu ungenau ist.

Vielen Dank für all die Hinweise, am Ende läufts zwar nicht wie 
gewünscht, dafür aber einiges auf dem Weg hin gelernt.

von rene (Gast)


Lesenswert?

Ich habe eine Kalibration des Mega 169 Butterfly in 60 zeilen ASM.

http://www.ibrtses.com/embedded/avrosccal.html

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.