EDN logo


Design Ideas: September 2, 1996

C function turns PC into serial-bus master

Gregory Young,
Z-World Engineering, Davis, CA

The UARTs built into most microcontrollers support a "9th-bit" communications mode. If the master sets the 9th bit of a character it transmits, the slaves then interpret that character as a slave address, not as data. The 9th-bit mode simplifies master-slave communications by using character protocols over multidrop serial lines, such as the RS-485. A PC's UART family (for example, the 8251 or 16550), however, does not support 9th-bit communications. This shortcoming is unfortunate, as the PC is an attractive alternative for many embedded applications. Also, a PC can be ideal as a laboratory tool for evaluating new slave devices. Luckily, you can trick the PC into performing 9th-bit communications. The UART's little-used and often-forgotten "mark" and "space" parity options can add the 9th bit to the UART's native 8-bit communications. The C function in Listing 1 performs the trick.

Listing 1—9th-bit serial communications on a PC

#define  UART     0x2F8         // Base Address for UART (COM2)
#define  LCR      (UART+3)      // Line Control Register I/O Address
#define  LSR      (UART+5)      // Line Status Register I/O Address

void
sendPacket     (  const char     *pchPacket,
                  unsigned       wCount
                )

{     outportb ( LCR,inportb(LCR)&0xEF );    // Set Mark Parity (9th = 1)
      serPut ( *pchPacket++ );               // Write Address
      while (inportb(LSR) & 0x04);           // Wait for Address Sent
      outportb ( LCR,inportb(LCR)|0x10 );    // Set Space Parity (9th = 0)
      while (--wCount)                       // Send Remaining Bytes
          serPut ( *pchPacket++ );
}

The sendPacket function allows you to send a number of bytes (wCount) from a buffer (pchPacket) in a typical 9th-bit master-slave format. The first byte of a packet transmits with its 9th bit set to 1 to indicate that the character is the address of the slave for which the packet is intended. The remainder of the packet transmits with the characters' 9th bits set to 0 so the slaves won't mistake data for slave addresses and, thereby, erroneously wake slaves that have chosen to ignore the packet. The function in Listing 1 is generic and works with any serial driver on the PC. The default initialization for the PC's serial port should be 8 data bits, 1 stop bit, and space parity.

Note that for completeness, access to the needed control registers is hard-coded in this example; you may wish to access the control registers in a more elegant fashion via your serial driver. Prior to sending the slave-address byte, the routine clears bit 4 of the UART's line-control register (LCR), thereby programming the UART for mark parity. Mark parity sets the 1 in the 9th bit. The function then sends the address byte. Because PC UARTs don't queue the parity bit along with the data in their output buffers, the routine must wait until the address byte is completely sent before shifting back to space parity.

When bit 2 of the line-status register (LSR) becomes 1, the transmission of the address byte is complete. Once the address has been sent, the routine reverts to data mode (space parity) by clearing bit 4 of the LCR. You may then send the data portion of your packet, each byte of which has its 9th bit set to 0. In most protocols, slaves reply only with data bytes so you need no special handling to receive replies. (DI #1915)


| EDN Access | feedback | subscribe to EDN! |
| design features | out in front | design ideas | departments | products | columnist |


Copyright © 1996 EDN Magazine. EDN is a registered trademark of Reed Properties Inc, used under license.