PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Typisches "Aber gestern gings doch noch" (UART)



Furay
20.06.2013, 08:25
Hallo Zusammen,

nachdem nun meine Funktionsaufrüfe klappen (Danke an dieser Stelle nochmal) hat alles wunderbar geklappt, sogar das UART.

Dann hab ich ein paar Funktionen geschrieben usw. Als ich dann den UART inniger Teste wollte musst ich ärgerlicherweise feststellen, das am HTerm nur noch Müll ankommt.
"Also wieder zum Anfang..." dachte ich mir und habs auf die minimal Funktionen (init, senden) beschränkt womit es schon funktioniert hatte.

Auch hiermit kam nur Datenmüll an (siehe Anhang) vielleicht könnt Ihr mir hier helfen? Ich hab die Funktionen aus dem Datenblatt genohmen und angepasst.

Randdaten
* µC ist eine ATMega128L
* Als Clock wird der interne 8MHz Gernerator verwendet
* Die Übertragung läuft über ein FT232R (somit USB)



#include <avr/io.h>

#define F_CPU 8000000UL
//Defines für Einstellungen
#define UART0_BAUD 9600
#define UART0_MYUBRR F_CPU/16/UART0_BAUD-1

#include <util/delay.h>

/************************************************** ***************
* Funktionsname: phy_uart0_Init
*
* BAUDRATE = 9600 BAUD
* Empfänger = Aktiviert
* Sender = Aktiviert
* Rahmengröße = 8 Bit
* StopBit = 1 StopBit
*
************************************************** ***************/
void phy_uart0_Init(void)
{
/* Baudrate festlegen */
UBRR0H = (unsigned char) (UART0_MYUBRR >> 8);
UBRR0L = (unsigned char) UART0_MYUBRR;

/* Receiver und Transmitter aktivieren*/
UCSR0B = (1 << RXEN) | (1 << TXEN);

/* Rahmenformat einstellen: 8 Bit, 1stop bit */
UCSR0C = (3 << UCSZ0) | (1 << USBS0);
}


/************************************************** ***************
* Funktionsname: phy_uart0_Transmit
************************************************** ***************/
void phy_uart0_Transmit(unsigned char data)
{
/* Warte auf Leeren Sende Buffer*/
while ( !( UCSR0A & (1<<UDRE)) )
;

/* Put data into buffer, sends the data */
UDR0 = data;
}

/************************************************** ***************
* Funktionsname: Main
************************************************** ***************/
int main(void)
{
phy_uart0_Init();

while(1)
{
phy_uart0_Transmit('H');

_delay_ms(500);
}
}

Grüße

Furay

Besserwessi
20.06.2013, 09:17
Der Takt des internen Generators in nicht besonders genau - für die UART ist das grenzwertig und kann vor allem bei hohen oder niedrigen Temperaturen zu Fehlern führen. Etwas könnte man verbessern wenn die Frequenz genauer als ab Werk eingestellt ist, oder alternativ im Programm die tatsächliche Frequenz des Exemplars besser getroffen wird.

Ein Versuch wäre es mal den Wert bei F_CPU um etwa 3-5 % zu vergrößern / zu verkleinern.

oberallgeier
20.06.2013, 09:23
Hallo Furay
... UART ... am HTerm nur noch Müll ... Mega128L ... interne 8MHz ... 9600 BAUD ...Vielleicht ists die Hitze ? ;-)

Ich weiß nicht, ob Dein interner Clock genau genug für die 9k6 Bd ist. Vielleicht probierst Du es erstmal mit 2k4 oder so? Das Problem des Baudratenfehlers wurde mal schön anschaulich von uwegw präsentiert (klick) (https://www.roboternetz.de/community/threads/42046-Auswirkungen-von-Baudratenfehlern-(RS232)?p=401602&viewfull=1#post401602) und ich hatte das für meine Megas nachgerechnet (klick) (https://www.roboternetz.de/community/threads/42185-Baudraten-define-xxx-und-einige-Auswirkungen?p=403120&viewfull=1#post403120), die fast immer mit 20 MHz laufen und über nen FT232 prächtig mit 256k plappern können (wenn nicht zuviel andere Interrupts dreinreden). Bei Tests bzw. bei Problemen neige ich auch dazu das UBRR zu definieren und nicht durch den Präprozessor ausrechnen zu lassen - dann weiß ich genau, wo ich bin. Und die ganz kleveren/misstrauischen Kollegen lassen sich den vom Präprozessor errechneten Wert sogar beim Kompilieren ausgeben - ich dachte, ich hätte das sogar schon mal mit der Fehlerquote gesehen *ggg*.

Musste den hübschen Baudratenrechner mit Fehlerangabe/-grenze erst suchen, hier ist der Link dazu. (http://www.gjlay.de/helferlein/avr-uart-rechner.html) Darin siehste auch, warum manche mit dem total krummen 14.7456 MHz-Quarz arbeiten.

Furay
20.06.2013, 11:41
Danke erstmal für die schnellen Antworten.

Ich hab nun das mit den +/- 3 und 5% einstellen versucht - Resultat bleibt gleich.
Von der Geschwindidkeit bin ich jetzt abwärts alles durchgegangen bis runter zu 300. Statt einem H bekomme ich jedoch auch da nur ein "Viereck".

Mit dem Temperaturproblem könntet Ihr vielleicht recht haben... hab das Ding zum Test jetzt erstmal in den Tiefkühle gepackt... mal schauen was er danach sagt.

Es gib zwei Platinen von der Sorte, die Eine betreibe ich aktiv, die andere ist ein Backup. Beide weisen jedoch das gleiche verhalten auf.

- - - Aktualisiert - - -

So ein kleiner Nachtrag... irgendwie schein wirklich der Präprozessor das zu verursachen.
ich hab jetzt die Zahlen ins UBRR0 fix reingeschrieben und schlagartig geht es auch.
Warum es jedoch gestern mit dem gleichen Code ging, kann ich mir nicht erklären.

Weis einer von euch auf die schnelle wie ich den von Präprozessor errechnet wert mir ausgeben lassen kann - würde mich nur interessieren worauf der kommt?

Nochmals danke für die Hilfe. ist ein klasse Forum.

Grüße

Furay

oberallgeier
20.06.2013, 12:20
... irgendwie schein wirklich der Präprozessor das zu verursachen ...Kenn ich, plötzlich klappts (oder nicht) und ich weiß nicht warum. Das sind die dunklen Stunden meiner Zeit - oder die Auswirkungen der dunklen Macht.

Ich weiß nicht, ob Dir das helfen könnte - zumindest trägts nix bei zur Erhellung der Präprozesser(fehl)rechnung. Ich mache das so:


Initialisierung im main:
...
init_uart0 ( (uint16_t)(F_CPU / BAUD / 16 - 0.5) ); //
...
void init_uart0( uint16_t bauddivider ) // UBBR-Rechnung in der uart0.c
...
UBRR0H = bauddivider >> 8;
UBRR0L = bauddivider; // set baud rate
...