Forum: Mikrocontroller und Digitale Elektronik Frage zu RTS und CTS Signalen


von Christian O. (chris_o)


Lesenswert?

Hallo Leute,
ich weiß, das Thema ist schon etliche male behandelt worden, konnte aber 
leider keine Lösung für mein Problem finden.

Und zwar geht es um folgendes:
Ich sende mit einem PIC33FJ16GS404 über UART daten an ein 
Bluetoothmodul. Um das Modul nicht zu überfordern möchte ich den 
Hardware-Handshake über RTS/CTS machen.

An meinem PIC ist das CTS-Signal ein Input(Port B, Bit 0), auf dem die 
RTS-Leitung des Bluetoothmoduls hängt und umgekehrt.

Aktuell habe ich probleme beim senden. So wie es aussieht überfordert 
mein PIC das Bluetoothmodul....

So sieht meine Senderoutine aus:
1
 int Bluetooth_Send(int Lang,char senden[])
2
{
3
    static int i = 0;
4
    static int finish = 0;
5
    
6
   //Send data
7
    if ((i <= Lang)&&(PORTBbits.RB0 == 0))
8
    {
9
        //__delay_us(80);                                 //Verzögerung um Bluetoothmodul nicht zu überfordern (80µs)
10
        if(!IFS0bits.U1TXIF)                                //Wenn Interrupt Flag nicht gesetzt
11
        {  
12
            U1TXREG=senden[i];
13
            i++;
14
        }  
15
        else
16
        {
17
            IFS0bits.U1TXIF = 0;                                //Rücksetzen der Interruptflag
18
        }
19
    }
20
    if (i==Lang)
21
    {
22
       finish = 1;
23
       i=0;
24
    }
25
    else
26
    {
27
     finish = 0;   
28
    }
29
    
30
    return (finish);
31
}
Diese Routine wird von der main-funktion immer wieder aufgerufen (ist in 
einer Schleife)

Wenn ich den Delay von 80µs rein mache kommen so gut wie alle Daten an. 
Ich möchte das ganze aber mit Handshake machen um sicher zu gehen.

Mit dem Oszi habe ich am CTS-Pin des µC gemessen... es kommt immer mal 
wieder ein High-Pegel, was für mich ja "nicht senden" heisen würde.
Dies würde ich ja über die Abfrage "if ((i <= Lang)&&(PORTBbits.RB0 == 
0))" gewährleisten.

Ich habe mir gedacht, dass es eventuell auch an meiner 
UART-Initialisierung liegen könnte. Die sieht wie folgt aus:
1
/*Initialisieren UART*/                                
2
U1MODEbits.STSEL = 0;                           // 1-Stop bit
3
U1MODEbits.PDSEL = 0;                           // No Parity, 8-Data bits
4
U1MODEbits.ABAUD = 0;                           // Auto-Baud disabled
5
U1MODEbits.BRGH = 0;                            // Standard-Speed mode
6
U1MODEbits.RTSMD = 0;                           // Flow Control mode
7
U1MODEbits.UEN1 = 0;                            // UxTX, UxRX and UxRTS pins are enabled and used; UxCTS pin is controlled by port latches
8
U1MODEbits.UEN0 = 1;                            
9
U1BRG = BRGVAL;                                 // Baud Rate setting for 115200
10
11
U1MODEbits.UARTEN = 1;                          // Enable UART
12
U1STAbits.UTXEN = 1;                            // Enable UART TX
13
__delay_ms(10);                                 // Delay von 10ms
14
15
IFS0bits.U1TXIF = 0;                            // Interruptflag auf 0 setzen

Hat jemand ne Idee was der Fehler sein könnte?

von Thomas E. (picalic)


Lesenswert?

Christian O. schrieb:

>         if(!IFS0bits.U1TXIF)       //Wenn Interrupt Flag nicht gesetzt
>         {
>             U1TXREG=senden[i];
>             i++;
>         }
>         else
>         {
>             IFS0bits.U1TXIF = 0;
> //Rücksetzen der Interruptflag
>         }

Ich kenne jetzt die PIC33... nicht näher und habe nicht ins Datenblatt 
geschaut, aber von den kleinen PICs kenne ich das so, daß das UART 
TX-Interrupt Flag von der Hardware auf 1 gesetzt wird, wenn das 
Senderegister bereit ist, Daten aufzunehmen. Das TX-IF wird dann beim 
Schreiben ins Senderegister auch automatisch von der Hardware 
zurückgesetzt.

Wenn das bei den PIC33... genauso ist, ist Deine if-Bedingung schonmal 
falsch...

von Christian O. (chris_o)


Lesenswert?

Thomas E. schrieb:
> Christian O. schrieb:
>
>>         if(!IFS0bits.U1TXIF)       //Wenn Interrupt Flag nicht gesetzt
>>         {
>>             U1TXREG=senden[i];
>>             i++;
>>         }
>>         else
>>         {
>>             IFS0bits.U1TXIF = 0;
>> //Rücksetzen der Interruptflag
>>         }
>
> Ich kenne jetzt die PIC33... nicht näher und habe nicht ins Datenblatt
> geschaut, aber von den kleinen PICs kenne ich das so, daß das UART
> TX-Interrupt Flag von der Hardware auf 1 gesetzt wird, wenn das
> Senderegister bereit ist, Daten aufzunehmen. Das TX-IF wird dann beim
> Schreiben ins Senderegister auch automatisch von der Hardware
> zurückgesetzt.
>
> Wenn das bei den PIC33... genauso ist, ist Deine if-Bedingung schonmal
> falsch...

Hi, danke erst mal für deine Antwort!
Im Datenblatt steht folgendes:

•  If UTXISEL<1:0> =
00
, the UxTXIF bit is set when a character is transferred from the
transmit buffer to the UARTx Transmit Shift Register (UxTSR) or the 
transmit buffer is
empty. This implies at least one location is empty in the transmit 
buffer.

The UxTXIF bit is set when the module is first enabled. The user 
application should clear the
UxTXIF bit in the Interrupt Service Routine (ISR).

Heißt also so wie ich das versteh, dass ich ja erst mal einen character 
ins transmit buffer schreiben muss... dann wirds ins Shift Register 
geschoben und die IF wird auf 1 gesetzt (nach meinem Verständnis wird 
der character dann gesendet) Anschließend muss ich dann das IF wieder 
auf 0 setzen, damit ich den nächsten character senden kann....

Oder wie hättest du das ganze gemacht?

von Thomas E. (picalic)


Lesenswert?

Ich glaube, Du hast da was missverstanden: das TXIF muss nicht gelöscht 
werden, damit Du was senden kannst, sondern es zeigt an (wenn "1"), daß 
der UART bereit ist, das nächste Byte im TXREG aufzunehmen. Beim Senden 
per Interrupt würde so immer dann, wenn das TXREG leer ist (d.h. der 
Inhalt des TXREG wurde ins Sende-Schieberegister übertragen), ein 
Interrupt ausgelöst, und die ISR holt dann das nächste Datenbyte aus dem 
Speicher und schreibt es ins TXREG.
Ein Unterschied zu den kleinen PICs scheint zu sein, daß das TXIF nicht 
automatisch durch Schreiben ins TXREG zurückgesetzt wird, sondern per 
Software gelöscht werden muss.

Deine if-Bedingung ist aber genau falsch herum, d.h. Du schreibst ins 
TXREG, wenn das TXIF auf 0 ist!

Probier's mal so:
1
         if(IFS0bits.U1TXIF)       //Wenn Interrupt Flag gesetzt
2
         {
3
             U1TXREG=senden[i];
4
             IFS0bits.U1TXIF = 0;  //Rücksetzen des Interrupt Flags
5
             i++;
6
         }

von Christian O. (chris_o)


Lesenswert?

Hmh...das würde dann auch erklären, warum mein Handshake nicht richtig 
funktioniert...

=> Habs probiert... sieht aus als würde es so laufen
Danke!

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.