Forum: Mikrocontroller und Digitale Elektronik UART bei ATmega/88 Atmega168


von gast (Gast)


Lesenswert?

Hallo,

ich versuche gerade, einen ATmega88 gegen einen ATmega168 zu tauschen. 
Dabei gibt's Probleme mit dem UART. Der folgende Code funktioniert beim 
Atmega88 wunderbar, beim ATmega168 aber nicht:

1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <inttypes.h>
5
6
#define F_CPU 18432000
7
#define __OPTIMIZE__
8
9
// Baudrate
10
#define BAUD 115200
11
12
// Berechnungen zur Baudrate:
13
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
14
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
15
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
16
 
17
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
18
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
19
#endif
20
21
//Forwarddeklarationen 
22
void USART_Init( unsigned int ubrr);
23
void USART_Transmit( unsigned char data);
24
unsigned char USART_Receive( void );
25
26
char text1[4];
27
28
int main() 
29
{
30
        //USART initialisieren
31
  USART_Init(UBRR_VAL);
32
  uint8_t i=0;
33
34
  while(1)
35
  {
36
      i++;        
37
      itoa(i, text1, 16);
38
      USART_Transmit(text1[0]);
39
      USART_Transmit(text1[1]);            
40
      USART_Transmit(0x0A); //LF
41
      USART_Transmit(0x0D); //CR
42
        }        
43
  return 0;
44
}
45
46
void USART_Init( unsigned int ubrr) 
47
{
48
  //Set baud rate
49
  UBRR0H = (unsigned char)(ubrr>>8);
50
  UBRR0L = (unsigned char)ubrr;
51
  //Enable receiver and transmitter
52
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
53
  // Set frame format: 8data, 2stop bit
54
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
55
}
56
57
void USART_Transmit( unsigned char data )
58
{
59
  //Wait for empty transmit buffer
60
  while ( !( UCSR0A & (1<<UDRE0)) );
61
  //Put data into buffer, sends the data
62
  UDR0 = data;
63
}
64
65
unsigned char USART_Receive( void )
66
{
67
  // Wait for data to be received
68
  while ( !(UCSR0A & (1<<RXC0)) );
69
  // Get and return received data from buffer
70
  return UDR0;
71
}

die Routinen USART_Init, USART_Transmit und USART_Receive habe ich aus 
dem Datenblatt zum ATmega 48/88/168 entnommen, die Application Note 
"AVR095 - Migrating between ATmega48, 88 and 168" ist mir bekannt - sie 
enthält leider nichts, was auf einen Unterschied am UART zwischen den 3 
Prozessoren hinweisen würde. Andere Baudraten oder 
Stopbitkonfigurationen funktionieren mit dem ATmega88 auch, nicht aber 
mit dem 168. Ich benutze AVR Studio und achte darauf, mein device 
richtig einzustellen, wenn ich den Prozessor wechsle, auch am Programmer 
(usbprog am ISP) stelle ich immer zwischen dem 88 und dem 168 um.

... Weiss jemand, was ich noch ändern könnte ? - Oder, was ich übersehen 
habe?

von Stefan E. (sternst)


Lesenswert?

Fuses vergleichen.

von Seppl (Gast)


Lesenswert?

Checke mal ob die ISR-Vektoren stimmen.
Testweise Uart per Polling abfragen.....

Gruß

Seppl

von Hc Z. (mizch)


Lesenswert?

Zwar keine Antwort auf Deine Frage, aber eine Anmerkung:
1
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
wird für Baudrates zwischen 4096 und 65535 falsche Werte liefern 
(Integer-Überlauf).  Verwende doch einfach die Makros aus 
<util/setbaud.h>.

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.