USART falsch initialisiert?

Gast #2281278
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!!!
Gast #2281539
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.
Gast #2281563
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.
Gast #2281573
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.
Angehängte Dateien:
Moderator Persönliche Seite #2281584
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.
#2281587
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".
#2281589
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
Gast #2281607
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?
Gast #2281618
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?
Gast #2281621
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.
Gast #2281626
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.
Moderator Persönliche Seite #2281627
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.

:-)
Gast #2281638
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
Moderator Persönliche Seite #2281684
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 ;-)
Gast #2282445
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.
Gast #2282499
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.
Gast #2282601
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
#2282623
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.
Gast #2282648
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?
Gast #2282747
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
#2282756
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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren