Forum: Mikrocontroller und Digitale Elektronik ATmega164PA -> UARTs wollen nicht -.-


von Markus O. (pipimaxi)


Lesenswert?

Guten Tag liebe Gemeinde,
seit gestern Abend sitze ich an einem Problem, was mir bis jetzt 
jegliche graue Haare bereitet hätte, wenn ich denn welche hätte ;-)
Es geht um den UART beim ATmega164PA.

Ich "beclocke" diesen über einen Quarz mit 12MHz, habe ihn an meinem 
JTAGICE mk2 zum debuggen, alles wunderbar soweit.

Hier mal der Code, mit welchem ich die UARTs inite:
1
void uart_init(void)
2
{
3
  UBRR0 = (F_CPU/(16*19200ul))-1;
4
  UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0);
5
  UCSR0C = (3<<UCSZ00);
6
  
7
  //configure UART -> FT232RL
8
  UBRR1 = (F_CPU/(16*(long)19200))-1;
9
  UCSR1B = (1<<TXEN1) | (1<<RXEN1) | (1<<RXCIE1);
10
  UCSR1C = (3<<UCSZ10);
11
}

F_CPU ist in diesem Fall auf 12000000ul gesetzt.
So, der aufmerksame Leser wird erkannt haben, dass am UART1 ein FT232RL 
hängt, welcher mir als USB Brücke für den Laptop dient.
Hier benutzt ich HTerm, um das ganze zu testen.

Empfangen funktioniert...wenn ich über HTerm 10mal hintereinander das 
Zeichen schicke, lande ich in der ISR und kann auch die Bits auf der 
Leitung mit dem Oszi erkennen, diese Richtung FT232RL -> ATmega geht 
also.
Senden allerdings nicht...
Zu Beginn des Programms ist der Pin low, logischerweise, habe ich die 
Init-Routine durchschritten, ist der Sende-Pin high, so soll es auch 
sein, aber dabei bleibts.
Sende ich mit dieser Routine ein Zeichen:
1
void uart1send(uint8_t data)
2
{
3
  while(!(UCSR1A & (1<<UDRE1)))
4
  UDR1 = data;
5
}

Das Gleiche habe ich auch mit dem UART0, hier ist das gleiche Phänomen 
am Ausgangspin.
Daher vermute ich mal, dass __irgendwo__ ein dummes Bit nicht gesetzt 
ist oder sonst eine Einstellung verkehrt, was mir das Senden verhindert.
Ich wüsste momentan nicht, an was es liegen könnte...FuseBits sind 
soweit alle richtig gesetzt, sonst funktioniert der Controller ja auch.

Kann mir jemand helfen?

MfG
Markus

P.S.:
Die Main schaut recht unspektakulär aus, aber hier dennoch:
1
int main(void)
2
{
3
  uint8_t test;
4
  uart_init();
5
  sei();
6
  
7
    while(1)
8
    {
9
    uart0send(0x55);
10
    uart1send(0x55);
11
    //TODO:: Please write your application code 
12
    }
13
}

von Markus O. (pipimaxi)


Lesenswert?

Ein kleines Addendum:
Interessanterweise lande ich auch nicht in der USARTn_TX_vect ISR, 
obwohl diese im Register UCSRnB |= (1<<TXCIEn) aktiviert ist.
'n' steht hier jeweils als Platzhalter für UART1 und UART0!

Daher geht mein Verdacht immer mehr Richtung ATmega!

von Hubert G. (hubertg)


Lesenswert?

Markus Oberle schrieb:
> Hier mal der Code, mit welchem ich die UARTs inite:
> void uart_init(void)
> {
>   UBRR0 = (F_CPU/(16*19200ul))-1;
>   UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0);
>   UCSR0C = (3<<UCSZ00);
>
>   //configure UART -> FT232RL
>   UBRR1 = (F_CPU/(16*(long)19200))-1;
>   UCSR1B = (1<<TXEN1) | (1<<RXEN1) | (1<<RXCIE1);
>   UCSR1C = (3<<UCSZ10);
> }

Hier hast du das aber unterschlagen.

von Markus O. (pipimaxi)


Lesenswert?

hm damn it.
ok, da geb ich dir recht.
So schaut meine Routine aktuell aus:
1
void uart_init(void)
2
{
3
  UBRR0 = (F_CPU/(16*19200ul))-1;
4
  UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0) | (1<<TXCIE0);
5
  UCSR0C = (3<<UCSZ00);
6
  
7
  UBRR1 = (F_CPU/(16*(long)19200))-1;
8
  UCSR1B = (1<<TXEN1) | (1<<RXEN1) | (1<<RXCIE1) | (1<<TXCIE1);
9
  UCSR1C = (3<<UCSZ10);
10
}

kommt davon, wenn man gleichzeitig postet und nebenbei rumprobiert.

Erfolg bleibt weiterhin aus :-(

von Markus O. (pipimaxi)


Lesenswert?

So, ich darf teilweisen Erfolg verkünden...ich verstehs aber net...

es funktioniert, wenn ich die Zeile auskommentier:
1
while(!(UCSR1A & (1<<UDRE1)))

aber warum....KEINE AHNUNG! in allen möglichen Beispielen und laut 
Datenblatt, soll es SO mit der Zeile funktionieren...tut es aber nicht 
-.-

von Stefan E. (sternst)


Lesenswert?

Markus Oberle schrieb:
> in allen möglichen Beispielen und laut
> Datenblatt, soll es SO mit der Zeile funktionieren

Überall dort steht aber mit Sicherheit dahinter entweder noch ein 
Semikolon oder ein {}.

von Coder (Gast)


Lesenswert?

Exakt. Im Datenblatt steht, dass das UDRE Bit gesetzt wird, wenn das 
Senderegister leer ist und weiteres Datenbyte gesendet werden darf. Also
1
while (((UCSR1A & (1<<UDRE1))==0))
2
{
3
  __no_operation;
4
}
5
6
UDR1=dummy;

Wenn man die geschweiften Klammern nicht haben möchte, setzt man ein ; 
ans Ende der Zeile von der while-Anweisung.

So wie Du das hingeschrieben hast, schreibst Du ins UDR Register wenn es 
belegt ist.

von Coder (Gast)


Lesenswert?

Und bevor jemand meckert, ja ich habe mich verklammert...

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.