Forum: Mikrocontroller und Digitale Elektronik Kommunikation mit UART, Code-Fehler in Funktion?


von Cris (Gast)


Lesenswert?

Hallo miteinander,

sieht jemand von Euch einen offensichtlichen Grund, warum die folgende 
Funktion nicht funktionieren sollte?

Aufgabe soll es sein, über den UART eine beliebige Anzahl von Bits zu 
übertragen.


unsigned int SchreibeUART(int outlen, unsigned char* outbuf)
{
     unsigned int Nr;

     for (Nr=0;Nr<outlen;Nr++)
     {
      *pUART = outbuf[Nr];
      while((*pUART+1)&0x40)==0);  //Abfrage Statusregister->Sendepuffer 
leer
     }

/*     warten bis das letzte Byte weg ist   */

 return(1);
}

Vielen Dank,
Cris

von Cris (Gast)


Lesenswert?

Nachtrag:

Sorry, ein beliebige Anzahl von Bytes!!

von Karl H. (kbuchegg)


Lesenswert?

Cris schrieb:

> Aufgabe soll es sein, über den UART eine beliebige Anzahl von Bits zu
> übertragen.

Das das Statusregister eine um 1 höhere Adresse als das Senderegister 
hat, hast du kontrolliert?

> sieht jemand von Euch einen offensichtlichen Grund, warum die folgende
> Funktion nicht funktionieren sollte?

Ja

>       while((*pUART+1)&0x40)==0);  //Abfrage Statusregister->Sendepuffer

 *pUART+1

ist der um 1 erhöhte Inhalt von *pUART.

Du willst

     *(pUART+1)


Ich würde die Abfrage, ob das Sendregister beschrieben werden kann, vor 
das Beschreiben ziehen.
1
     for (Nr=0;Nr<outlen;Nr++)
2
     {
3
      while((*(pUART+1))&0x40)==0)  //Abfrage Statusregister->Sendepuffer
4
leer
5
        ;
6
      *pUART = outbuf[Nr];
7
     }

auf die Art, brauchst du beim AUfruf der Funktion nicht darauf achten, 
ob eine vorhergehende Sendeoperation schon abgeschlossen ist, und du 
brauchst auch in der Funktion nicht darauf warten, dass das letzte Byte 
schon draussen ist.
Die UART schiebt das letzte Byte raus, während dein Programm schon 
wieder weiterläuft.

Das hier im Funktionsinterface
1
unsigned int SchreibeUART(int outlen, unsigned char* outbuf)
das int bei outlen ungeschickt ist, brauch ich wohl nicht extra 
erwähnen.

von kurz (Gast)


Lesenswert?

>Abfrage Statusregister

Bist Du sicher, daß Du den Status des Registers abfragst ?

von Markus F. (pippo)


Lesenswert?

Auf die Gefahr hin, dass ich mich als Anfänger oute, aber wo ist denn 
pUART eingehängt?

Gibts denn vielleicht ne Fehlermeldung, bzw. wie genau äußert sich der 
Fehler?

von Peter D. (peda)


Lesenswert?

Markus F. schrieb:
> Auf die Gefahr hin, dass ich mich als Anfänger oute, aber wo ist denn
> pUART eingehängt?

Die Frage ist garnicht blöd.
Wenn da ne Adresse zugewiesen wurde, die per IN/OUT zugegriffen werden 
muß, gehts schief.


Peter

von Cris (Gast)


Lesenswert?

Danke schonmal,

aber weshalb ist 'int outlen' ungeschickt gewählt?

Kann die Reihenfolge Schreiben/Status-abfrage dafür verantwortlich sein, 
dass mein Programm bisher nicht lief?

von Cris (Gast)


Lesenswert?

Nachtrag an Markus:
pUART wird ein Adressbereich über:

volatile unsigned int *pUART = (unsigned int*) ADR_FLEX_L

zugewiese...wenn das deine Frage beantwortet?

von Karl H. (kbuchegg)


Lesenswert?

Cris schrieb:
> Danke schonmal,
>
> aber weshalb ist 'int outlen' ungeschickt gewählt?

Weil du ständig signed/unsigned Warnungen kriegen wirst.
Zumal du ja auch innerhalb der Funktion deinen Schleifenzähler als 
unsigned hast.

Wenn schon, dann sei konsequent und mach alles unsigned oder alles 
signed (wobei sich allerdings die Frage erhebt welchen Sinn dort eine 
Länge von -1 haben könnte)

Für solche Fälle gibt es in C den Datentyp size_t. Damit dokumentiert 
man dann auch, dass es sich hierbei um eine Längenangabe handelt. strlen 
liefert zb. einen size_t zurück. malloc möchte einen size_t haben, etc 
...

> Kann die Reihenfolge Schreiben/Status-abfrage dafür verantwortlich sein,
> dass mein Programm bisher nicht lief?


             while((*pUART+1)&0x40)==0)

Nochmal (zur Verdeutlichung füge ich Klammern ein, wie der Compiler die 
Sache anhand der Vorrangregeln sieht)

   Du hast          ( ( (*pUART)+1  ) & 0x40 ) == 0
   Du willst aber   ( ( *(pUART+1)  ) & 0x40 ) == 0

Deine original while Schleife testet, ob im Senderegister der Wert 0x3F 
drinnensteht. Du willst aber ganz was anderes: Du willst das 
Statusregister testen, ob dort Bit 6 gesetzt ist.

von Karl H. (kbuchegg)


Lesenswert?

> volatile unsigned int *pUART = (unsigned int*) ADR_FLEX_L

ADR_FLEX_L  ist die numerische Adresse des Senderegisters?
und (ADR_FLEX_L + 1) ist die numerische Adresse des Statusregisters?

von Peter D. (peda)


Lesenswert?

Cris schrieb:
> volatile unsigned int *pUART = (unsigned int*) ADR_FLEX_L

Also ist es wohl doch kein AVR.

Es muß irgendein Chip sein, dessen UART 16bittig ist (unsigned int *), 
was zumindest ungewöhnlich ist.

Und das volatile sagt, daß ein Interrupt Dir die UART-Adresse unter den 
Füßen wegziehen darf, was auch ungewöhnlich ist.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Peter Dannegger schrieb:
> Cris schrieb:
>> volatile unsigned int *pUART = (unsigned int*) ADR_FLEX_L
>
> Also ist es wohl doch kein AVR.
>
> Es muß irgendein Chip sein, dessen UART 16bittig ist (unsigned int *),
> was zumindest ungewöhnlich ist.

Yep. Ist mir gar nicht aufgefallen.

Wird Zeit für mehr Informationen des TO über seine Umgebung.

(Den unsigned int glaub ich ihm schon mal nicht. Halt ich für den Fehler 
eines übereifrigen Einsteigers)

von Cris (Gast)


Lesenswert?

Mist, Fehler von mir...

Ich hatte natürlich schon:
while(*(pUART+1)&0x40)==0);

Spielt dann die Reihenfolge immernoch ein Rolle?


Nein Nein ist kein AVR..sorry hätte ich dazu sagen sollen...ist ein DSP 
von TI. Ich hoffe, dass das nicht so wild ist...

von Mark B. (markbrandis)


Lesenswert?

Cris schrieb:
> Nein Nein ist kein AVR..sorry hätte ich dazu sagen sollen...ist ein DSP
> von TI. Ich hoffe, dass das nicht so wild ist...

Und welcher genau, unterliegt strengster Geheimhaltung ;-)

von Karl H. (kbuchegg)


Lesenswert?

Cris schrieb:
> Mist, Fehler von mir...
>
> Ich hatte natürlich schon:
> while(*(pUART+1)&0x40)==0);
>
> Spielt dann die Reihenfolge immernoch ein Rolle?
>
>
> Nein Nein ist kein AVR..sorry hätte ich dazu sagen sollen...ist ein DSP
> von TI. Ich hoffe, dass das nicht so wild ist...

trotzdem sieht das hier
1
volatile unsigned int *pUART
seltsam aus.
Bist du sicher, dass das Senderegister deiner UART 16 Bit breit ist?

Das hier
    pUART+1
gibt dir dann die numerisch um 2 höhere Adresse nach pUART 
(sizeof(unsigned int) mal als 2 angenommen)

von Cris (Gast)


Lesenswert?

Ist der TMS320C31!!!

Bin mir sicher!

von Karl H. (kbuchegg)


Lesenswert?

Kannst du einen Link zu einem vernünftigen Datenblatt geben. Mit dem was 
ich mir auf die Schnelle ergoogle, kann ich das irgendwie nicht so recht 
nachvollziehen.

Danach sind die Memory Mapped Register

    808040h     Serial Global Control
    808042h     FSX/DX/CLKX Serial Port Control
    808043h     FSR/DR/CLKR Serial Port Control
    808044h     Serial R/X Timer Control
    808045h     Serial R/X Timer Control
    808046h     Serial R/X Timer Period Register
    808048h     Data Transmit
    80804Ch     Data Receive

Data Transmit dürfte das Senderegister sein. Die Control Register sind 
dann allerdings weit weg davon, und vor allen Dingen nicht auf +1

PS: Ich würde auch mal sagen, dass die Grafik, die ich in einem TI 
Datenblatt gefunden habe, deine Aussage nicht unterstützt, dass du es 
mit 16 Bit Registern zu tun hast. Aber ich hab auch nur so ein schmufti 
Übersichtsdatenblatt gefunden, welches mehr über Pin-Timings und electr. 
Characteristics quasselt.

von Cris (Gast)


Lesenswert?

Hallo Karl-Heinz,

ok...ich werd mal suchen+finden...danke vielmals...

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.