Serial-to-Parallel Port Communication
Serial to parallel data transfer can be achieved in the following way. Figure 4 is the circuit diagram for interface between RS232 and printer parallel port. Strobe is used to synchronize data transfer between microcontroller and printer. Busy and Ack signals are used to accomplish data transfer with proper handshaking. Transmission of any one character e.g. "A" by microcontroller to PC was used to synchronize data transfer between PC and microcontroller.
Timing cycles for data transfer are:
- Microcontroller first checks the Busy line. If it is asserted low (printer not busy), it sends a character "A" to the PC.
- As soon as the PC receives this character, it writes data on the serial register and keep on polling for "A" on the receive buffer.
- Microcontroller waits for the byte to be received over serial port by polling received data ready buffer or by calling the interrupt subroutine and when the data is ready, it writes it on the data lines of port 1 followed by assertion of Strobe to low.
- Printer asserts Busy to high, reads data sends Ack, writes data and when ready to receive another byte asserts Busy to low.
- Meanwhile, microcontroller waits for Ack, removes Strobe as soon as it receives Ack and keep on polling Busy pin until it is asserted to low and then sends character "A" to the PC to indicate that it is ready to receive another byte and the cycle continues.
The program can, be further enhanced by providing a buffer of size 60-80 characters on the microcontroller.
The design can be easily enhanced to support Enhanced Parallel Port (EPP) instead of SPP. EPP requires to outport data on the data register to transfer data and inport data on the data register to read data. In addition, nDataStrobe signal is to be monitored which tells a data write or read operation in progress.
Finalizing the Adapter
The final adapter will have three lines for serial port -- RxD, TxD and Ground -- and one 25-pin interface. The adapter will have both parallel-to-serial mode and serial-to-printer mode programs at different locations. A switch for 0/5V (P3.7 on the microcontroller) can be used to decide which program to run. Similarly, you can use P3.3 to set 2 baud rates. Everytime a serial interrupt occurs, the interrupt routine first checks which program caused the interrupt by checking pin P3.7 and then jumping to respective location for the different TxD and RxD routines. Final circuitry would be as shown in Figures 2 and 4.
Conclusion
I've presented a simple standalone parallel to serial port adapter using the 20-pin Atmel AT89C2051 microcontroller that supports bi-directional data communication between RS-232 and SPP ports which can be further enhanced to support USB and EPP/ECP ports on similar lines. The adapter supports auto baud setting and has a switch to determine which routine to run (parallel to serial OR serial to printer port communication). It can be used for numerous purposes like network adapters for interfacing various electronic devices. The adapter was successfully tested using PC and printer. C and assembly routines test the adapter in parallel-to-serial port mode that can be used to develop its device drivers.
Acknowledgements
This work is part of my B-Tech final year project done at IIT, Bombay in 1998-99. I thank all the people in SPI lab in Electrical Engineering department for their timely support whenever required.
/* Description: The program initializes various parallel
port registers, reads a character from the keyboard,
displays it on screen, transmits it over parallel port,
reads the received character on the serial port and
displays it on the screen.*/
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define DATA 0x378
#define STAT 0x379
#define CNTRL 0x37a
#define SP2 0x2f8
#define LCR 0x2fb
#define DLL 0x2f8
#define DLH 0x2f9
#define LSR 0x2fd
#define IER 0x2f9
#define IIR 0x2fa
void main()
{
unsigned inc1, inc2, inr;
int ch;
int rcv;
/*-------------------------Initialization--------------------------*/
outportb(DATA, 0XFF); /* initialize data port */
outportb(CNTRL, 0x00);
outportb(LCR, 0x00);
outportb(IER, 0x03); /*set interrupt enable register */
outportb(LCR, 0x83); /* set bit format, DLAB=1*/
outportb(DLL, 0x60); /*set baud rate = 1200 */
outportb(DLH, 0x00);
/*------------------------Parallel Port--------------------*/
clrscr();
while((ch = getch()) != '\r')
{
putchar(ch);
delay(1);
do /* wait for Busy signal*/
{
inc1=inportb(STAT);
}
while ((inc1 & 0x80) == 0x80);
outportb(DATA, ch);
delay(5);
outportb(CNTRL, 0x01); /* send strobe */
do /* wait for Ack */
{
inc2=inportb(STAT);
}
while((inc2 & 0x40) == 0x40);
delay(2);
outportb(CNTRL, 0X00); /* clear strobe */
delay(5);
outportb(DATA, 0xff); /*remove data */
/*----------------Serial Port----------------------*/
do /* wait for Data*/
{
inr = inportb(IIR);
}
while((inr & 0x04) != 0x04);
outportb(LCR, 0x03); /* dlab = 0 */
rcv=inportb(SP2);
putchar(rcv);
}
/*------------------------------------------------------*/
/* send next byte */
}
/*Description: The program polls for Strobe to be
asserted to low by the PC (indicating data ready),
reads data from the parallel port and acknowledges it,
transmits it over transmitter pin and deasserts Busy to
low to indicate that next cycle may begin.*/
.org 0000h
ljmp main
.org 0023h
nop
nop
clr scon.1
nop
reti
main: .org 0050h
anl tmod,#0fh
orl tmod,#20h
mov th1,#0cch
orl pcon, #80h
orl tcon, #40h
mov scon, #50h
mov ie, #90h
setb p3.5
getdata: setb p3.4
strwait: jb p3.2, strwait
clr p3.4
nop
mov a,p1
clr p3.5
nop
nop
stb: jnb p3.2, stb
setb p3.5
nop
nop
mov sbuf,a
nop
nop
nop
nop
sjmp getdata
.end


