Forum: Compiler & IDEs UART Atmega 64 Probleme


von rma (Gast)


Lesenswert?

Hallo zusammen

Ich möchte momentan eine UART von einem Atmega64 zum laufen bringen. 
Habe aber leider Probleme. Momentan denke es liegt an der 
Initialisierung. Habe das Datenblatt mehrmals angschaut, konnte den 
Fehler aber nicht finden.
Für eure Hilfe wäre ich dankbar.

Angaben:
Atmega64
Interner clock: 8MHz
1
#include "WLAN-Board.h" 
2
3
4
void USART_Transmit( unsigned char);
5
unsigned char USART_Receive( void );
6
7
/////////////////////////main/////////////////////////////////////////////
8
void main (void)
9
{
10
  int EmpfangenDaten;
11
  //Init();
12
  DDRA  = (1<<DDA0) | (0<<DDA1);
13
  PORTA  = (1<<PA0) | (1<<PA1);
14
  
15
  UCSR1A = (0<<U2X1);  
16
  UCSR1B = (1<<RXCIE1) | (1<<TXCIE1) |  (1<<RXEN1) | (1<<TXEN1);
17
  UBRR1L = 51;
18
  
19
  
20
  while(1)
21
  {
22
    PORTA ^= (1<<PA0);
23
    USART_Transmit(58);
24
    EmpfangenDaten = USART_Receive();
25
26
  }
27
////////////////////////Funktionen////////////////////////////////////////
28
}
29
void USART_Transmit( unsigned char data )
30
{
31
  /* Wait for empty transmit buffer */
32
  while ( !( UCSR1A & (1<<UDRE1)) )
33
  
34
  /* Put data into buffer, sends the data */
35
  UDR1 = data;
36
}
37
38
unsigned char USART_Receive( void )
39
{
40
  /* Wait for data to be received */
41
  while ( !(UCSR1A & (1<<RXC1)) )
42
  /* Get and return received data from buffer */
43
  return UDR1;
44
}

Falls ihr den Fehler seht wäre mir geholfen.

Ebenso habe ich Probleme beim debuggen mit dem AVR Studio 4.19. Habt ihr 
auch Probleme oder mache ich da auch noch Fehler?

von Krapao (Gast)


Lesenswert?

>   UCSR1B = (1<<RXCIE1) | (1<<TXCIE1) |  (1<<RXEN1) | (1<<TXEN1);

Du gibst da zwei Interrupts frei und ich sehe keine ISRs dafür. Es 
passiert zwar nix weil das sei() fehlt, aber das scheint mir nicht 
duchdacht zu sein.

Wie kommst du auf 51 und wie groß ist der nominelle Baudratenfehler bei 
internen 8MHz und der Wunschbaudrate? Ist die 8 MHz tatsächlich wirksam 
oder hat der AVR eventuell noch eine andere Taktrate ab Werk?

>  while ( !( UCSR1A & (1<<UDRE1)) )
> ...
>  while ( !(UCSR1A & (1<<RXC1)) )

Da fehlen die Anweisungsblöcke der while-Schleifen!

von MWS (Gast)


Lesenswert?

rma schrieb:
> while ( !( UCSR1A & (1<<UDRE1)) )
>
>   /* Put data into buffer, sends the data */
>   UDR1 = data;

Semikolon vergessen, dürfte so übersetzt werden:
1
while ( !( UCSR1A & (1<<UDRE1)) ) UDR1 = data;
1
while ( !(UCSR1A & (1<<RXC1)) ) return UDR1;

Außerdem sind 19200 Baud mit dem eher ungenauen R/C-Oszillator ein 
Problem.

von rma (Gast)


Lesenswert?

Interrupt:
Ich weiss das ich momentan zwei Interupts freigebe. Dies weil ich später 
mit Interrupt arbeiten möchte.

Krapao schrieb:
> Wie kommst du auf 51 und wie groß ist der nominelle Baudratenfehler bei
> internen 8MHz und der Wunschbaudrate? Ist die 8 MHz tatsächlich wirksam
> oder hat der AVR eventuell noch eine andere Taktrate ab Werk?

51 habe ich aus dem Datenblatt gelsen für das ubrr1. Nomineller 
Bautdrahten fehler ist 0.2%. Die internen 8MHz habe ich bei den Fuses 
eingestellt. Und die Wunschbaudrate ist 9600.

Gruss Raphael

von MWS (Gast)


Lesenswert?

rma schrieb:
> Und die Wunschbaudrate ist 9600.

Richtig, das hier falsch gelesen:
> UCSR1A = (0<<U2X1);

9600 sollte noch gehen.

von STK500-Besitzer (Gast)


Lesenswert?

rma schrieb:
> Interrupt:
> Ich weiss das ich momentan zwei Interupts freigebe. Dies weil ich später
> mit Interrupt arbeiten möchte.

Den Controller interessiert aber nicht, was du in Zukunft machen willst, 
sondern nur das, was ihm gesagt wird:
Bei Auftreten eines Ereignisses am UART soll er die Interrupt-Routinen 
anspringen.

von rma (Gast)


Lesenswert?

Ok ich habe nun die Semikolons beim while eingefügt, und die Interupts 
Flag auskommentiert.

Sollte ich den jetzt nicht etwas sehen, wen ich mit TeraTerm (ähnlich 
Hyperterminal) etwas sende, auf dem uC etwas sehen?
1
#include "WLAN-Board.h" 
2
3
4
void USART_Transmit( unsigned char);
5
unsigned char USART_Receive( void );
6
7
///////////////////////////////main///////////////////////////////////////
8
void main (void)
9
{
10
  int EmpfangenDaten;
11
  //Init();
12
  DDRA  = (1<<DDA0) | (0<<DDA1);
13
  PORTA  = (1<<PA0) | (1<<PA1);
14
  
15
  UCSR1A = (0<<U2X1);  
16
//  UCSR1B = (1<<RXCIE1) | (1<<TXCIE1);    Interrupt eischalten
17
  UCSR1B = (1<<RXEN1) | (1<<TXEN1);
18
  UBRR1L = 51;
19
  
20
  while(1)
21
  {
22
    PORTA ^= (1<<PA0);
23
    USART_Transmit(58);
24
    EmpfangenDaten = USART_Receive();
25
26
  }
27
}
28
///////////////////////////////Funktionen//////////////////////////////////
29
void USART_Transmit( unsigned char data )
30
{
31
  /* Wait for empty transmit buffer */
32
  while ( !( UCSR1A & (1<<UDRE1)) );
33
  
34
  /* Put data into buffer, sends the data */
35
  UDR1 = data;
36
}
37
38
unsigned char USART_Receive( void )
39
{
40
  /* Wait for data to be received */
41
  while ( !(UCSR1A & (1<<RXC1)) );
42
  /* Get and return received data from buffer */
43
  return UDR1;
44
}

von MWS (Gast)


Lesenswert?

Schnittstelleneinstellungem im OS ok ?
RXD mit TXD verbinden, (ohne uC), kommen die gesendeten Zeichen im 
Terminal zurück ?
Wenn ein Bootloader aktiv ist, alle UART-Register gezielt setzen und 
nicht auf Defaults verlassen.

von Krapao (Gast)


Lesenswert?

rma schrieb:
> //  UCSR1B = (1<<RXCIE1) | (1<<TXCIE1);    Interrupt eischalten
>   UCSR1B = (1<<RXEN1) | (1<<TXEN1);

Nur ein Hinweis für später: Die beiden absoluten Zuweisungen 
hintereinander beissen dich, wenn du dein Programm erweiterst.

MWS schrieb:
> ... alle UART-Register gezielt setzen und nicht auf Defaults verlassen.

Kann ich nur unterstreichen. Du setzt UCSR1C nicht. Damit ist dein 
Datenformat: 5-Bit (Table 80. UCSZ Bits Settings), No Parity, 1 
Stoppbit. Das schafft ein PC nicht so ohne weiteres (spezielles 
Terminalprogramm).

von MWS (Gast)


Lesenswert?

Krapao schrieb:
> Damit ist dein Datenformat: 5-Bit (Table 80. UCSZ Bits Settings), No
> Parity, 1 Stoppbit.

Das Format ist per Default 8 Bit, schau' im Datenblatt unter dem 
Register die Bits in "Initial Value" an. Vorher ablaufende SW könnte das 
aber ändern.

von rma (Gast)


Lesenswert?

MWS schrieb:
> RXD mit TXD verbinden, (ohne uC), kommen die gesendeten Zeichen im
> Terminal zurück ?

Ja die Zeichen kommen wieder zurück.

Wenn ihr sagt die Register gezielt setzen sind dann alle gemeint, oder 
nur spezielle die sicher richtig sein müssen. Wenn es nur spezielle sind 
welche muss ich dann alle setzen?

von Krapao (Gast)


Lesenswert?

@ MWS

Jo danke, die Initial Value (= Werte nach dem RESET) habe ich nicht 
beachtet.

> Wenn ihr sagt die Register gezielt setzen sind dann alle gemeint, oder
> nur spezielle die sicher richtig sein müssen. Wenn es nur spezielle sind
> welche muss ich dann alle setzen?

Setz alle die du für die Funktion brauchst. Beim Lesen einer UART 
Initialisierung (und einer Problembeschreibung) erwartet man, dass die 
Baudrate eingestellt wird, dass das Datenformat eingestellt wird und 
dass der RX und/oder TX eingestellt werden. Eine Zeile weglassen, weil 
man sich auf die Voreinstellungen verlässt, ist IMHO kein gelungener 
Programmierstil. Mir wäre das zu fehlerträchtig und um des machens 
willen eine Kleinigkeit anders zu machen als alle anderen (Tutorial, 
Datenblattbeispiele)... warum? Man möchte doch nicht über eine besonders 
knappe UART-Init diskutieren, sondern ein Problem in den Griff bekommen. 
Dazu benutzt man bewährten Code und kümmert sich dann um eventuelle 
Probleme.

von Krapao (Gast)


Lesenswert?

Atmega64 & UART1... hast du dir die M103C Fuse mal angesehen? Nicht dass 
der AVR kompatibel zum Atmega103 eingestellt ist, denn der hat keine 
UART1!

von rma (Gast)


Lesenswert?

Krapao schrieb:
> Atmega64 & UART1... hast du dir die M103C Fuse mal angesehen? Nicht dass
> der AVR kompatibel zum Atmega103 eingestellt ist, denn der hat keine
> UART1!

Du hast den Fehler gefunden. Dieses Fuse war wirklich gesetzt, deswegen 
konnte ich die UART1 nicht brauchen.

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.