mikrocontroller.net

Forum: Compiler & IDEs UART Ausgabe


Autor: Michael Kuehn (michael1104)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich hab ein Probelem, ich arbeite gerade dass tutorial durch, und habe 
eine frage zur UART Ausgabe... Ich will testweise einfach nur ein x 
ausgeben. Ich habe den ATMega8 und hab auch schon ins Datenblatt 
geschaut, komme aber nicht weiter..

Hier mein Code
#ifndef F_CPU


#define F_CPU 4000000UL
#endif

#define BAUD 9600UL


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

#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu 
hoch!
#endif

#include <avr/io.h>
#include <stdint.h>


void uart_init()
{
    UCSRB |= (1<<TXEN);
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);

    UBRRH = UBRR_VAL >> 8;
    UBRRL = UBRR_VAL & 0xFF;
}


int main(void)
{
  uart_init();
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 
*/
    {
    }

    UDR = 'x';


}


Vielen Dank schonmal

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte.

Michael Kuehn wrote:
> Hi,
> ich hab ein Probelem, ich arbeite gerade dass tutorial durch, und habe
> eine frage zur UART Ausgabe... Ich will testweise einfach nur ein x
> ausgeben. Ich habe den ATMega8 und hab auch schon ins Datenblatt
> geschaut, komme aber nicht weiter..
>
> Hier mein Code

Vielleicht hülft's, die Frage auch zu stellen ;-)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wo genau ist das Problem?

Du kannst die AVR Checkliste abarbeiten. da steht einiges 
Hilfreiches  zu UART Problemen und mehr drin.

Ich habe bei deinem Code derzeit nur den Verdacht, dass es Probleme mit 
der Taktquelle gibt. Die Definition von F_CPU deutet auf eine externe 
Taktquelle hin, die natürlich 1. vorhanden und richtig angeschlossen 
sein muss und 2. per richtig eingestellte AVR Fuses ggf. zum 
Schwingen gebracht werden muss. Erst dann hat die Angabe F_CPU eine 
Chance im folgenden Quellcode richtig interpretiert zu werden.

In deinem Code wird auch nur ein einzelnes x gesendet. Stelle das doch 
mal auf "Dauerfeuer" um:

int main(void)
{
  uart_init();
  for(;;)
  {
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
    {
    }
    UDR = 'x';
  }
}

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1) In den AVR-Sheets wird UBRRx vor UCSRx gesetzt. Warum änderst du 
dieses Prozedere?

2) Schreibe hier korrekter, klarer und kürzer
UCSRx = ...
anstatt
UCSRx |= ...

3) AFAIK sollte man eine Toleranz von +/- 0.2 % einhalten. Ob dein Prog 
richtig rechnet (sieht zumindest mal so aus), kannst zB hier 
gegenkontrollieren:

http://www.gjlay.de/helferlein/avr-uart-rechner.html

Hier noch ne funktionierende init-Funktion:
#define F_CPU 4000000
#define BAUDRATE 9600
#define U2X_BIT 1

void uart_init(void)
{
    unsigned short ubrr = -.6 + F_CPU/((16L-8*U2X_BIT)*BAUDRATE);

    UBRRH = ubrr>>8;
    UBRRL = ubrr;

    UCSRA = (U2X_BIT << U2X) | (1 << TXC);

    // Enable UART Receiver, Transmitter
    // Data mode 8N1, asynchronous

    UCSRB = (1 << RXEN) | (1 << TXEN);
    UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);

    // Flush Receive Buffer
    do
        UDR;
    while (UCSRA & (1 << RXC));
}

Autor: Michael Kuehn (michael1104)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem ist, dass ich das gesendete Zeichen nicht auf der seriellen 
Schnittstelle empfange, sondern nur kryptischen Muell...
#define F_CPU 3686400


#include <avr/io.h>
#include <stdint.h>
#include <inttypes.h>


void USART_Init()
{
unsigned int baud = 1200;
/* Set baud rate */
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;


UCSRB = (1<<RXEN)|(1<<TXEN);
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

void USART_Transmit()
{



while ( !( UCSRA & (1<<UDRE)) );

UDR = 'x';
}


int main ()
{
  USART_Init();

  for(;;)
  {
  USART_Transmit();
  }
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist falsch:

unsigned int baud = 1200;
/* Set baud rate */
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;

So kannst du die Baudrate nicht setzen. Im Datenblatt ist eine Tabelle, 
in der steht, welche Werte bei welcher Baudrate in die Register UBRRL 
und UBRRH müssen. Und im AVR GCC Tutorial ist eine Formel, die die Werte 
aus der Wunschbaudrate und der Taktrate berechnet und sogar meldet, wenn 
ein zu grosser Baudratenfehler auftreten würde.


UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
                       ^^^^
Warum hast du das dazu genommen? Das erfordert eine andere Einstellung 
im Terminalprogramm auf dem PC (dem Empfänger): 2 Stoppbits!

Im allerersten Posting hattest du #define F_CPU 4000000UL und jetzt hast 
du #define F_CPU 3686400. Hast du inzwischen die externe Taktquelle 
gewechselt (anderer Quarz?). Wenn du eine externe Taktquelle hast 
(welche?), kannst du mal die Fuses auslesen, einen Screenshot machen und 
hier anhängen. Ich möchte nachsehen, ob die Taktquelle richtig 
eingestellt ist.

Autor: Michael Kuehn (michael1104)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So,
das mit den 2 Stoppbits, ist ok, dass habe ich bewusst gewählt und auch 
im Terminalprogramm eingestellt.

Der Takt, wird ja von extern vorgegeben, über einen Quarz der mit 
3,6864MHz läuft...
Wie kann ich die Fuses auslesen? Ich benutze AVRStudio4 und das myavr 
Board

Für 2400baud kann ich die Register so setzen?

UBRRH = 0x50;  //2400
UBRRL = 0x0f;

gemäß Tabelle Datenblatt

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Kuehn wrote:

> UBRRH = 0x50;  //2400
> UBRRL = 0x0f;

Nee. Ich lese im Datenblatt Tabelle 61 den Wert 95. Damit wäre die 
Zeile:

UBRR = 95; // 16-Bit Zugriff dem Compiler überlassen
UBBR = 0x5F; // Alternativ

Oder:

UBRRH = 0; // Selbst 2 8-Bit Zugriffe machen
UBRRL = 95;

Alternativ:

UBRRH = 0; // Selbst 2 8-Bit Zugriffe machen
UBRRL = 0x5F;

> Ich benutze AVRStudio4 und das myavr Board

Die Angabe hilft bereits. Wenn der originale AVR drauf ist, brauchst du 
keine Fuses einzustellen. Das ist dann wohl schon ab Entwickler/Verkauf 
gemacht. Jedenfalls sehe ich keinen Fuses-Einstellschritt in der 
myAVR-Doku.

Autor: Michael Kuehn (michael1104)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für deine Hilfe, es funktioniert...

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. wrote:

> UBRR = 95; // 16-Bit Zugriff dem Compiler überlassen
> UBBR = 0x5F; // Alternativ

räusper

Wie soll das denn gehen???

&UBRRH = 0x40
&UBRRL = 0x29

Fällt was auf...?

Michael Kuehn wrote:
> #define BAUD 9600UL

Michael Kuehn wrote:
> unsigned int baud = 1200;

Michael Kuehn wrote:
> Für 2400baud kann ich die Register so setzen?

Etwas unentschlossen. Steht das Terminal immer noch richtig?
Flusskontrolle aus?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. wrote:

> Stefan B. wrote:
>> UBRR = 95; // 16-Bit Zugriff dem Compiler überlassen
>> UBBR = 0x5F; // Alternativ
>
> *räusper*
>
> Wie soll das denn gehen???
>
> &UBRRH = 0x40
> &UBRRL = 0x29
>
> Fällt was auf...?

Nein auf Anhieb nicht. Habe ich das Makro für den 16-Bit Zugriff auf das 
UBRR IO-Register falsch geschrieben?

ADD: Ah, jetzt ja ;-)

Beim Atmega8 liegen die beiden 8-Bit IO-Register nicht nebeneinander im 
Speicher. Wahrscheinlich habe ich das falsch von anderen IO-Registern 
übertragen (ADC?). Es gibt kein einzelnes UBRR Register. Man muss 
getrennt mit UBRRL und UBRRH arbeiten. Danke, ich glaube das werde ich 
nimmer vergessen, rotwerd ;-)

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. wrote:

> ADD: Ah, jetzt ja ;-)
>
> Beim Atmega8 liegen die beiden 8-Bit IO-Register nicht nebeneinander im
> Speicher. Wahrscheinlich habe ich das falsch von anderen IO-Registern
> übertragen (ADC?). Es gibt kein einzelnes UBRR Register. Man *muss*
> getrennt mit UBRRL und UBRRH arbeiten. Danke, ich glaube das werde ich
> nimmer vergessen, rotwerd ;-)

Ich hab's net ausprobiert, aber eigentlich müsste der Compiler 
warnen/der Linker mackern, daß er UBRR nicht kennt, wenn man diesen 
Zugriff versucht.
Kann mir nämlich kaum vorstellen, daß das Makro in den Headern drinne 
ist (zumindest nicht für ATmega8).

Keine Ahnung, warum Atmel das so seltsam gemacht hat, zudem zusammen mit 
UBSRC als Shadow. Ist wohl ein Silicon-Hack das...

Jepp, ADC packt man besser via 16-Bit-Zugriff an, zumal die Reihenfolge 
auf lo/hi nicht egal ist.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt hast du mich mit runtergelassenen Hosen erwischt: Ich habe es 
nämlich auch nicht im Compiler ausprobiert, sondern einfach 
hingeschrieben. Wie gesagt, was falsch im Kopp drin ist, kommt nur durch 
Fehlermachen (und einen der es merkt) raus.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. wrote:
> Jetzt hast du mich mit runtergelassenen Hosen erwischt:
Und das bei den Temperaturen ... brrr

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.