PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einsteiger braucht UART Hilfe



Yunus64
20.04.2012, 19:36
Hallo Leute,

sitze seit heute Mittag am UART (bin absoluter Neuling). Hab das Kapitel UART im Datasheet komplett abgearbeitet. Parallel dazu auch http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART hier reingeschaut (deutsche Übersetzung der Registerfunktionen). Nun alles angeschlossen Programmiert und es will einfach nicht funktionieren.

meine Code:


/*
* AVRGCC2.c
*
* Created: 20.04.2012 16:34:54
* Author: Administrator
*/
#include <avr/io.h>
#include <util/delay.h>




#define F_CPU 16000000UL
#define BAUD 9600UL

#include <util/setbaud.h>


int main(void)
{
//UART DEfinitionen

UCSRB = (1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

UBRRL_VALUE;
UBRRL_VALUE;


int x;

while(1)
{
while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
{
}

UDR = 'x'; /* schreibt das Zeichen x auf die Schnittstelle */
}
}

Als Hardware habe ich:
RN-Control 1.4
myAVR USBtoUART

Software:
AVRStudio
HTerm

sternst
20.04.2012, 19:44
UBRRL_VALUE;
UBRRL_VALUE;


Das ist praktisch so, als würdest du schreiben:


42;
42;
Sieht irgendwie nicht wirklich sinnvoll aus, oder?

Yunus64
21.04.2012, 10:20
Hoppla,
da hat sich ein Tippfehler und ein Verständnisfehler eingeschlichen.

Wollte schreiben:

UBRRL_VALUE
UBRRH_VALUE

hatte es so verstanden, dass durch die gesetzte F_CPU und BAUD aus der setbaud.h mit den befehlen UBRRL_VALUE automatisch die richtigen Bits im Register gesetzt werden.

Lange Rede kurzer Sinn, Danke für deine Hilfe

LG
Yunus

Yunus64
03.05.2012, 19:35
Hallo,

also irgendwie will das immer noch nicht so funzen. Habe mittlerweile mittels Loopback die PC-Seite gecheckt, da scheint alles in Ordnung zu sein. Ausserdem habe ich erfahren, dass F_CPU vor dem delay.h header stehen soll, auch das habe ich geändert. Aber der µC sendet einfach nichts an meinen PC.

Terminal: HTerm ist auf 8N1 9600Baud und Flow Control gestellt.




#include <avr/io.h>
#define F_CPU 16000000
#define BAUD 9600

#include <util/delay.h>
#include <util/setbaud.h>



int main(void)
{
//UART DEfinitionen

UCSRA &= ~(1<<U2X);
UCSRB = (1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

UBRRL = UBRRL_VALUE;
UBRRH = UBRRH_VALUE;

while(1)
{
while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
{
;
}
UDR = 'x';

}

shedepe
03.05.2012, 21:38
Hey also als erstes musst du wissen welche Einstellungen du für den UART verwenden willst. Also wie viele Stopbits, Datenbits, Parity, Handshake usw.
Die genauen Einstellungen findest du im Datenblatt zum verwendeten Atmega32 Controller, das Anfänger jedoch schnell erschlägt.
Ich poste dir hier mal die Einstellungen die ich verwende:




UBRRH = ((F_CPU +BAUD*8 )/ (BAUD * 16L) - 1) >>8;
UBRRL = ((F_CPU +BAUD*8 )/ (BAUD * 16L) - 1) & 0xFF;

UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
UCSRC = (1<<UCSZ0) | (1<<UCSZ1);




Die Einstellungen schalten den Sender und Empfäger ein und schalten den Empfangsinterupt ein.
Es sind 8 Datenbits eingestellt, Parität Disabled und ein Stopbit eingestellt.

Die Baudrate musste du oben unter der F_CPU definition noch definieren.

shedepe
03.05.2012, 21:42
PS. nur der vollständigkeit halber, hier noch das Datenblatt:
www.atmel.com/Images/doc2503.pdf

Die benötigten Informationen findest du ab Seite 159

Yunus64
03.05.2012, 22:02
Hallo shedepe,

das Datenblatt habe ich mir bereits sehr geduldig zu Gemüte geführt und bin der Meinung, mir scheint was du da geschrieben hast unterscheidet sich auch nicht wesentlich von meiner Version. Ich sehe hier einen Unterschied bei der definition der register UBRRL und UBRRH (hier habe ich die header Datei verwendet um mir Arbeit zu ersparen, aber ich werde es morgen mal auf "manuellem" Wege probieren. Der zweite unterschied ist das du beim schreiben in das Register UCSRC nich das Bit URSEL gesetzt hast, im Datenblatt jedoch steht, dass dies notwendig ist?

LG
Yunus

shedepe
03.05.2012, 22:18
Soweit ich mich entsinne ist es nicht nötig URSEL explizit zu setzen, da es bereits 0 ist. Probier es einfach noch mal so.

Kampi
03.05.2012, 22:19
Hi,

also ich habe jetzt auch zwei Stunden rumprobiert und mich gewundert warum bei mir nur Zeichenmüll rauskam. Ich hatte erst

UCSRB = (1<<RXEN) | (1<<TXEN);
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
UCSRC = (1<<URSEL)

da stehen und damit funktioniert es NICHT.
Ändere ich es auf

UCSRB = (1<<RXEN) | (1<<TXEN);
UCSRC = (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0);

um funktioniert es (nur so am Rande).
Hier hast du ein funktionierendes Programm was du verwenden kannst:



/*
* Hallo Welt.c
*
* Created: 03.05.2012 20:46:19
* Author: Daniel
*/

#define F_CPU 16000000UL // CPU Takt für das delay

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>
#include <stdlib.h>

char data[50] = "Hallo"; // Text der ausgegeben werden soll
int lenght = 0x00;

int main(void)
{
UART_Init();

while(1)
{
Send_UART_Char(data);
_delay_ms(500);
}
}

void UART_Init()
{
UCSRB = (1<<RXEN) | (1<<TXEN); // Rx und Tx aktivieren
UCSRC = (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0); // 8 Bit Nachrichtenlänge einstellen


UBRRH = 0x00;
UBRRL = 0x33; // Baudrate auf 19200 festlegen
}


void Send_UART_Char(char data[])
{
char Counter;

lenght = strlen(data);

while(Counter < lenght)
{
while (!(UCSRA & (1<<UDRE)));
UDR = data[Counter];
Counter++;
}

Counter = 0x00;
while (!(UCSRA & (1<<UDRE)));
UDR = 0x0A;
while (!(UCSRA & (1<<UDRE)));
UDR = 0x0D;
}


Ich hab halt alles vom UART händlich gemacht (finde ich zum ersten lernen bischen besser als die "fertigen" Libs zu verwenden. Da versteht man den Ablauf bischen besser.
Vergleich das mal mit deinem Programm. Von der void Send_UART_Char brauchst du dann nur die Zeilen nehmen die nur 1 Zeichen senden (der Rest ist eine Schleife womit ein ganzer String gesendet wird). Ein einzelnes Zeichen sendest du so:

while (!(UCSRA & (1<<UDRE)));
UDR = 0x0D;

Ich denke du hast sicher nur eine Kleinigkeit verkehrt gemacht :)

sternst
03.05.2012, 23:33
Ich hatte erst

UCSRB = (1<<RXEN) | (1<<TXEN);
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
UCSRC = (1<<URSEL)

da stehen und damit funktioniert es NICHT.
Natürlich nicht. Die mittlere Zeile schreibt was nach UBRRH, und die letzte Zeile setzt die Datengröße auf 5-Bit.



Terminal: HTerm ist auf 8N1 9600Baud und Flow Control gestellt."Flow Control"? Du hast doch gar kein "Flow Control".

Yunus64
04.05.2012, 13:26
"Flow Control"? Du hast doch gar kein "Flow Control".

Ich meinte natürlich, das der Haken bei Flow Control NICHT gesetzt ist.

Kampi ich habe deinen Code mittlerweile auch probiert der will auch nicht. Ich werde nachher mal testen ob der AVR überhaupt noch lebt... ich weiss echt nicht woran es noch liegen könnte :/

LG
Yunus

Kampi
04.05.2012, 14:19
Prüf mal ob die Verbindung in Ordnung ist. Verbinde direkt vor dem AVR Rx und Tx und check dann mal ob der Loopback funktioniert. Wenn er funktioniert ist die Leitung in Ordnung und das Problem ist der AVR.

Inventor76
04.05.2012, 15:22
Auch auf die Gefahr hin dass es anscheinend nur eine Lapalie ist aber hast du bei Hterm den richtigen Com-Port eingestellt?

Yunus64
04.05.2012, 23:13
Prüf mal ob die Verbindung in Ordnung ist. Verbinde direkt vor dem AVR Rx und Tx und check dann mal ob der Loopback funktioniert. Wenn er funktioniert ist die Leitung in Ordnung und das Problem ist der AVR.

Wurde bereits gecheckt und funktioniert.


Auch auf die Gefahr hin dass es anscheinend nur eine Lapalie ist aber hast du bei Hterm den richtigen Com-Port eingestellt?

COM ist auf 3 gestellt, da der Loopback auch funktioniert hat denke ich da sollte alles passen.

Bin leider noch nicht dazu gekommen den AVR auf Funktion zu testen, wollte mich aber schonmal für die rege Anteilnahme bedanken. Für mich kommen als Fehlerquelle nur noch AVR MAX232 oder RN-Board in frage

LG
Yunus

Kampi
04.05.2012, 23:17
Um einen Fehler des MAX232 auszuschließen, hatte ich vorgeschlagen das du den Controller aus der Schaltung rausnimmst und direkt dort wo Rx und Tx des Controllers war, eine Brücke reinsetzt. Anschließend machst du den Loopbacktest nochmal. So testest du das Kabel vom PC bis zum MAX232 rein und vom MAX232 raus die Strecke zum Controller und wieder zurück. Und wenn das dann Funktioniert, weißt du ganz sicher das der Fehler am Controller ist. Welches RN-Board verwendest du? Mein Code wurde direkt auf dem RN-Control getestet.

Yunus64
05.05.2012, 04:31
Das mir soetwas nicht einfällt :) ... Also es scheint definitiv der MAX232 defekt zu sein. Wie kriege ich ersatz? Muss es GENAU der selbe sein also MAX232CPE ?

Kampi
05.05.2012, 09:21
Hast es ausprobiert :)?
Du musst nicht haargenau den selben MAX232 nehmen. Du kannst auch jedes andere IC was 232 im Namen hat nehmen (nen FT232 aber nicht das ist ein UART zu USB Wandler :) )

Inventor76
05.05.2012, 09:53
Versuchs trotzdem mal mit COM 1. Ist immerhin bei den meisten pc für die serielle Schnittstelle. Mehr als das es auch nicht klappt kann ja nicht sein.