Forum: Mikrocontroller und Digitale Elektronik USART falsch initialisiert?


von Daniel (Gast)


Lesenswert?

Ich zweifele gerade an meiner Intelligenz. Ich schreibe gerade mein 
erstes C-Programm für einen Atmega8 (komme aus der Assembler-Ecke) und 
möchte über USART/Midi ein Instrument ansteuern. Hier die relevanten 
Code-Ausschnitte:
1
#ifndef F_CPU
2
#define F_CPU    4000000UL
3
#endif
4
5
#define BAUD    31250
6
#define UBRR_VAL  ((F_CPU+BAUD+8)/(BAUD*16)-1)
7
#define BAUD_REAL  (F_CPU/(16*(UBRR_VAL+1)))
8
#define BAUD_ERROR  ((BAUD_REAL*1000)/BAUD)
9
10
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
11
#error Baudratefehler!
12
#endif
13
14
void uart_init(){
15
  UCSRB |= (1<<TXEN);
16
  UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
17
  UBRRH = UBRR_VAL >> 8;
18
  UBRRL = UBRR_VAL & 0xFF;
19
}
20
21
22
23
int main(void)
24
{
25
  lcd_init();
26
  uart_init();
27
  
28
  lcd_string("TEST: ");
29
  
30
  DDRB = 0x01;//TEST
31
  PORTB ^= 0x01;//TEST
32
  
33
  while (!(UCSRA & (1<<UDRE)))
34
  {
35
    PORTB ^= 0x01;//TEST
36
  }
37
  UDR = 145;
38
  while (!(UCSRA & (1<<UDRE)));
39
  {
40
    PORTB ^= 0x01;//TEST
41
  }
42
  UDR = 39;
43
  while (!(UCSRA & (1<<UDRE)));
44
  {
45
    
46
  }
47
  UDR = 100;
48
  
49
  while(1)
50
  {}
51
  return 0;
52
}

Irgendwie spuckt nun TX nur Dauer-High aus. Mein TEST-TOGGLE sorgt für 
einen kurzen HIGH-Puls(ca. 2,5us). Das LCD läuft einwandfrei (Code 
fehlt).


Helft mir doch bitte auf die Sprünge. Das Datenblatt spuckt mir genau 
den selben Code aus und ich stehe voll auf dem Schlauch.

Danke!!!

von Daniel (Gast)


Lesenswert?

Hat denn keiner eine Idee, was los sein könnte?

von Timmo H. (masterfx)


Lesenswert?

Vielleicht einfach mal PD1 (Txd) auf Ausgang setzen.

von spess53 (Gast)


Lesenswert?

Hi

>Vielleicht einfach mal PD1 (Txd) auf Ausgang setzen.

Das Pin wird automatisch Ausgang, wenn TXEN gesetzt wird.

MfG Spess

von Timmo H. (masterfx)


Lesenswert?

Ja stimmt. evtl. auch einfach nur ein Fehler in der Schaltung.

von Daniel (Gast)


Lesenswert?

spess53 schrieb:
>>Vielleicht einfach mal PD1 (Txd) auf Ausgang setzen.
>
> Das Pin wird automatisch Ausgang, wenn TXEN gesetzt wird.

Naja auf jeden Fall, hat ein manuelles setzen von PD1 in DDRD nichts 
gebracht.

Der Quarz schwingt sauber mit einer Amplitude von 800mVpp. Das LCD tut 
fleißig seinen Dienst. Die Messung des Signals erfolgt direkt an PD1. 
Ich weiß nicht, was da an der Schaltung falsch sein sollte.

von Timmo H. (masterfx)


Lesenswert?

Ha:
1
#define UBRR_VAL  ((F_CPU+BAUD+8)/(BAUD*16)-1)
mach da mal das draus:
1
#define UBRR_VAL  ((F_CPU+BAUD*8)/(BAUD*16)-1)

von Daniel (Gast)


Lesenswert?

Timmo H. schrieb:
> Ha:#define UBRR_VAL  ((F_CPU+BAUD+8)/(BAUD*16)-1)mach da mal das draus:#define 
UBRR_VAL  ((F_CPU+BAUD*8)/(BAUD*16)-1)

Genial gesehen, Danke, bringt aber nichts. Schade :-(

von Timmo H. (masterfx)


Lesenswert?

Ja hab ich mir gedacht, aber ein Fehler ists dennoch.
Bist du sicher, dass du uns keinen Code vorenthalten hast, wo du ggf. 
doch noch den Port anders befingerst?

von Daniel (Gast)


Lesenswert?

Timmo H. schrieb:
> Ja hab ich mir gedacht, aber ein Fehler ists dennoch.

Definitiv.


Ich habe mal das Sende-Zeug in eine Endlosschleife gepackt:

1
while(1){
2
  while (!(UCSRA & (1<<UDRE)))
3
  {
4
    PORTB ^= 0x01;
5
  }
6
  UDR = 145;
7
  while (!(UCSRA & (1<<UDRE)))
8
  {
9
    PORTB ^= 0x01;
10
  }
11
  UDR = 39;
12
  
13
  while (!(UCSRA & (1<<UDRE))){}
14
  UDR = 100;
15
  }

Auf dem Oszi ist rein gar nichts mehr zu sehen. Der PB0-Testpin wird 
auch nicht mehr getoggelt, seit UBRR_VAL korrigiert wurde. Anscheinend 
werden die while-Schleifen gar nicht durchlaufen.

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Timmo H. schrieb:
> Bist du sicher, dass du uns keinen Code vorenthalten hast, wo du ggf.
> doch noch den Port anders befingerst?

Anbei alle Quelldateien. Möchte das jetzt nicht hier als Fließtext 
reinpacken. Wenn gewünscht, mache ich das natürlich.

Der Code, insbesondere main(), sieht gerade etwas durcheinander aus, 
wegen dem vielen Probieren.

von Timmo H. (masterfx)


Lesenswert?

Mhh,
versuch mal ob es was bringt wenn du nach dem Uart Init zumindest einmal 
das UDR ausliest...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Daniel schrieb:
>
1
#ifndef F_CPU
2
> #define F_CPU    4000000UL
3
> #endif
4
>

So etwas mache ich äußerst ungern. Ist im Projekt ein abweichender 
F_CPU-Wert eingetragen, kommen diese Zeilen gar nicht zum Tragen. Es 
gibt noch nichtsmals eine Fehlermeldung, dass hier ein abweichender Wert 
steht.

Entweder nur:
1
#define F_CPU    4000000UL

oder mal alle 3 Zeilen testweise auskommentieren.

von Uwe (de0508)


Lesenswert?

Hallo,

ich möchte Dir nur einen Tipp geben, verwende doch mal die fertigen 
Routinen von Peter Dannegger.

Bei mir läuft damit alle sehr gut !

AVR-GCC: UART mit FIFO
- Beitrag "AVR-GCC: UART mit FIFO"

Peter Fleury hat auch einige Routinen veröffentlicht:
- http://homepage.hispeed.ch/peterfleury/avr-software.html#libs

Beide funktionieren und man braucht nichts mehr selber zu "stricken".

von Dietrich L. (dietrichl)


Lesenswert?

Daniel schrieb:
> void uart_init(){
>   UCSRB |= (1<<TXEN);
>   UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
>   UBRRH = UBRR_VAL >> 8;
>   UBRRL = UBRR_VAL & 0xFF;
> }

Vertausch mal versuchsweise die Reihenfolge:

 void uart_init(){
   UBRRH = UBRR_VAL >> 8;
   UBRRL = UBRR_VAL & 0xFF;
   UCSRB |= (1<<TXEN);
   UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
 }

Im Datenblatt ist es so beschrieben. Vielleicht mag der UART nicht, die 
Baudrate-Register zu ändern, wenn er schon enabled ist.

Gruß Dietrich

von Daniel (Gast)


Lesenswert?

Ich habe einen neuen ATmega8 eingesetzt, das half nichts.

Aber irgendwie läuft es jetzt nachdem ich alle Ratschläge umgesetzt 
habe. Jetzt wollt ihr bestimmt noch wissen, wessen Idee das Teil zum 
Laufen gebracht hat?

von Timmo H. (masterfx)


Lesenswert?

Hast du auch UDR vorher mal ausgelesen?

von Daniel (Gast)


Lesenswert?

Dietrich L. schrieb:
> Vertausch mal versuchsweise die Reihenfolge:
>
>  void uart_init(){
>    UBRRH = UBRR_VAL >> 8;
>    UBRRL = UBRR_VAL & 0xFF;
>    UCSRB |= (1<<TXEN);
>    UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
>  }

Der Gewinner ist Dietrich. Also euch allen ein ganz dickes Dankeschön.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Daniel schrieb:
> Jetzt wollt ihr bestimmt noch wissen, wessen Idee das Teil zum
> Laufen gebracht hat?

Na klar :-)

von Daniel (Gast)


Lesenswert?

Timmo H. schrieb:
> Hast du auch UDR vorher mal ausgelesen?

Jo, und auf dem LCD ausgegeben. Ich weiß aber nicht, was das auf deutsch 
heißt^^ Cheng-Peng

Besonders hart finde ich ja, dass ich diesen Quäl-Code aus dem Tutorial 
habe. Da sollte man vielleicht mal die richtige Version einstellen. Soll 
ich das mal versuchen?

von Daniel (Gast)


Lesenswert?

Frank M. schrieb:
> Daniel schrieb:
>> Jetzt wollt ihr bestimmt noch wissen, wessen Idee das Teil zum
>> Laufen gebracht hat?
>
> Na klar :-)

Sorry, Frank, du warst es leider nicht (obwohl ich dich zunächst 
favorisiert habe). Ich werde deinen Ratschalg aber in Zukunft 
beherzigen, klingt nämlich recht logisch.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Daniel schrieb:
> Besonders hart finde ich ja, dass ich diesen Quäl-Code aus dem Tutorial
> habe. Da sollte man vielleicht mal die richtige Version einstellen. Soll
> ich das mal versuchen?

Ja.

von Daniel (Gast)


Lesenswert?

Frank M. schrieb:
> Daniel schrieb:
>> Besonders hart finde ich ja, dass ich diesen Quäl-Code aus dem Tutorial
>> habe. Da sollte man vielleicht mal die richtige Version einstellen. Soll
>> ich das mal versuchen?
>
> Ja.

Das ist ja leichter, als ich dachte. Man benötigt ja nichteinmal einen 
Account. Hab's angepasst mit dem Verweis auf diesen Thread.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Daniel schrieb:
> Sorry, Frank, du warst es leider nicht (obwohl ich dich zunächst
> favorisiert habe).

Mein Favorit war auch Dietrich. Ist schon interessant, was man alles so 
bei einer simplen UART-Initialisierung falsch machen kann. Auf die 
Reihenfolge wäre ich nie gekommen, da benutze ich von Projekt zu Projekt 
nur Copy-and-Paste. Und glücklicherweise kommt da die TXEN-Zeile immer 
als letztes :-)

> Ich werde deinen Ratschalg aber in Zukunft beherzigen, klingt nämlich
> recht logisch.

:-)

von spess53 (Gast)


Lesenswert?

Hi

>Das ist ja leichter, als ich dachte. Man benötigt ja nichteinmal einen
>Account. Hab's angepasst mit dem Verweis auf diesen Thread.

Vielleicht etwas voreilig. Das URSEL-Bit haben nicht alle AVRs. Bei 
denen ist die Reihenfolge egal.

MfG Spess

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

spess53 schrieb:
> Vielleicht etwas voreilig. Das URSEL-Bit haben nicht alle AVRs. Bei
> denen ist die Reihenfolge egal.

Das URSEL-Bit stand aber auch schon vorher an dieser Stelle. Das könnte 
man natürlich noch mit
1
#ifdef URSEL
2
  ...
3
#else
4
  ...
5
#endif
schöner machen.

@Daniel:

Mir ist aufgefallen, dass die offenbar falsche TXEN-Reihenfolge mehrfach 
im Artikel vorkommt. Du hast aber nur eine korrigiert ;-)

von Daniel (Gast)


Lesenswert?

Frank M. schrieb:
> @Daniel:
>
> Mir ist aufgefallen, dass die offenbar falsche TXEN-Reihenfolge mehrfach
> im Artikel vorkommt. Du hast aber nur eine korrigiert ;-)

Stimmt, das hatte ich nicht gesehen, weil ich nur den Empfangen-Teil 
bearbeitet habe. Wurde inzwischen aber von einem anderen User angepasst. 
Sorry.

von Daniel (Gast)


Lesenswert?

spess53 schrieb:
> Vielleicht etwas voreilig. Das URSEL-Bit haben nicht alle AVRs. Bei
> denen ist die Reihenfolge egal.

Was ist daran voreilig?

Für den Fall, dass der verwendetet AVR kein URSEL hat, schadet die 
Änderung nicht.

Für den Fall, dass der verwendete AVR ein URSEL hat, spart die Änderung 
richtig Zeit und Nerven. Siehe mein Fall. So nen rießen Spaß hat's jetzt 
auch nicht gemacht.

von spess53 (Gast)


Lesenswert?

Hi

>Für den Fall, dass der verwendete AVR ein URSEL hat, spart die Änderung
>richtig Zeit und Nerven. Siehe mein Fall. So nen rießen Spaß hat's jetzt
>auch nicht gemacht.

Ein Blick ins Dtenblatt hätte gereicht. Dort steht das laut und deutlich 
drin.

MfG Spess

von Stefan E. (sternst)


Lesenswert?

spess53 schrieb:
>>Für den Fall, dass der verwendete AVR ein URSEL hat, spart die Änderung
>>richtig Zeit und Nerven. Siehe mein Fall. So nen rießen Spaß hat's jetzt
>>auch nicht gemacht.
>
> Ein Blick ins Dtenblatt hätte gereicht. Dort steht das laut und deutlich
> drin.

Was genau soll denn da stehen?
Ich sehe jedenfalls so auf Anhieb nicht, was diese Reihenfolge vorgeben 
soll. Insbesondere nichts in Zusammenhang mit URSEL.

von Daniel (Gast)


Lesenswert?

spess53 schrieb:
> Ein Blick ins Dtenblatt hätte gereicht. Dort steht das laut und deutlich
> drin.

Mit einem solchen Argument könnt ihr euer Tutorial komplett einstampfen. 
Außerdem habe ich einen Blick ins Datenblatt gewagt. Ich bin ja nicht 
unbedingt blöd, aber ich habe meinen Fehler dadurch nicht bemerkt.

Du willst jetzt nicht wirklich meckern, weil ich das Tutorial 
anfängerfreundlicher gemacht habe, ohne ein Zeichen zu löschen oder 
hinzuzufügen?

von spess53 (Gast)


Lesenswert?

HI

>Was genau soll denn da stehen?
>Ich sehe jedenfalls so auf Anhieb nicht, was diese Reihenfolge vorgeben
>soll. Insbesondere nichts in Zusammenhang mit URSEL.

Was ist mit 'Accessing UBRRH/UCSRC Registers' im Kapitel UART?

MfG Spess

von Stefan E. (sternst)


Lesenswert?

spess53 schrieb:
> Was ist mit 'Accessing UBRRH/UCSRC Registers' im Kapitel UART?

Ja, was ist damit? Warum soll sich daraus irgendein Zwang für eine 
bestimmte Reihenfolge ergeben?

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:
> HI
>
>>Was genau soll denn da stehen?
>>Ich sehe jedenfalls so auf Anhieb nicht, was diese Reihenfolge vorgeben
>>soll. Insbesondere nichts in Zusammenhang mit URSEL.
>
> Was ist mit 'Accessing UBRRH/UCSRC Registers' im Kapitel UART?

Um ehrlich zu sein, ich versteh jetzt auch nicht worauf du hinaus 
willst. Beim SChreiben sollte doch eigentlich mit dem URSEL Bit alles 
geregelt sein.

(Obwohl ich mich auch an dieses Problem bei meinen ersten UART 
Funktionen erinnern kann. Aber dann wird halt der Code immer 
weiterkopiert, wenn er mal läuft, sodass ich dem nie weiter nachgegangen 
bin)

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.