Forum: Mikrocontroller und Digitale Elektronik Uart empfängt nur kryptische Zeichen - Fehler in der Programmierung


von Jens (Gast)


Lesenswert?

Hallo, ich habe ein Problem mit UART. Das Problem liegt aber mehr an der 
Programmierung. Zunächst hatte ich eine .c file, wo ich alle funktionen 
drinnen hatte. Jetzt wollte ich es so aufbauen, dass ich im Projekt 
einen Ordner mit einer uart.h und uart.c file generiere und im projekt 
selber die main.c und eine defines.h die übergreifend ist
Projekt:
 -uart:
    -uart.h
    -uart.c
  main.c
  defines.h


main.c:
1
#include "defines.h"
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include "uart/uart.h"
5
6
7
int main(void)
8
{
9
    uart_init(MYUBRR);
10
    while (1) 
11
    {
12
    uart_sendString("nice :) ");
13
    _delay_ms(1000);
14
    }
15
}

uart.c
1
#include "../defines.h"
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include "uart.h"
5
6
7
8
9
void uart_init(unsigned int ubrr)
10
{  
11
  /* Set baud rate */
12
  //UBRR0H = UBRR_VAL >> 8;
13
  //UBRR0L = UBRR_VAL & 0xFF;
14
15
  /* Enable receiver and transmitter */
16
  UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
17
18
  /* Set frame format: 8data, 2stop bit */
19
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
20
}
21
22
/* Simple methods to make UART read and transmit more readble - Extremely unnecessary*/
23
void uart_transmit( unsigned char data )
24
{
25
  while(!(UCSR0A & (1<<UDRE0)));
26
  UDR0 = data;
27
}
28
29
30
unsigned char uart_receive( void )
31
{
32
  return UDR0;
33
}
34
35
void uart_sendString(char *StringPtr)
36
{
37
  
38
  while(*StringPtr != 0x00)
39
  {
40
    uart_transmit(*StringPtr);
41
    StringPtr++;
42
  }
43
44
}

uart.h
1
#ifndef UART_H_
2
#define UART_H_
3
4
void uart_init( unsigned int ubrr);
5
void uart_interruptOn(void);
6
void uart_transmit( unsigned char data );
7
unsigned char uart_receive( void );
8
void uart_sendString(char *StringPtr);
9
10
#endif /* UART_H_ */

defines.h
1
#ifndef DEFINES_H_
2
#define DEFINES_H_
3
4
5
#define F_CPU 16000000UL
6
7
8
/* UART Serial defines */
9
#define BAUD 9600UL
10
#define MYUBRR F_CPU/16/BAUD-1
11
12
/* Berechnung UART */
13
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
14
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
15
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
16
17
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
18
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
19
#endif
20
21
22
23
#endif /* DEFINES_H_ */

Wenn ich das Programm so laufen lasse, kommen allerdings nur kryptische 
Zeichen an. Das ist aber erst, nachdem ich es aufgesplittet habe. Wie 
gesagt, als alles in der main.c drinn war, hat es funktioniert. Wie kann 
ich den parameter "nice :) " übergeben, damit dieser richtig empfangen 
wird?

Jens

von Karl M. (Gast)


Lesenswert?

Hallo Jens,

Der USART ist nicht initialisiert, damit ist den Problem klar. Im 
Empfangsfall fehlt das Prüfen, ob ein Zeichen überhaupt empfangen wurde.

von Theor (Gast)


Lesenswert?

Vergleiche nochmal diese Berechnungen:

#define MYUBRR F_CPU/16/BAUD-1

/* Berechnung UART */
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden

Die beiden Ausdrücke ergeben nicht den selben Wert.

von Theor (Gast)


Lesenswert?

Karl M. schrieb:
> Hallo Jens,
>
> Der USART ist nicht initialisiert, damit ist den Problem klar.

Richtig.

  //UBRR0H = UBRR_VAL >> 8;
  //UBRR0L = UBRR_VAL & 0xFF;

ist unwirksam, weil auskommentiert. Und UBRR_VAL muss durch ubrr ersetzt 
werden.

Das kommt davon, wenn man so früh am Sonntag programmiert. Hast Du denn 
schon Kaffee getrunken?

> Im
> Empfangsfall fehlt das Prüfen, ob ein Zeichen überhaupt empfangen wurde.

Ja. Daran würde ich noch arbeiten.

von Carl D. (jcw2)


Lesenswert?

Nach Reset und ohne weitere Initialisierung des BRR sendet die UART mit 
1/16 der Taktfrequenz.
Also bis zu 1,25MBd bei 20MHz Quarz ohne DIV8.
Vielleicht kann der empfangende Rechner ja sogar so schnell mitlesen.

von Jens (Gast)


Lesenswert?

Theor schrieb:
> Karl M. schrieb:
>> Hallo Jens,
>>
>> Der USART ist nicht initialisiert, damit ist den Problem klar.
>
> Richtig.
>
>   //UBRR0H = UBRR_VAL >> 8;
>   //UBRR0L = UBRR_VAL & 0xFF;
>
> ist unwirksam, weil auskommentiert.

mhh stimmt, dass hatte ich auskommentiert, da UBRR_VAL nicht bekannt 
war, bis ich die Berechnung der Baudrate ins defines.h gepackt habe. 
Wollte es eigentlich in der main.c lassen. Dann habe ich es vergessen 
wieder einzukommentieren.


Theor schrieb:
> Und UBRR_VAL muss durch ubrr ersetzt
> werden.

Das ist auf der TutorialSeite aber anders erklärt. Also dort ist es so, 
wie ich es gemacht habe (bzw. ich habe es so gemacht wie es dort ist).
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART


Theor schrieb:
>> Im
>> Empfangsfall fehlt das Prüfen, ob ein Zeichen überhaupt empfangen wurde.
>
> Ja. Daran würde ich noch arbeiten.

Das käme jetzt als nächstes.

Danke schon einmal.

von A. S. (Gast)


Lesenswert?

Theor schrieb:
> Die beiden Ausdrücke ergeben nicht den selben Wert.

Abgesehen vom gerundeten LSB: ist da ein Überlauf, oder was ist anders?

von Stromverdichter (Gast)


Lesenswert?

willst du wirklich 8n2 oder doch lieber 8n1

Jens schrieb:
> /* Set frame format: 8data, 2stop bit */
>   UCSR0C = (1<<USBS0)|(3<<UCSZ00);

von Stefan F. (Gast)


Lesenswert?

Es ist immer wieder das Selbe.

Tut euch einen Gefallen und verwendet die
https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html
anstatt die Baudraten-Register selbst zu berechnen.

[Mod: Link korrigiert]

Beitrag #5601571 wurde von einem Moderator gelöscht.
Beitrag #5601573 wurde von einem Moderator gelöscht.
Beitrag #5601579 wurde von einem Moderator gelöscht.
von Dirk B. (Gast)


Lesenswert?

Jens schrieb:
>   UCSR0C = (1<<USBS0)|(3<<UCSZ00);
schreibt je nach uC in UBRRH (Resultat bei UBRRL=0: 279 Baud)
UCSR0C = (1<<URSEL)|(1<<USBS0)|(3<<UCSZ00)
könnte da besser funktionieren.

von Theor (Gast)


Lesenswert?

@ Jens
@ Achim

Achim S. schrieb:
> Theor schrieb:
>> Die beiden Ausdrücke ergeben nicht den selben Wert.
>
> Abgesehen vom gerundeten LSB: ist da ein Überlauf, oder was ist anders?

Tja. Da hatte ich wohl selbst noch nicht genug Kaffee. :-)

Ich habe das einfach mathematisch betrachtet anstatt das 
Trunkierungsproblem bei float nach int Konvertierungen mit zu 
berücksichtigen, dass mir natürlich bekannt ist.

Mein Fehler. Tut mir leid, wenn ich Verwirrung gestiftet habe.

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.