Forum: Mikrocontroller und Digitale Elektronik XMega USART Probleme


von Wolfgang K. (polarwolf_94)


Lesenswert?

Hallo,
Ich habe eine Frage.
Ich habe mit dem USART ein Problem.
Und zwar kann ich senden und das Funktioniert super, nur Empfangen kann 
ich nicht.
Köönts ihr bitte mal drüberschauen, weil vll habe ich ja einen Fehler.
Programmieren tu ich einen ATXMega128A3 mit C



Code:
Konfiguration des USART's
//-----------USART-------------

//PORTD.OUTSET = PIN3_bm;                        //D2-TX High setzen
OSC.CTRL |= OSC_RC32MEN_bm;                      //Oscilator auf 32MHz 
stellen
CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc;

PORTD.DIRSET = PIN3_bm;                        //D2-TX als Ausgang 
definieren
PORTD.OUTSET = PIN3_bm;                        //Ausgang auf High setzen
PORTD.DIRCLR = PIN2_bm;                        //D-RX als Eingang 
definieren
PORTD.DIRSET = PIN1_bm;                        //Reset vom 
Grafikcontroller
//----------Baudrate------------------------
USARTD0.BAUDCTRLA = 0b11010001;
USARTD0.BAUDCTRLB = 0b00000000;

USARTD0.CTRLA = 0b00000000;                      //nicht zu verwenden
USARTD0.CTRLB = USART_TXEN_bm | USART_RXEN_bm;   //RX und TX aktivieren
USARTD0.CTRLC = USART_CHSIZE_8BIT_gc;            //8 Bit modus



void Touch()                  //Controller fragt den Grafikcontroller, 
wo die Fläche berührt wurde und gibt dementsprechend die X und Y-Achse 
zurück
{
unsigned int x_pos1, x_pos2, y_pos1, y_pos2;
unsigned char to[2] = {0x6F, 0x05};

for (int x = 0; x < 2; x++)
{
USARTD0.DATA = to[x];
_delay_ms(3);
}


while(!(USARTD0.STATUS & USART_RXCIF_bm));
x_pos1=USARTD0.DATA;
while(!(USARTD0.STATUS & USART_RXCIF_bm));
x_pos2=USARTD0.DATA;
while(!(USARTD0.STATUS & USART_RXCIF_bm));
y_pos1=USARTD0.DATA;
while(!(USARTD0.STATUS & USART_RXCIF_bm));
y_pos2=USARTD0.DATA;

//Die 4x8Bit-Bytes müssen nun umgewandelt werden in zwei 16Bit-Bytes
x_pos=(x_pos1*256+x_pos2);
y_pos=(y_pos1*256+y_pos2);
_delay_ms(200);
return (x_pos,y_pos);

}


x_pos und y_pos sind am Anfang des Programmes definiert als unsigned int
Ist das so korrekt oder ist da ein Fehler drinnen?
Würdet Ihr etwas anderes machen?

: Bearbeitet durch User
von Detlev T. (detlevt)


Lesenswert?

Was heißt "empfangen kann ich nicht"? IMO fehlt in deiner Routine auf 
jeden Fall das "manuelle" zurücksetzen des RXCIF, weil keine ISR 
aufgerufen wird.

von spess53 (Gast)


Lesenswert?

Hi

>PORTD.DIRCLR = PIN2_bm;                        //D-RX als Eingang
>PORTD.DIRSET = PIN3_bm;                        //D2-TX als Ausgang

ist unnötig. Datenblatt:

CTRLB – Control register B

Bit 4 – RXEN: Receiver Enable
... The receiver will override normal port operation for the RxD pin, 
when
enabled.

Bit 3 – TXEN: Transmitter Enable
...The transmitter will override normal port operation for the TxD pin, 
when
enabled.

MfG Spess

von Wolfgang K. (polarwolf_94)


Lesenswert?

Detlev T. schrieb:
> Was heißt "empfangen kann ich nicht"? IMO fehlt in deiner Routine auf
> jeden Fall das "manuelle" zurücksetzen des RXCIF, weil keine ISR
> aufgerufen wird.

Naja.  Ich habe ein touch-display und wenn ich was sende, dann sehe ich 
das am Display.
Und wenn ich den obrigen code dem grafikcontroller schicke, dann sendet 
er mir die touch-Koordinaten.

Das heißt, wie sollte es aufgebaut werden mit der isr?
Also wie sollte der code ausschauen?

von Wolfgang K. (polarwolf_94)


Lesenswert?

void Touch()                  //Controller fragt den Grafikcontroller, 
wo die Fläche berührt wurde und gibt dementsprechend die X und Y-Achse 
zurück
{
unsigned int x_pos1, x_pos2, y_pos1, y_pos2, Statusfertig=0;   //Daten 
dient als Zwischenspeicher der USART-Daten/Position dient als Springer 
der If()-Bed.
unsigned char to[2] = {0x6F, 0x05};

for (int x = 0; x < 2; x++)
{
  USARTD0.DATA = to[x];
  _delay_ms(3);
}

if(Position==1)
{
x_pos1=Daten;
}

if(Position==2)
{
x_pos2=Daten;
}

if(Position==3)
{
y_pos1=USARTD0.DATA;
}

if(Position==4)
{
y_pos2=USARTD0.DATA;
Position=0;
Statusfertig=1;
}

if(Statusfertig==1)
{
//Die 4x8Bit-Bytes müssen nun umgewandelt werden in zwei 16Bit-Bytes
x_pos=(x_pos1*256+x_pos2);
y_pos=(y_pos1*256+y_pos2);
_delay_ms(200);
return (x_pos,y_pos);
Statusfertig=0;
}
}

ISR(USARTD0_RXC_vect)
{
  Daten=USARTD0.DATA;
  Position++;
}



Wäre es so besser?
Hab es probiert, aber es ist nichts herausgekommen

von Gerhard G. (g_g)


Lesenswert?

Hallo,

Wolfgang Karner schrieb:

> void Touch()      //Controller fragt den Grafikcontroller,
> wo die Fläche berührt wurde und gibt dementsprechend die X und Y-Achse
> zurück

der Grafikcontroller kann keine Daten zurück liefern.
Das macht doch der TOUCH SCREEN CONTROLLER.
Das Senden der Daten vom TOUCH SCREEN CONTROLLER kann ich 
nachvollziehen.
Das Empfangen aber nicht! Der TOUCH SCREEN CONTROLLER kann keine vom 
USART kommenden Daten  auswerten noch verarbeiten. Außer die für die 
AD-Wandlung nötigen Registerinformationen. Die empfangenen Daten vom 
TOUCH SCREEN CONTROLLER zum Grafikcontroller zu senden um z.B. ein 
Kästchen anzuzeigen könnte mehr Sinn machen.

Erklär uns bitte das Senden genauer.

Gruß G.G.

von Stefan F. (Gast)


Lesenswert?

>>PORTD.DIRSET = PIN3_bm;                        //D2-TX als Ausgang

> ist unnötig. Datenblatt:

>Bit 3 – TXEN: Transmitter Enable
>...The transmitter will override normal port operation for the TxD pin,
>when enabled.

Doch, das ist nötig. Der Transmitter steuert nämlich nicht die 
Übertragungsrichtung des I/O Pins (im Gegensatz zur ATmega Reihe).

von Gerhard G. (g_g)


Lesenswert?

Hallo,

hab mich leider vertan:

> Erklär uns bitte das Senden genauer.


Erklär uns bitte das Empfangen genauer.


Gruß G.G.

von Wolfgang K. (polarwolf_94)


Lesenswert?

Also.
Wenn ich am touch-display ankomme, wird der port d0 auf gnd gesetzt. 
Also steuere ich zu dem zeitpunot den controller an.
Aleo wenn der pin d0 auf gnd ist, schicke ich dem controller den ersten 
code.  Mit dem einen befehl sage ich, dass es um den touch geht und mit 
dem zweitem befehl sage ich, dass er mir die koordinaten zurück geben 
soll.
Dann schickt er mir über rx- die daten.  Das sind zweimal die 
x-Koordinaten und zweimal die y Koordinaten.    Diese speichere ich ab 
und werte sie am schluss aus.    Darum x_pos1 und x_pos2.
Dann sage ich halt x-pos=xpos1x256+xpos2.
Nur bekomme ich das mit dem empfangen nicht ganz so hin.  Ich glaube, 
dass das isr falsch ist oda so.   Aber dazu kenne ich mich leider zu 
wenig noch aus.
Gibts noch unklarheit?

von Gerhard G. (g_g)


Lesenswert?

Hallo,


Wolfgang Karner schrieb:
> touch-Display


du schreibst irgendwo ich habe ein Touch-Display.

> Naja.  Ich habe ein touch-display und wenn ich was sende, dann sehe ich
> das am Display.
> Und wenn ich den obrigen code dem grafikcontroller schicke, dann sendet
> er mir die touch-Koordinaten.


Ist das ein intelligentes Display zum Beispiel so was, das Befehle zum 
Display per RS-232 sendet?

http://www.lcd-module.de/



Gruß G.G.

von Wolfgang K. (polarwolf_94)


Lesenswert?

Das ist das display von ribu.at

von Wolfgang K. (polarwolf_94)


Lesenswert?

Den Controller habe ich bei RIBU.at bestellt.
Es ist ein Picaso SGC Grfikcontroller.
Mit diesem kommuniziert man mit dem USART.
Das ist alles intern verbunden.
Wenn ich etwas hinschicke, dann zeigt es genau das an, was ich möchte.
Jetzt schicke ich ihm halt den Code, dass er mir die Koordinaten geben 
soll.
Dann schickt er über RXe die Bytes.

Nur dadurch, dass ich ein relativer Anfänger bin, weiß ich nicht, wie 
ich jetzt die Daten mir holen kann und abspeichern kann.
Eines ist mir aufgefallen, dass ich sei(); oben vergessen habe.

Hat irgenjemand eine Idee, was ich Falsch gemacht habe?

von spess53 (Gast)


Lesenswert?


von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hänge hier mal eine Usart-Test Routine hier an.

Mit der Lib kannst du mit zwei Befehlen jeweils senden und empfangen.

Rs232_SendByte();

test[0]= Rs232_GetByte();

Eine Test-Funktion ist in der usart_test.c vorhanden

Der zurückgegebene String beinhaltet deine X/Y Werte.
Die Daten müssen notfalls noch byteweise nach Hex konvertiert werden.
Der Empfang ist Interrupt gesteuert und gepuffert.
Die USART-Lib soll dir erst mal helfen deine USART-Probleme zu lösen.

Funktionen die das Display betrifft, solltest du dann selber weiter 
entwickeln können.



Gruß G.G.

von Wolfgang K. (polarwolf_94)


Lesenswert?

Gerhard Gehlert schrieb:
> Hallo,
>
> ich hänge hier mal eine Usart-Test Routine hier an.
>
> Mit der Lib kannst du mit zwei Befehlen jeweils senden und empfangen.
>
> Rs232_SendByte();
>
> test[0]= Rs232_GetByte();
>
> Eine Test-Funktion ist in der usart_test.c vorhanden
>
> Der zurückgegebene String beinhaltet deine X/Y Werte.
> Die Daten müssen notfalls noch byteweise nach Hex konvertiert werden.
> Der Empfang ist Interrupt gesteuert und gepuffert.
> Die USART-Lib soll dir erst mal helfen deine USART-Probleme zu lösen.
>
> Funktionen die das Display betrifft, solltest du dann selber weiter
> entwickeln können.
>
> Gruß G.G.

Einmal vielen herzlichen Dank

Bitte entschuldige, aber bei Empfangen verstehe ich den Code noch nicht 
ganz
[
// die X/Y Daten müssen dann in einem bestimmten Zeitraum zurück kommem
    // der USART-Buffer stellt dann die Daten hier zur Verfügung

    char test[]="                          ";  // Hier steht deine 
Auswertung als String,
    test[0]=Rs232_GetByte();          // zur Auswertung müssen die Daten 
bytweise in Hex gewandelt werden!

]

Soll ich in dem Feld nun was hineinschreiben?
Die Koordinaten kommen als Hex-Daten zurück.  Also muss ich das dann 
nicht noch zusätzlich umwandeln, oder?

LG Wolfi

von Wolfgang K. (polarwolf_94)


Lesenswert?

Könnte man es auch so lösen?

[
void Touch()                  //Controller fragt den Grafikcontroller, 
wo die Fläche berührt wurde und gibt dementsprechend die X und Y-Achse 
zurück
{
unsigned char x_pos1, x_pos2, y_pos1, y_pos2;    //X/Y-Positionen vom 
Grfikcontroller
unsigned char to[2] = {0x6F, 0x05};

for (uint8_t x = 0; x < 2; x++)
{
  USARTD0.DATA = to[x];
  _delay_ms(3);
}

// die X/Y Daten müssen dann in einem bestimmten Zeitraum zurück kommem
// der USART-Buffer stellt dann die Daten hier zur Verfügung

//char test[]="                          ";  // Hier steht die 
Auswertung als String,
//test[0]=
sei();
Rs232_GetByte();          // zur Auswertung müssen die Daten bytweise in 
Hex gewandelt werden!
cli();
if(okToSendAirQuality==1)
{
  Rs232Buffer[1]=x_pos1;
  Rs232Buffer[2]=x_pos2;
  Rs232Buffer[3]=y_pos1;
  Rs232Buffer[4]=y_pos2;

  x_pos=(x_pos1*256+x_pos2);
  y_pos=(y_pos1*256+y_pos2);

  okToSendAirQuality=0;
  return x_pos, y_pos;
}

]

Kann es sein, dass man durch den Befehl sei(), den USART stört?
Weil wenn ich sei() als oberster stelle habe, dann wird kein Signal zum 
Grafikcontroller geschickt.

von Gerhard G. (g_g)


Lesenswert?

Hallo ,



wenn du Rs232_Init() hier verwendest, haben sei() und cli() hier nichts 
zu suchen. Sie sind Bestandteil der USART-Initialisierung.

Wenn du die obige Routine nicht verwendest, kannst du den nachfolgenden 
Code:

Rs232_GetByte()

auch nicht verwenden!


Man kann natürlich die Lib auflösen und in deine Anwendung integrieren.

Dann sollten aber alle Funktionen 1:1 übernommen werden.





Gruß G.G.

von Wolfgang K. (polarwolf_94)


Lesenswert?

Ich habe die anderen Anwendungen eh mitgenommen, sonst würde ja es sonst 
nicht funktionieren.
Wenn ich deinen Code 1:1 verwende, was meinst du mit char test="  "; 
hier drinnen steht ....

Das heißt,  dass dort die abgespeichert sind?
Und kann ich die dann so auslesen wie im Code von mir?

von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe dir jetzt eine verkürzte Version beigelegt. Alles in einer 
Datei.

Damit ist es jetzt möglich auf die empfangene Daten direkt zuzugreifen.
Du muss nur noch die Anzahl der zurück gelieferten X/Y Daten in der 
for()
Schleife bestimmen. Das Zusammensetzen deiner X/Y Daten überlasse ich 
dir.


Viel Spaß

: Bearbeitet durch User
von ALX (Gast)


Lesenswert?

Hallo, hab das gleiche von RIBU.
Auch habe ich Eure Diskusion aus Zeigründen nur überflogen , SORRY wenn 
ich falsch liege.
1.
Mir scheint das du in deinem Code das garnicht mitbekommst weil das 
senden zu schnell durch ist.
2.
Du solltest mal überlegen, dass wenn das Touch betädigt wird, ein 
Interupt an P0 auslöst, und du DANN die Koordinaten erst abholst. Weil 
es würde (glaub ich) später schwierig werden so zeitkritsch zu Arbeiten.

Viel Erfolg  !

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.