Forum: Mikrocontroller und Digitale Elektronik ATMega128 mit ucos-II UART Problem


von Davor (Gast)


Lesenswert?

Hallo!

Ich verwende einen ATMega 128 mit dem RTOS µcos-II.

Ich habe nun folgendes Problem.

Ich möchte über UART mit einem Touchscreen kommunizieren (4D Systems 
uLDC-28PT).

Ich setze die zuständigen Register:
1
void initTouch()
2
{
3
    UCSR1B = _BV(RXEN1) | _BV(TXEN1);
4
    UBRR1L = UBRR_L_D;
5
    UBRR1H = UBRR_H_D;
6
}

Der Touchscreen erhält befehle in Form von 8-Bit HEX-Zeichen.
Diese sende ich mit:
1
int disp_putc(char c)
2
{
3
4
    while(!(UCSR1A & (_BV(UDRE1)))) {}
5
    UCSR1A |= _BV(TXC1);
6
7
    UDR1 = c;
8
    return 0;
9
}
Die Antwort ACK oder NCK lese ich folgendermaßen aus:
1
INT8U disp_getc()
2
{
3
  
4
    while ( !(UCSR1A & (1<<RXC)) )
5
        ;
6
7
    return (INT8U) UDR1;
8
}
Das funktioniert so weit auch wunderbar. Möchte ich nun, wenn ich auf 
den Tochscreen drücke die Koordinaten auslesen, muss ich 0x6F und 0x01 
über UART Senden.

Für befehle die aus mehreren 8-Bit Befehlen bestehen habe ich folgende 
Funktion:
1
char disp_puts(char *s)
2
{
3
    char x,y;
4
    while (*s!=0)
5
    {
6
        if(s[0]>=65)
7
        {
8
            x=s[0]-55;
9
        }
10
        else
11
        {
12
            x=s[0]-48;
13
        }
14
        if(s[1]>=65)
15
        {
16
            y=s[1]-55;
17
        }
18
        else
19
        {
20
            y=s[1]-48;
21
        }
22
        disp_putc(x*16+y);
23
        s+=2;
24
    }
25
    OSTimeDlyHMSM(DISP_ACK_DLY);
26
    return 1;
27
}
Auch diese Funktioniert einwandfrei, weil ich in der Lage bin aus dem 
Code Objekte auf dem Touchscreen zu zeichnen.

Folgende Sache tritt nun auf:

Ich lese die Touchscreen-Koordinaten wie folgt aus:
1
while(1) 
2
{
3
    disp_puts("6F01\0");
4
    coord_x1 = disp_getc();
5
    OSTimeDlyHMSM(0, 0, 0, 50);
6
    coord_x2 = disp_getc();
7
    OSTimeDlyHMSM(0, 0, 0, 50);
8
    coord_y1 = disp_getc();
9
    OSTimeDlyHMSM(0, 0, 0, 50);
10
    coord_y2 = disp_getc();
11
    OSTimeDlyHMSM(0, 0, 0, 50);
12
    printf("x1: %d  x2: %d  y1: %d  y2: %d       \n",     coord_x1,coord_x2,coord_y1,coord_y2);
13
}
Für x und y koordinaten liefert das Teil 16-Bit werte.

Die printf-Funktion printet auf die zweite UART Schnittstelle welche ich 
mit hterm auslese.

Nun es funktioniert anfangs ziemlich gut. Doch irgendwann bleibt das 
Programm nachdem es x1, x2 und y1 ausgelesen hat in der while-schleife 
von y2 und wartet unendlich lang auf den letzten wert.

Ich verstehe nicht wieso das nicht funktionert.

Weiters schütze ich den "Auslesevorgang" mit mutex und stelle sicher, 
dass kein anderer Task irgendwas machen darf, solange das Auslesen 
dauert.

Was noch verweunderlicher ist, ist folgendes:
Wenn das Programm nun in der while Schleife unendlich lange wartet und 
ich die Nase voll ab und Vcc vom Touchscreen abstecke, kommt y2 an, das 
printf wird ausgeführt und das programm wartet oben wieder auf neue 
Touch eingaben.

Kann mir bitte jmd. helfen :)

von Karl H. (kbuchegg)


Lesenswert?

Davor schrieb:

> Kann mir bitte jmd. helfen :)


Wozu die
 OSTimeDlyHMSM(0, 0, 0, 50);
?

Die Funktion disp_getc() wartet doch sowieso so lange, bis ein Zeichen 
reingekommen ist. Mit dem Delay kann höchtens eines passieren: das ein 
Zeichen verpasst wird. Und das darf auf gar keinen Fall passieren, da 
der Code unbedingt 4 Zeichen von der UART haben will. Und der wartet 
dann auch so lange, bis 4 Zeichen da sind.

> und ich die Nase voll ab und Vcc vom Touchscreen abstecke
und kein Mensch weiß exakt, was dann tatsächlich alles auf der UART 
Leitung passiert. Die UART weiß nichts von Zeichen. Die interessiert 
sich nur dafür, dass da irgendeine Schaltflanke auf der Leitung den 
Prozess des Empfangs triggert. Der Empfangsprozess ist aber in 
Zeiteinheiten von dieser Flanke definiert. D.h. irgendeine x-beliebige 
Flanke auf der Leitung triggert die UART, so dass sie in regelmässigen 
Zeitabständen den Zustand der Leitung protokolliert. Was das für 
'Scheinbits' sind, interessiert die UART nicht weiter.

von Karl H. (kbuchegg)


Lesenswert?

PS.
In einer realen Appliaktion wird man das ganze dann sowieso auf 
Interrupt Betrieb umstellen.

von Davor (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Davor schrieb:
>
>> Kann mir bitte jmd. helfen :)
>
>
> Wozu die
>  OSTimeDlyHMSM(0, 0, 0, 50);
> ?
>

Okay. Danke für die Info. Ohne dem TimeDly passiert exakt das selbe.


Karl Heinz Buchegger schrieb:
> PS.
> In einer realen Appliaktion wird man das ganze dann sowieso auf
> Interrupt Betrieb umstellen.

Ja habe ich auch schon probiert, und die Werte dann in einem zirkularem 
Puffer gespeichert. Auch da konnte ich (beim Debuggen mittels JTAG) 
erkennen, dass er nur 3 Werte anstatt 4 bekommt.

von spess53 (Gast)


Lesenswert?

Hi

>Ich setze die zuständigen Register:
>....
>UBRR1L = UBRR_L_D;
>UBRR1H = UBRR_H_D;

Beim Schreiben von 16-Bit-Registern gilt: erst H dann L. Beim Lesen ist 
es umgedreht.

MfG Spess

von Davor (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Ich setze die zuständigen Register:
>>....
>>UBRR1L = UBRR_L_D;
>>UBRR1H = UBRR_H_D;
>
> Beim Schreiben von 16-Bit-Registern gilt: erst H dann L. Beim Lesen ist
> es umgedreht.
>
> MfG Spess

Ok. Danke!
Habe auch das geändert. Ändert nichts an meinem Problem.

von Davor (Gast)


Lesenswert?

Ich habe das problem soeben gelöst.

Als ich das TimeDly in char disp_puts(char *s) entfernt habe, tritt der 
Fehler nicht mehr auf.

Danke Karl für den Hinweis auf das Verhalten von TimeDlys.

LG

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.