PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART: PC->µC



Goblin
18.04.2008, 16:41
Hallo!

Ich versuche mich gerad ein wenig an C und möchte gern Bytes vom PC empfangen und am PortC durch eine LED-Leiste anzeigen lassen. Hier mein Code (Aus verschiedensten Tutorials zusammenkopiert):



#include <inttypes.h>
#include <avr/io.h>
#define F_CPU 7372800L
#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille

int main(void)
{
UCSRB |= (1<<RXEN); // UART RX einschalten
UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1

UBRRH = UBRR_VAL >> 8;
UBRRL = UBRR_VAL & 0xFF;
DDRC = 0xFF;
PORTC = 255;


while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar
;
{
PORTC = UDR;
};
}

Was passiert ist dass die LED-Leiste GANZ kurz leuchtet (programmstart) und dann aus ist. Ich habe schon geschaut, ob es vllt mit 1200 Baud (im Terminal-Prog eingestellt) läuft, wegen des /8-Fuses, aber ist nicht. Hab den Ausgang (TXD) der USB-Uart-Bridge an RXD am Mega8 angeschlossen.
Kann mir wer sagen, was ich falsch mache? Hab schon hier im Forum viel rumgelesen, aber dabei keine neuen Erkenntnisse gewonnen.

geronet
18.04.2008, 16:57
Da is wohl ein ; zuviel nach dem while ;)

Goblin
18.04.2008, 17:04
Nun guuut, aber das Entfernen desselben hat keine sichtbaren Resultate herbeigeführt.

m.a.r.v.i.n
18.04.2008, 21:30
Das ; war schon in Ordnung.
Da fehlt noch eine Endlos while Schleife. Sonst wird dein Programm nur einmal durchlaufen.


while(1)
{
while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar
;
{
PORTC = UDR;
}
}

Goblin
18.04.2008, 21:35
geht nicht auch ne do/loop-schleife?

Pascal
18.04.2008, 22:20
Das ist doch vollkommen egal, ob do loop oder while oder for, hauptsache endlos. Machen tun die doch in dem Fall eh alle dasselbe.

Felix G
19.04.2008, 09:58
Aber das Semikolon vor der geschweiften Klammer muss trotzdem weg, sonst gehört sie nicht mehr zum while und der Block wird immer ausgeführt.

Goblin
20.04.2008, 18:07
Hm ich hab das jetzt mal ausprobiert. Wenn ich den USB/RS232-Adapter nur mit der Datenleitung mit dem µc verbinde und nicht mit GND, ist auf PortC Disco. Allerdings leuchtet gar nichts, wenn ich GND verbinde und Daten sende... Ich vermute langsam dass es nen Hardware-Problem ist. Ich werd diesen ominösen Adapter mal per Oszi unter die Lupe nehmen....

drew
22.04.2008, 20:07
Hallo,
das mit der Seriellen Schnittstelle am PC musst du erst mal in den Griff bekommen.
Verbinde mal RX und TX von der RS232. Wenn du dann was vom PC absendest solltest du es auch gleich wieder empfangen.

Ich hab nicht ganz verstanden, wie du den Atmega an den PC angeschlossen hast. Hast du einen Pegel-Wandler drin, ala MA232 oder setzt du das Signal direkt auf USB um ala FTDI?

Drewle

Goblin
23.04.2008, 21:17
Nen... Wie ich IIRC einige Male schrob, benutze ich den MySmartUsb von "MyAvr.de". Das ist eine RS232/SPI/TWI/Programmer- Eierlegende-Wollmilchsau für den USB-Port. Es steht als normaler Com-Port am Rechner zur Verfügung. Ich hab es jetzt auch mal mit dem Oszi durchgemessen und festgestellt: Das Teil schmeisst nur GND raus ^^ Hab mich schon mit dem Hersteller in Verbindung gesetzt.. Hoffe ich krieg Ersatz.

Goblin
25.04.2008, 19:35
Ich hatte zur Sicherheit nochmal TX und RX verbunden: Kommt nix zurück. Hab den Adapter gestern an den Hersteller geschickt. Der hat mir vorher Reparatur oder Austausch zugesichert.

Goblin
11.05.2008, 09:12
So ich habe den Adapter wieder und er funktioniert nun auch. Ich habe nun nen Prog geschrieben, welches sich aus einem Datenstream, der über uart gesendet wird an einer bestimmten Stelle 12 Bytes raussucht und daraus 12 Software-PWMS zaubert. Die Software-PWMS funktionieren, wenn ich die PWM-Werte, die in einem Array stehen, hart code. Wenn ich meine Daten per RS232 sende, leuchten die 4 RGB-LEDS irgendwie nicht so wie sie sollen. Eine beispielsweise ist IMMER grün. Ich poste hier mal meinen Code für die UART-Abfrage und die Variablen, die ich benutze:



volatile uint16_t bytecnt; // Zaehlt die Bytes des Datensatzes
volatile uint8_t mybytes = 0; // Wieviele Bytes hab ich schon empfangen?
volatile uint8_t pwms[12]={0,0,0,0,0,0,0,0,0,0,0,0}; // Array mit den PWM-Werten
volatile const uint16_t startwert = 1; // Hier im Datensatz beginnen meine 12 Bytes


Ein Datensatz ist also 255+Byte+Byte+...+Byte
An einer definierten Stelle darin stehen die 12 Bytes (hintereinander), die mich interessieren. Diese Stelle steht in der Konstante "Startwert". In diesem Fall direkt hinter der 255.
Hier der Code der den Uart ausliest. Der ist das einzige was ausser der Timer-ISR läuft:



while(1)
{
while (!(UCSRA & (1<<RXC))) // Warten bis Zeichen verfuegbar
;
{
if(UDR==255) bytecnt=0; // Wenn eine 255 gesendet ist, faengt Datensatz von vorne an
bytecnt++; // Bytes zaehlen
if (bytecnt==startwert) mybytes++; // Hier ist mein Byte #1
if (mybytes > 0) // Wenn Byte #1 gefunden wurde...
{
pwms[mybytes-1] = UDR; // ...Byte in PWM-Array schieben
mybytes++; // ...Habe 1 Byte mehr gesammelt
}
if (mybytes == 13) mybytes = 0; // Wenn 12 Bytes da sind, sind die Daten komplett
}
}


Der Plan ist:
Wenn das Byte das empfangen wurde = 255 ist, wird der Zähler, der die Gesamt-Bytes des Datensatzes mitzählt auf Null gesetzt.
Wenn der Gesamt-Byte-Zähler = dem Startwert der interessanten Region ist, geht der Zähler, der die interessanten und damit übernommenen Bytes zählt auf 1.
Das ermöglicht, dass ab jetzt die folgende IF-Abfrage positiv wird, sodass Das aktuelle Byte ins Array geschrieben wird und mybytes, also die Anzahl der empfangenen Bytes erhöht wird. Wenn 12 Bytes empfangen wurden dann wird mybytes wieder 0, sodass keine weiteren Bytes übernommen werden.

Hab ich da nen logischen Fehler drin? Oder nen Implementierungs-Fehler? Oder ist am Ende der Code in Ordnung und meine Sende-Software macht Mist? Oder liegt es vllt daran, dass ich "UDR" lieber am Anfang der Schleife in eine Variable packen sollte und mit dieser weiterarbeiten sollte?

Danke für eure Hilfe!