Forum: PC-Programmierung RS485 - Visual Basic - Verwendung von 9 Bits


von Olaf R. (gruser)


Lesenswert?

Hallo,

wenn ich ein RS485-Protokoll verwenden möchte, so muss ich in der Lage 
sein 9 Bits pro Byte übertragen zu können. Das neunte Bit kennzeichnet 
ob es sich um eine Adresse oder ein Datenbyte handelt.

Bei Visual Basic 2005 kann man aber nur "SerialPort1.DataBits = x" 
einstellen, wobei x = 5,6,7 oder 8 Bits sein kann. Leider gehts nicht 
mit 9 Bits.

Hat jemand eine Idee, wie man sauber 9 Bits pro Byte über die 
Schnittstelle übertragen kann?

Gruß
gruser

von Kobaltchlorid (Gast)


Lesenswert?

> Hat jemand eine Idee, wie man sauber 9 Bits pro Byte über die
> Schnittstelle übertragen kann?

Beim normalen PC meines Wissens gar nicht. Ein echtes hardwarebasiertes 
9bit-Protokoll inklusive Parity und Start/Stop-Bits wie bei 
Mikrocontrollern ist beim PC-UART nicht vorgesehen. Es gibt Würgarounds, 
wie z.B. hier beschrieben:

http://electronicdesign.com/Articles/Index.cfm?AD=1&ArticleID=6245

Ansonsten geht's nur mit zusätzlicher Hardware, z.B. einem 
Mikrocontroller mit zwei UARTs als "Übersetzer".

von Ralf (Gast)


Lesenswert?

Hi,

> Hat jemand eine Idee, wie man sauber 9 Bits pro Byte über die
> Schnittstelle übertragen kann?
Kommt drauf an, wie du sauber definierst. Es gibt keinen UART, der 9 
_Daten_bits unterstützt, nur eben 8 plus Parity. Aber Parität hat vier 
mögliche Zustände, even, odd, mark und space, das heisst, du musst eben 
mit Mark und Space arbeiten, dann klappt das, so hab ich es in VB & Co. 
auch immer gemacht.

Ralf

von Olaf R. (gruser)


Lesenswert?

Habe mir erst die Mühe gemacht die Dezimalzahl in einen Binärwert 
umzurechnen, um dann die Quersumme zu bestimmen. Je nach Ergebnis habe 
ich dann von ODD auf EVEN (oder umgekehrt) geschaltet.

Jetzt sehe ich mit MARK und SPACE geht es ja noch einfacher, wenn mein 
Master sendet setzte ich einfach MARK, wenn die Slaves senden schalte 
ich um auf SPACE.

Schönen Dank für eure Hilfe!
Olaf

von Olaf R. (gruser)


Lesenswert?

Hmmm... ein neues Problem habe ich mit den 9 Bits:

Vom PC (Master) aus verschicke ich testweise den Wert 170 an einen 
PIC-Controller (Slave). Egal ob ich das Byte mit MARK oder SPACE an den 
PIC schicke, in der Variablen "addr" steht offensichtlich immer nur der 
Wert 170, da mein Lämpchen an- und wieder ausgeht (s.u.). Ich hätte 
gedacht wenn ich RX9=1 setze, könnte ich "addr" mit 9 Bit füllen. Ziel 
ist es anschließend das 9. Bit zu maskieren, so dass der PIC klar 
erkennt dass es sich um eine Adresse handelt.

Sorry wenn ich mich ein wenig kompliziert ausgedrückt haben sollte, aber 
ich habe keine Ahnung mehr woran es liegen könnte, eventuell in der 
Initialisierung? Vielleicht habt wieder eine gute Idee ;-)

Den Code habe ich im wesentlichen mal hier reinkopiert.


void InitUSART()
{
    BRGH=1;
    SPBRG=20;               // 57600 baud @ 20MHz input clock
    SPEN = 1;               // Set_Serial_Pins;
    SYNC = 0;               // Set_Async_Mode;
    TX9 = 0;                // Set_8bit_Tx;
    RX9 = 1;                // Set_9bit_Rx;
    CREN = 1;               // Enable_Rx;
    TXEN = 1;               // Enable_Tx;
    RCIE=0;                 // Rx Interrupt aus
}


//*******  Hauptprogramm 
*************************************************

void main(void)
{
    uns16 a;
    char n;
    char w;
    uns16 addr;             // habe Adresse mal als uns16 definiert
    uns16 test1;
    uns16 test2;

    TRISA = 0b.0000.0000;    // PortA als Ausgang definieren
    TRISB = 0b.0000.0000;    // PortB als Ausgang definieren
    TRISE = 0b.0000.0000;    // PortE als Ausgang definieren

    TRISD = 0b.0000.0000;

    PORTD = 0b.0000.0000;

    TRISC=0b.1011.1100;     // RC6>TX, RC7>RX
    InitUSART();            // Hardwareschnittstelle des PICs einstellen


while (1)
  {

         // Empfangen von Daten

  pause(500);
  pause(500);
  pause(500);
  pause(500);
  pause(500);
  pause(500);

  PORTA = 0b.0000.0000;              // Lampe schaltet aus

         while(!RCIF);                      // Warte auf Empfang
         addr=RCREG;                        // Empfange Adressnummer

  if (addr==170)
    {
    PORTA = 0b.1111.1111;    // Lampe schaltet ein
    pause(500);
    PORTD = 0b.0000.0010;

    delay_mks(1000);
    TXREG = addr;
    while(!TRMT==1);         // Solange hier warten bis Transmittpuffer 
leer ist
    delay_mks(1000);

    PORTD = 0b.0000.0000;
    delay_mks(1000);
    }
  }
}

von Ralf (Gast)


Lesenswert?

Tja, ich kenne mich mit PICs nicht aus, komme aus der 8051er-Ecke, aber 
mir fallen zwei Sachen auf:

1. Beim 8051 muss man nach dem Senden/Empfangen eines Zeichens das 
entsprechende Interrupt-Flag löschen (auch bei Polling-Betrieb, da 
dieses Flag als Erkennung genutzt wird). Das sehe ich bei dir nicht. 
Wird das Flag automatisch beim Lesen durch die Hardware gelöscht oder 
hast du das vergessen?
Würde man das Rx-Flag eines 8051 nicht löschen, wird man ständig 
dasselbe Zeichen auslesen, bis ein anderes kommt, und das dann wieder 
permanent auslesen...

2. Ich sehe nirgends deine Auswertung, ob es sich um Adressen oder Daten 
handelt? Also die Auswertung des 9.Bits...

Ralf

von Olaf R. (gruser)


Lesenswert?

Das hin- und her schicken der Daten klappt ja... dabei brauchte ich 
keine Flags zu löschen. Mich wundert es halt nur dass ich die Variable 
nicht mit einem 9 Bit langen Datenwort füllen kann, offenbar ist immer 
noch bei 255 Ende. In der "addr" steht offensichtlich der Wert 170, 
sonst hätte mein Lämpchen nicht angefangen zu blinken ;) Nachdem ich das 
gesehen habe, habe ich den Teil mit dem Maskieren wieder herausgenommen, 
macht ja keinen Sinn das 9. Bit zu maskieren wenn es nicht da ist.

von Ralf (Gast)


Lesenswert?

Dann ist dein Fehler klar. Du gehst fälschlicherweise davon aus, dass du 
mit 9 Bit als ganzes arbeitest, aber es sind real 8 + 1 Bit. Das heisst, 
du kannst IMMER nur maximal 255 (0xFF) empfangen, das 9. Bit musst du 
separat auswerten. Wenn du einen größeren Wert als 255 empfangen willst, 
musst du ihn auf zwei Bytes aufteilen und auch als Bytes senden...

Ralf

von Olaf R. (gruser)


Lesenswert?

Ja aber warum gibt es in der Beschreibung die Unterscheidung:

    RX9 = 0;                // Set_8bit_Rx
    RX9 = 1;                // Set_9bit_Rx

Irgendwie muss der Empfänger doch dieses 9. Bit auswerten können, sonst 
macht es doch keinen Sinn. Auf dem Oszi sehe ich dass ein Byte (mit MARK 
bzw. SPACE am Ende) rausgeht - damit muss der PIC doch etwas anfangen 
können...

von Ralf (Gast)


Lesenswert?

Beim 8051 wird beim Senden das 9.Bit vorher in ein Flag eines SFRs 
geladen, der UART sendet diesen Bitzustand dann mit.
Beim Empfang wird das 9.Bit in einem weiteren Flag eines SFRs 
gespeichert, sodass es die Software auswerten kann.
Ich würde sagen, das ist bei deinem PIC auch so. Das steht dann im 
UART-Kapitel des Datenblattes, wie es funktioniert.

Ralf

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.