Forum: Mikrocontroller und Digitale Elektronik AVR ATmega32 - UART-Problem


von Reinhard S. (rezz)


Lesenswert?

Hallo zusammen,

mit meinem NET-IO möchte ich per UART/RS232 kommunizieren. Abweichend 
zur Bestückung lass ich ihn mit internem Takt auf 1 MHz laufen.

Quellcode (kopiert aus Beitrag "ATmega32 UART init." 
nachdem ein anderer auch schon nicht ging):
1
#include <avr/io.h>
2
 
3
int main(void)
4
{
5
  UBRRH = (unsigned char)(6>>8);
6
  UBRRL = (unsigned char) 6;  // 9600 Baud
7
 
8
  UCSRB=(1<<TXEN);
9
  UCSRC=(1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
10
 
11
  while(1)
12
  {
13
    while (!(UCSRA&(1<<UDRE)))
14
    {
15
    }.
16
    UDR = 'a';
17
    while (!(UCSRA&(1<<UDRE)))
18
    {
19
    }
20
    UDR = 'b';
21
  }
22
}
Es sollte nun ständig a und b senden, hex also 0x61 und 0x62. Bei mir in 
hterm kommen aber nur 0xC1 und 0xC2 an.

Kann mir jemand einen Tipp geben, in welcher Richtung ich den Fehler 
suchen muss?

von Spess53 (Gast)


Lesenswert?

Hi

>Kann mir jemand einen Tipp geben, in welcher Richtung ich den Fehler
suchen muss?

Dein 1MHz interner Takt ist zu ungenau.

MfG Spess

von Stefan E. (sternst)


Lesenswert?

Reinhard S. schrieb:
> Kann mir jemand einen Tipp geben, in welcher Richtung ich den Fehler
> suchen muss?

9600 Baud bei 1 MHz funktioniert nur mit U2X.

von Reinhard S. (rezz)


Lesenswert?

Spess53 schrieb:
> Hi
>
>>Kann mir jemand einen Tipp geben, in welcher Richtung ich den Fehler
> suchen muss?
>
> Dein 1MHz interner Takt ist zu ungenau.

Bei 16 MHz bekomme ich auch nur 0x89 und 0x85 raus. :(

von Uwe (de0508)


Lesenswert?

Hallo,

das läuft nicht durch den Compiler ohne Fehlermeldung(en) !
1
 while (!(UCSRA&(1<<UDRE)))
2
    {
3
    }.

von Reinhard S. (rezz)


Lesenswert?

Uwe S. schrieb:
> Hallo,
>
> das läuft nicht durch den Compiler ohne Fehlermeldung(en) !
>
1
>  while (!(UCSRA&(1<<UDRE)))
2
>     {
3
>     }.
4
>

Der "." kommt auch nicht im Quelltext bei mir vor. Ist mir jetzt 
rätselhaft, wie der hier rein kommt.

von Uwe (de0508)


Lesenswert?

Hallo Reinhard,

dann ist das ein Copy and Paste error.

Suche doch mal hier im Forum nach AVR-GCC: UART mit FIFO
der Code stammt von PeDa Peter Dannegger und funktioniert mit wenigen 
Anpassungen.

von c-hater (Gast)


Lesenswert?

Reinhard S. schrieb:

> Bei 16 MHz bekomme ich auch nur 0x89 und 0x85 raus. :(

Du mußt natürlich bei 16MHz auch das BR-Register entsprechend angepaßt 
initialisieren...

von Reinhard S. (rezz)


Lesenswert?

Hey,

da bin ich wieder mit einem neuen Problem.

Hier erstmal mein Quelltext:
1
#include "compiler.h"
2
3
void USART_Init( unsigned int baud );
4
unsigned char USART_Receive( void );
5
void USART_Transmit( unsigned char data );
6
7
unsigned char uart_empfangen;
8
unsigned char uart_empfangen_char;
9
10
void USART_Init( unsigned int baud )
11
{
12
  // Set baud rate 
13
  UBRRH = (unsigned char)(baud>>8);
14
  UBRRL = (unsigned char)baud;
15
  // Enable receiver and transmitter 
16
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1 << RXCIE);
17
  
18
  // Set frame format: 8data, 1stop bit 
19
20
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  
21
  uart_empfangen = 0x00;
22
}
23
24
unsigned char USART_Receive( void )
25
{
26
  // Wait for data to be received 
27
  while ( !(UCSRA & (1<<RXC)) )
28
  ;
29
  // Get and return received data from buffer 
30
  return UDR;
31
}
32
void USART_Transmit( unsigned char data )
33
{
34
  // Wait for empty transmit buffer 
35
  while ( !( UCSRA & (1<<UDRE)) )
36
  ;
37
  // Put data into buffer, sends the data 
38
  UDR = data;
39
}
40
41
42
ISR(_VECTOR(14)) {
43
    
44
  uart_empfangen_char = UDR;
45
  uart_empfangen = 0x01;
46
  
47
}
48
49
50
int main(void)
51
{
52
  unsigned char i;
53
  
54
  USART_Init(103);// Extern 16 MHz
55
56
57
  // Enable global interrupts
58
  sei();
59
  
60
61
  while (1) {
62
  
63
    if (uart_empfangen != 0x00) {
64
      uart_empfangen = 0x00;
65
      for (i = 0; i <= 254; i++)
66
        USART_Transmit (i);
67
    }  
68
    
69
  /*  if ( (UCSRA & (1<<RXC)) )    {
70
      d = UDR;
71
      for (i = 65; i <= 69; i++)
72
      USART_Transmit (i);      
73
      
74
    }    
75
  */
76
  }
77
}

Problem: Senden und Empfangen via Pollen hat funktioniert, nur per 
Interrupt mag es nicht.

Ich hab es auch schon mit div. Prüfschleifen/Port-Toggeln probiert und 
dabei rausgefunden, dass die Interrupt-Routine angesprungen wird, jedoch 
das Löschen des Interrupts nicht funktioniert.

Laut Datenblatt und diversen Beispielen sollte dafür ja ein Lesen von 
UDR ausreichen, ist bei mir jedoch nicht der Fall.

Kann mir jemand das Brett vorm Kopf wegnehmen oder spinnt mein Net-IO?

von Stefan E. (sternst)


Lesenswert?

1
ISR(_VECTOR(14)) {
Was soll das? Warum nimmst du nicht wie jeder normale Mensch die dafür 
vorgesehen Namen? Dann hättest du auch nicht wie jetzt den falschen 
Vektor erwischt.

Reinhard S. schrieb:
> Ich hab es auch schon mit div. Prüfschleifen/Port-Toggeln probiert und
> dabei rausgefunden, dass die Interrupt-Routine angesprungen wird,

Sicher nicht.

Reinhard S. schrieb:
> jedoch
> das Löschen des Interrupts nicht funktioniert.

Weil eben die ISR (und damit das UDR-Lesen) überhaupt nicht ausgeführt 
wird. Im Moment landet dein Programm bei einem empfangenen Byte in einer
Endlos-Softreset-Schleife.


PS: Und über "volatile" musst du dich auch mal informieren.

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.