Forum: Mikrocontroller und Digitale Elektronik PIC18F2585 uart send complete


von PicNeuling (Gast)


Lesenswert?

Hallo
ich komme eigendlich aus der Atmel Welt muss mich aber jetzt mit einem 
Pic beschäftigen.
Bei allen Atmels gibt es eine uart send complete Interrupt.
Beim Pic habe ich das nicht gefunden. Liegt es an mir das ich die 
Struktur der Pic Datenblätter noch nicht -überrissen habe oder gibt es 
das tatsächlich nicht?
Wie wird der Sende Pin für Rs485 bei Pics gesteuert?
Lg

Danke

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

Hallo,
ich beschäftige mich eigentlich auch mehr mit Atmel oder Freescale, es 
stellt sich mir aber auch so dar, wie du es geschildert hast. Einen 
Interrupt äquivalent zum "TXC - USART Transmit Complete" habe ich beim 
PIC 18F2585 nicht gefunden. Dort gibt es anscheinend nur ein "TXIF: 
EUSART Transmit Interrupt Flag bit".

Ich vermute du möchtest RS485 im Halbduplex betreiben und dann immer 
Driver/Receiver umschalten?

Ich fürchte, dann musst du das zeitbasiert machen (musste ich letztens 
auch machen).

PicNeuling schrieb:
> Wie wird der Sende Pin für Rs485 bei Pics gesteuert?

Meinst du damit einen Pin, der den Bus-Transceiver umschaltet zwischen 
Receive/Transmit?

Ich habe einen gewöhnlichen GPIO benutzt und kurz vor dem Senden 
umgeschaltet und - zeitbasiert - nach dem Senden abgeschaltet.

Gegenfrage: Gibt es bei Atmels eine Möglichkeit das automatisch zu 
machen (außer mit einem GPIO)?

Gruß,
Alex

von Volker S. (vloki)


Lesenswert?

Ich kenne mich mit den Atmels nicht so aus, aber da scheint es so zu 
sein, dass es einen Interrupt gibt, nachdem das TX Register gesendet 
wurde.

Beim PIC gibt es Interrupts über das TXIF solange das Register frei ist. 
Also nach dem Senden wie bei Atmel, aber auch schon vorher, wenn gar 
nichts gesendet werden soll und auch nachher fortdauernd solange das 
TXREG frei ist.
Das kann man als Hinweis auffassen, dass ein neues Byte gesendet werden 
kann. -> Man muss den Interrupt abschalten, wenn man nichts zu senden 
hat.

von PicNeuling (Gast)


Lesenswert?

Alex B. schrieb:
> Meinst du damit einen Pin, der den Bus-Transceiver umschaltet zwischen
> Receive/Transmit?

Ja genau das meine ich.

Alex B. schrieb:
> Gegenfrage: Gibt es bei Atmels eine Möglichkeit das automatisch zu
> machen (außer mit einem GPIO)?


Nein das ist mir nicht bekannt habe es immer so wie du beschrieben hast 
gemacht.

Alex B. schrieb:
> zeitbasiert


Finde ich jetzt aber nicht sehr performant:-(((

Danke
Lg

von Volker S. (vloki)


Lesenswert?

RS485 habe ich selber noch nie verwendet aber vielleicht hilft die 
folgende Application Note etwas weiter:

AN774 Asynchronous Communications with the PICmicro USART

von PICs (Gast)


Lesenswert?

Nimm den normalen TX_Interrupt. Er zeigt dir doch, daß das Byte gesendet 
wurde.

Solange du was zu senden hast, gibt ein Byte aus.

Kommt der Interrupt und deine Message ist schon komplett gesendet, so 
schalte ihn ab.

Nun kannst du die Treiber umschalten.

von Ste N. (steno)


Lesenswert?

Das ist mir beim PIC18F26K80 auch aufgefallen und ich denke das wird 
wohl bei allen PIC18 ähnlich sein. Das TXIF Flag kann man so nicht zur 
Auswertung heran ziehen. Sobald das Sendregister leer ist, geht TXIF auf 
H und läßt sich auch nicht löschen. Fragt man in der Interruptroutine 
also nur TXIF ab, wird der Code (Wenn das Senderegister zufällig leer 
ist. Und das ist es ja fast immer :) auch bei einem Timerinterrupt 
ausgeführt. Aber jetzt kommt das Erfreuliche. Ein TX Complete Interrupt 
wird trotzdem korrekt ausgelöst. Ob das ein Bug ist oder so gewollt ist? 
keine Ahnung. Die Erratas schweigen sich dazu leider aus. Ich habe das 
für mich so gelöst, das ich TXIF an letzter Stelle im der 
Interruptroutine abfrage und bei den vorherigen Int's mit einem goto 
hinter TXIF springe. Wenn das Programm also bei TXIF ankommt, kann es 
nur noch der TX Int sein. Ist zwar nicht die sauberste Methode, aber 
funktioniert.

1
void InterruptServiceLow(void)
2
{
3
  // Timer0 Interrupt
4
  if (INTCONbits.TMR0IF) {
5
    TMR0L = T0_FREQ;
6
    INTCONbits.TMR0IF = 0;  // Clear T0 Int Flag
7
  
8
    ...
9
    goto LOW_ISR_END;
10
  }
11
12
  // CAN Receive Buffer 0 Interrupt Flag 
13
  if (PIR5bits.RXB0IF) {
14
    if (RXB0CONbits.RXFUL) {
15
      CAN_ReceiveMessage ();
16
      RXB0CONbits.RXFUL = 0;
17
    }
18
    PIR5bits.RXB0IF = 0;  // Clear the received flag.
19
    goto LOW_ISR_END;
20
  }
21
22
    /** USART TX Interrupt ********************************************************
23
    *** Wichtig: Das TX Int Flag wird nicht gelöscht. Es zeigt nach einem
24
    *** Interrupt eigentlich nur an, das das TX Senderegister wieder beschrieben werden
25
    *** kann. Deswegen steht dieser Interrupthandler an letzter Stelle.  Wenn wir
26
    *** hier ankommen, kann es nur noch der TX Int sein. In jedem anderen Handler
27
    *** wird nach Abarbeitung mit Goto ISR_Ende: diese Routine übersprungen
28
    ******************************************************************************/
29
    if (PIR1bits.TX1IF) {
30
      if (PIE1bits.TX1IE)
31
        UART_TX_ISR ();
32
    }
33
34
  LOW_ISR_END:;
35
}

Gruß, Steffen

von Volker S. (vloki)


Lesenswert?

Steffen N. schrieb:
> Fragt man in der Interruptroutine
> also nur TXIF ab,

Frag einfach immer auch das IR-Enable mit ab!
(Ist halt so bei IR auf einen Vektor ...)
1
void high_isr(void)
2
{
3
    if(INTCONbits.TMR0IE && INTCONbits.TMR0IF){ // if timer 0 overflow
4
        mTOG_LED_3(); // then toggle LED
5
        INTCONbits.TMR0IF = 0; // and clear flag
6
        return;
7
    }
8
//    if (interrupt_2_enabled && interupt_2_flagged){
9
//      ...
10
//      return;
11
//    }
12
13
    while(1){;} // Endloschleife → finde unvorhergesehene interrupts
14
}

von WehOhWeh (Gast)


Lesenswert?

Stimmt so, leider:
Zitat:
While flag bit TXIF indicates the status of the TXREG
register, another bit, TRMT (TXSTA<1>), shows the
status of the TSR register. TRMT is a read-only bit which
is set when the TSR is empty. No interrupt logic is tied to
this bit so the user has to poll this bit in order to
determine if the TSR register is empty.

Ich würde mir das mit einem Timer lösen. Dann verliert man nicht allzu 
viel Performance. In dessen ISR kannst du den PIN setzen.

Alternativ nimm neuere PIC24, wie der PIC24FV32KA304. Die können das was 
du willst. Da kann man das Verhalten mittels UTXISEL so einstellen, dass 
der Interrupt kommt, wenn das shiftregister leer ist.
Es kann sein, dass einige neue PIC18 auch dieses Feature haben, aber da 
kenne ich mich nicht aus. Ich würde mir neuer Devices mal anschauen.

Der Umstieg ist meistens leicht, weil PICs im gleichen Package oft das 
gleiche Pinout haben.

Bei PICs wirklich enorm wichtig:
Darauf achten, ein neues Device zu nehmen. Microchip verkauft Schimmlige 
Gurken von 1985 immer noch, daher ist Vorsicht geboten!
Bei den alten PICs ist die Peripherie oft Mist. Bei den neueren PICs, 
speziell einige PIC24, ist die Peripherie inzwischen ein echter 
Pluspunkt. Numm z.B. einen PIC24FJ128GC006 :-)

von Ste N. (steno)


Lesenswert?

Volker S. schrieb:
> Frag einfach immer auch das IR-Enable mit ab!
> (Ist halt so bei IR auf einen Vektor ...)

Da hats Du natürlich vollkommen recht, nur löst diese Vorgensweise das 
Problem mit TXIF nicht. Ist beim PIC18 eben so und betrifft auch nur das 
TXIF Flag.

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.