Forum: Mikrocontroller und Digitale Elektronik UART Verzweifelung


von Matthias (Gast)


Lesenswert?

Hallo zusammen.

Ich nutze das STK500 mit AVR Studio und dem ATmega16 drauf. Den UART 
Port vom Controller habe ich direkt mit der Spare RS232 Schnittstelle 
des STK500 verbunden. Nun will ich einfach Zeichen senden über UART, 
aber das funktioniert einfach nicht! Es kommen immer andere Zeichen an! 
Habe auch schon verzweifelt im Forum nach einer Lösung gesucht, aber 
nichts gefunden, was mir da weiter hilft.
1
#include <avr/io.h>
2
#define FOSC 4000000// Clock Speed
3
#define BAUD 9600
4
#define MYUBRR FOSC/16/BAUD-1
5
6
7
void USART_Transmit( unsigned char data )
8
{
9
  /* Wait for empty transmit buffer */
10
  while ( !( UCSRA & (1<<UDRE)) )
11
    ;
12
  /* Put data into buffer, sends the data */
13
  UDR = data;
14
}
15
16
void USART_Init( unsigned int ubrr)
17
{
18
  /* Set baud rate */
19
  UBRRH = (unsigned char)(ubrr>>8);
20
  UBRRL = (unsigned char)ubrr;
21
  /* Enable receiver and transmitter */
22
  UCSRB = (1<<RXEN)|(1<<TXEN);
23
  /* Set frame format: 8data, 2stop bit */
24
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
25
}
26
27
int main( void )
28
{
29
  USART_Init ( MYUBRR );
30
  USART_Transmit(0x48);
31
  USART_Transmit(0x61);
32
  USART_Transmit(0x6C);
33
  USART_Transmit(0x6C);
34
  USART_Transmit(0x6F);
35
}

Einstellungen:
Frequency: 4000000
SUT_CKSEL: Int. RC Osc. 4 MHz; Start-up time 6 CK + 64ms
Fuses: High 0x99 Low 0xE3

Über UART kommen folgende Zeichen nun an: C8 E1 E1 EC EF

Was mache ich da genau falsch? Fehlt mir da irgendwo eine Einstellung im 
AVR Studio? Hoffe mir kann irgendwer sagen, was ich falsch machen, denn 
ich finde das Problem einfach nicht.

MFG
Matthias

von Peter D. (peda)


Lesenswert?

Das ist der Fehler:

Matthias wrote:
> SUT_CKSEL: Int. RC Osc. 4 MHz;

Schließe einen Quarz an und die UART funktioniert.


Peter

von Mike (Gast)


Lesenswert?

Moin,

als erstes ist mir in der Definition für die Baudrate ein Formelfehler 
aufgefallen, versuche mal:

#define MYUBRR (FOSC/(16*BAUD) - 1);

dann willst du als Format 8N2 verwenden.

Beim Atmega8 sieht dies so aus, sonst schau eben ins Datenblatt:

// Format: 8N2
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) | (1<<USBS);

Da du den Wert MYUBRR definiert hast, kannst dir die Übergaben sparen:

Beispiel:

void USART_Transmit()
{
  /* Wait for empty transmit buffer */
  while ( !( UCSRA & (1<<UDRE)) )
    ;
  /* Put data into buffer, sends the data */
  UDR = data;
}


int main( void )
{
  USART_Init ();
  USART_Transmit(0x48);
  USART_Transmit(0x61);
  USART_Transmit(0x6C);
  USART_Transmit(0x6C);
  USART_Transmit(0x6F);
}

So müsste es klappen.

Gruß Mike

von Mike (Gast)


Lesenswert?

Moin nochmal, ich muss mich eben korrigieren, meinte natürlich mit der 
definition :

void USART_Init()
{
  /* Set baud rate */
  UBRRH = (unsigned char)(ubrr>>8);
  UBRRL = (unsigned char)ubrr;
  /* Enable receiver and transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 2stop bit */
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

int main( void )
{
  USART_Init ();
  USART_Transmit(0x48);
  USART_Transmit(0x61);
  USART_Transmit(0x6C);
  USART_Transmit(0x6C);
  USART_Transmit(0x6F);
}

von Robert T. (robertteufel)


Lesenswert?

Es gaebe da noch eine Moeglichkeit die Sache anders zu testen, ist aber 
nur bei konstanter Temp und konstanter Spannung eine echte Option.
In mehreren Testlaeufen den Wert fuer FOSC um jeweils 1% zu aendern also 
40400000, dann 40800000, natuerlich auch in die andere Richtung 3960000 
usw. Wenn das Programm ansonsten richtig ist, dann wird der UART 
ploetzlich funktionieren. Die Tests weiter in dieselbe Richtung 
fortfuehren, bis er nicht mehr funktioniert. Den mittleren funktionial 
Wert nehmen, also z.B. 3920000. Soweit die Spannung sich nicht aendert 
(also keine Batterie!), sollte das dann funktionieren.

Es gibt einige interne Oscillatoren, die hinreichend genau sind fuer 
eine serielle Schnittstellen, der Osc des AVR gehoert nicht dazu ! :-(
Aehnliche Teile mit genauerem Osc waeren z.B. die Teile von Silabs oder 
die LPC900 von NXP. Beide sind mit einem schnellen 51-er core bestueckt.
Nur so zur Info.

Wie Peter also schon gesagt hat, ein externer Osc muss dran, mindestens 
wenn die Kommunikation ueber Spannung und Temperaturaenderungen 
zuverlaessig sein soll.

Robert Teufel
Partner in Silicon Valley gesucht?
Ich stehe gerne zur Verfuegung.
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Meine ARM/Cortex Webseite: http://www.lpc2000.com

von Matthias O. (ostinator)


Lesenswert?

Mhm, dann werde ich mir wohl mal einen besorgen und anschließen bzw. 
kann ich die Frequenz nicht sogar vom STK500 holen?

Wenn ich übrigens MYUBRR nicht übergebe, dann führt das zu einer Warnung 
und das ganze funktioniert dann gar nicht mehr.

Zumindest brauche ich mich jetzt nicht mehr wundern, wieso der Code aus 
dem Datenblatt nicht funktioniert.

von Michael U. (amiga)


Lesenswert?

Hallo,

40400000
es gehen größere Sprünge zum Test bei üblichen PC-UARTS.
Mit 3600000, 3800000, 4000000, 4200000, 4400000 usw, habe ich bisher 
immer schnell die Mitte gefunden.
Mein einer Mega32 schwingt auf ca. 4,4MHz, der Mega16 auf 4,3MHz.
Nutze ich öfter, wenn ich zum Debug mal schnell meinen Debug-UART nutze.

Der gefundene Mittelwert bleibt im Zimmer auch "ewig" stabil genug.

@ Robert Teufel (robertteufel): 40 400 000
Wo hast Du den 40MHz AVR her??? ;-))

Gruß aus Berlin
Michael

von Matthias O. (ostinator)


Lesenswert?

Happy
#define FOSC 4160000// Clock Speed

damit geht es :) Ist zwar keine saubere Lösung, aber zumindest weiß ich 
nun, dass mein Code nicht falsch ist.
Werde mir morgen dann mal einen Quarz besorgen.

DANKE!!!

von Peter D. (peda)


Lesenswert?

Wenn ich micht richtig erinnere, haben die alten ATmega verschiedene 
Calibrationsbyte für die verschiedenen RC-Frequenzen.

Beim Reset wird aber nur der Wert für 1MHz automatisch geladen.

Wenn man unbedingt den RC verwenden will, muß man also den Programmer 
anweisen, daß er das Calibrationsbyte für 4MHz in den Flash oder EEPROM 
lädt und dann nach dem Reset dort auslesen und setzen.

Die aktuellen ATmega164P laufen immer mit 8MHz und können per Vorteiler 
runter gesetzt werden (default Vorteiler 8 = 1MHz).


Peter

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.