Forum: Compiler & IDEs Probleme mit UART


von Möchte_gern_Freak (Gast)


Lesenswert?

Tag zusammen

Ich habe
http://www.rn-wissen.de/index.php/UART_mit_avr-gcc
und
http://www.rn-wissen.de/index.php/FIFO_mit_avr-gcc

Für mein Projekt schön übernommen =D Nur leider klappt das nicht so :(

Da ich leider einen anderen MC habe(ATMEGA 644-20PU), musste ich 
sämtliche Registernamen abändern.

Hier einige Punkte, wo ich mögliche Fehler vermute:

1.) URSEL konnte ich nirgens im Datasheet finden. Nach langem suchen 
habe ich mich für das UMSEL00 entschieden da das zum Register UCSR0C 
gehört...keine Ahnung ob das stimmt :(

2.) Muss ich die Pins für das UART eigentlich noch auf IN/OUT und 
High/Low schalten oder ist das egal?

Hoffe mir kann jemand weiterhelfen =D

von g457 (Gast)


Lesenswert?

> 1.) URSEL konnte ich nirgens im Datasheet finden. Nach langem suchen
> habe ich mich für das UMSEL00 entschieden da das zum Register UCSR0C
> gehört...keine Ahnung ob das stimmt :(

Da schaust besser nochmals (richtig) in die Datenplätter. (Kurzfassung: 
Nein.)

> 2.) Muss ich die Pins für das UART eigentlich noch auf IN/OUT und
> High/Low schalten oder ist das egal?

..auch das steht im Datenplatt. (Kurzfassung: Nein.)

HTH

von Karl H. (kbuchegg)


Lesenswert?

Möchte_gern_Freak schrieb:

> 1.) URSEL konnte ich nirgens im Datasheet finden. Nach langem suchen
> habe ich mich für das UMSEL00 entschieden da das zum Register UCSR0C
> gehört...keine Ahnung ob das stimmt :(

Wenn du Code von einem µC auf einen anderen übernimmst und mit einer 
Bezeichnung nichts anfangen kannst, dann lautet die richtige 
Vorgehensweise: Das Datenblatt des Quellprozessors heraussuchen und 
nachsehen, was dieses Bit macht.

URSEL hat eine besondere Bedeutung. Bei manchen AVR µC teilen sich das 
High-Byte der Baudrateneinstellung und das Controllbyte dieselbe 
Zugriffsadresse. Um nun unterscheiden zu können, was bei einem 
Schreibvorgang gemeint ist dient das USRSEL Bit. Ist es 0, so gilt der 
Schreibzugriff dem Highbyte der Baudrate. Ist es 1, so gilt der 
Schreibzugriff dem Controllbyte.

>
> 2.) Muss ich die Pins für das UART eigentlich noch auf IN/OUT und
> High/Low schalten oder ist das egal?

Das macht der µC intern schon selber. Sobald du den Receiver enablest, 
wird der Rx Pin zum Input. Sobald du den Transceiver enablest, wird der 
Tx Pin zum Output.

von Möchte_gern_Freak (Gast)


Lesenswert?

Also laut Datasheet ATmega8 ist URSEL das 7 Bit von UBRRH aber auch das 
7 Bit von UCSRC

Und in meinem Fall ist das 7te Bit von UCSR0C UMSEL01!
Und das habe ich so :( Das UMSEL00 ist ein Tippfehler im Forum..sorry.

Im code steht UMSEL01 und den Fehler habe ich immer noch nicht 
gefunden....

Ich kriege allerdings noch 2 Warnings:

../RRX_ON_Board.c:83: warning: 'USART_RXC_vect' appears to be a 
misspelled signal handler
../RRX_ON_Board.c:91: warning: 'USART_UDRE_vect' appears to be a 
misspelled signal handler


Das sind die beiden Interrupt Rutinen:
http://www.rn-wissen.de/index.php/UART_mit_avr-gcc#Interrupt-Routinen

von Krapao (Gast)


Lesenswert?

> ../RRX_ON_Board.c:83: warning: 'USART_RXC_vect' appears to be a
> misspelled signal handler
> ../RRX_ON_Board.c:91: warning: 'USART_UDRE_vect' appears to be a
> misspelled signal handler

Wie die entsprechenden Interruptvectoren bei dem ATMEGA 644-20PU heissen 
findest du raus, wenn du dir die Includedatei anschaust in der alle 
Namen der Interruptvektoren definiert werden. Diese Datei findest du, 
wenn du in deinem Projekt alle verwendeten Includedateien mal durch 
siehst.

von Möchte_gern_Freak (Gast)


Lesenswert?

Danke für die AW...Ich habe es jetzt Mehrmals "durchgelesen" und finde 
immer noch nicht das richtige :( HELP..

Ich weiss nicht welches..

Wenn ich richtig verstehe muss ich doch das hier abändern:
ISR (USART_UDRE_vect)

z.B zu ISR_BLOCK (USART_UDRE_vect)

oder verstehe ich da etwas falsch? Ist mein erstes GCC Projekt.... ;)

von Krapao (Gast)


Lesenswert?

Die io.h am Programmanfang ruft mit mit der Angabe des AVR Modells 
Atmega644 in AVR Studio
1
#elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__)
2
#  include <avr/iom644.h>

letztlich iom644.h auf und die ruft die iomxx4.h auf und darin sind die 
Zeilen:
1
/* USART0, Rx Complete */
2
#define USART0_RX_vect      _VECTOR(20)
3
#define SIG_USART_RECV      _VECTOR(20)
4
5
/* USART0 Data register Empty */
6
#define USART0_UDRE_vect    _VECTOR(21)
7
#define SIG_USART_DATA      _VECTOR(21)
8
9
/* USART0, Tx Complete */
10
#define USART0_TX_vect      _VECTOR(22)
11
#define SIG_USART_TRANS      _VECTOR(22)

Nur zur Sicherheit: Du hast wirklich einen Atmega644 und keinen 
Atmega644P?

von Stefan E. (sternst)


Lesenswert?

Möchte_gern_Freak schrieb:
> Also laut Datasheet ATmega8 ist URSEL das 7 Bit von UBRRH aber auch das
> 7 Bit von UCSRC
>
> Und in meinem Fall ist das 7te Bit von UCSR0C UMSEL01!
> Und das habe ich so :( Das UMSEL00 ist ein Tippfehler im Forum..sorry.
>
> Im code steht UMSEL01 und den Fehler habe ich immer noch nicht
> gefunden....

Und dass Bit 7 in UCSRC bei den beiden Controllern unterschiedlich 
benannt ist, gibt dir nicht zu denken?
Ist "anderer Name" = "andere Bedeutung" nicht irgendwie naheliegend?

Möchte_gern_Freak schrieb:
> Wenn ich richtig verstehe muss ich doch das hier abändern:
> ISR (USART_UDRE_vect)

Ja.

Möchte_gern_Freak schrieb:
> z.B zu ISR_BLOCK (USART_UDRE_vect)

Nein. Was falsch ist, ist der Name der ISR.
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

von Krapao (Gast)


Lesenswert?

> Wenn ich richtig verstehe muss ich doch das hier abändern:
> ISR (USART_UDRE_vect)
> z.B zu ISR_BLOCK (USART_UDRE_vect)

ISR (USART_UDRE_vect)
zu ISR_BLOCK (USART0_UDRE_vect)

Plus weitere Änderungen der Spezialregisternamen analog zu den 
Änderungen in iom644.h (neuer Code) und iom8.h (alter Code). Dabei sind 
Feinheiten bzgl. Bitnamen zu beachten, die in den Datenblättern beider 
AVRs nachzuschlagen sind.

von Stefan E. (sternst)


Lesenswert?

Krapao schrieb:
> ISR (USART_UDRE_vect)
> zu ISR_BLOCK (USART0_UDRE_vect)

"ISR" in "ISR_BLOCK" zu ändern, ist Unsinn.

von Krapao (Gast)


Lesenswert?

ADD: ISR zu ISR_BLOCK hatte ich nicht geprüft.

Laut avr-libc Doku entspricht ISR ohne Zusatz dem ISR_BLOCK. Für bessere 
Lesbarkeit des Codes kann man das machen. Es ist nicht notwendig und 
eine Funktionsänderung ist nicht vorhanden.

von Stefan E. (sternst)


Lesenswert?

Krapao schrieb:
> Für bessere
> Lesbarkeit des Codes kann man das machen.

Nein, kann man nicht.
ISR_BLOCK ist ein mögliches Attribut zu ISR.

von Möchte_gern_Freak (Gast)


Lesenswert?

Krapao schrieb:
> Nur zur Sicherheit: Du hast wirklich einen Atmega644 und keinen
> Atmega644P?

-.- Eigentlich sollte ich wissen dass ich nach 24:00 sehr viel fehler 
mache.... Ja da steht noch ein P!


Stefan Ernst schrieb:
> Und dass Bit 7 in UCSRC bei den beiden Controllern unterschiedlich
> benannt ist, gibt dir nicht zu denken?
> Ist "anderer Name" = "andere Bedeutung" nicht irgendwie naheliegend?

Eigentlich ja! Denn (fast) jeder Devloper will seine Kunden ja nicht mit 
unnötigen Änderungen nerven! Ich ich verstehe nur den (kopierten) Code 
(noch) nicht. Ich habe grad Brett vorm Kopf :(
Hat da jemand nen Tipp oder ne Lösung?

Stefan Ernst schrieb:
> Nein. Was falsch ist, ist der Name der ISR.
> http://www.nongnu.org/avr-libc/user-manual/group__...

Na dass nenne ich ja mal ne gute Seite...
Jetzt sind die Warnings weg

von Möchte_gern_Freak (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> URSEL hat eine besondere Bedeutung. Bei manchen AVR µC teilen sich das
> High-Byte der Baudrateneinstellung und das Controllbyte dieselbe
> Zugriffsadresse. Um nun unterscheiden zu können, was bei einem
> Schreibvorgang gemeint ist dient das USRSEL Bit. Ist es 0, so gilt der
> Schreibzugriff dem Highbyte der Baudrate. Ist es 1, so gilt der
> Schreibzugriff dem Controllbyte.

Wenn ich das jetzt richtig sehe, teilen sie sich das in meinem Fall 
nicht. Oder?

Was wird in diesem Fall aus der Code-Zeile
1
 UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);

von Stefan E. (sternst)


Lesenswert?

Möchte_gern_Freak schrieb:
> Wenn ich das jetzt richtig sehe, teilen sie sich das in meinem Fall
> nicht. Oder?

Richtig.

Möchte_gern_Freak schrieb:
> Was wird in diesem Fall aus der Code-Zeile
1
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
Ja, wie sollte die Zeile wohl aussehen, wenn man das URSEL-Bit gar nicht 
braucht?

Heißer Tipp am Rande: schau mal im Datenblatt nach, was der 
Default-Inhalt des Registers ist.

von Möchte_gern_Freak (Gast)


Lesenswert?

Datenblatt sagt auf S 178
1
void USART_Init( unsigned int baud )
2
{
3
/* Set baud rate */
4
UBRRHn = (unsigned char)(baud>>8);
5
UBRRLn = (unsigned char)baud;
6
/* Enable receiver and transmitter */
7
UCSRnB = (1<<RXENn)|(1<<TXENn);
8
/* Set frame format: 8data, 2stop bit */
9
UCSRnC = (1<<USBSn)|(3<<UCSZn0);
10
}

Ich brauche 8data, 1stop, Non-parity.
Meine Initialisierung sieht so aus:
1
void uart_init (void)
2
{
3
    uint8_t sreg = SREG;
4
    uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16UL*BAUDRATE) - 1);
5
6
    UBRR0H = (uint8_t) (ubrr>>8);
7
    UBRR0L = (uint8_t) (ubrr);
8
9
    // Interrupts kurz deaktivieren 
10
    cli();
11
12
    // UART Receiver und Transmitter anschalten, Receive-Interrupt aktivieren 
13
    // Data mode 8N1, asynchron 
14
    UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
15
     UCSR0C = (3<<UCSZ00);
16
17
    // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) 
18
    do
19
    {
20
        // UDR auslesen (Wert wird nicht verwendet) 
21
        UDR0;
22
    }
23
    while (UCSR0A & (1 << RXC0));
24
25
    // Rücksetzen von Receive und Transmit Complete-Flags 
26
    UCSR0A = (1 << RXC0) | (1 << TXC0);
27
28
    // Global Interrupt-Flag wieder herstellen 
29
    SREG = sreg;
30
31
    // FIFOs für Ein- und Ausgabe initialisieren 
32
    fifo_init (&infifo,   inbuf, BUFSIZE_IN);
33
    fifo_init (&outfifo, outbuf, BUFSIZE_OUT);
34
}

Was habe ich denn immer noch verbokt? tatsache ist: es geht nich!
F_CPU ist auf 14000000 eingestellt, Baud auf 9600..

von Karl H. (kbuchegg)


Lesenswert?

Möchte_gern_Freak schrieb:


> Was habe ich denn immer noch verbokt? tatsache ist: es geht nich!

tu dir selbst einen Gefallen und bring erst mal die ganz banale 
Einzelzeichen-Sendefunktionalität auf die Reihe, ehe du dann mit 
Interrupts und Fifo auf die komplexeren Varianten umstellst.
Je mehr Code du ungetestet in Betrieb nehmen willst, umso mehr 
Fehlermöglichkeiten gibt es.

von Möchte_gern_Freak (Gast)


Lesenswert?

Danke für den Tipp ;) Ich hatte bereits vorgestern mit vereinfachten 
Codes gearbeitet..

Das blöde: Es lag gar nicht am Code, sondern am einem Fusebit..

Es war reiner Zufall dass ich es gemerkt habe :)

Ich hatte auf 16K CK eingestellt...vorhin mal auf 1K CK gestellt und 
jetzt gehts..sogar die Variante mit Interups..

Jetzt aber noch eine verständnissfrage:

CK ist doch C(loc)k(s) also Take bis er Eingeschwungen ist, oder?
Wenn ich doch länger warte (16CK) sollte das doch nichts machen?!

Es ist ein Restposten Quarz und ich habe nur eine Angabe: 14Mhz ;)

Danke an alle und sry für die (unnötigen) Umstände

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.