Friday, February 11, 2011

Complete guide to parallel port programming








Lets begin straightaway with an argument….The world is moving towards RS-232, USB, Fire-wire and other serial bus standards, so why do I still bother using the parallel port?


For starters we are talking about controlling motors here. When it comes to controlling such devices, it’s always the legendary parallel port that hobbyists have been resorting to, since minimizing the required hardware, facilitating simple operation and a faster development cycle are some of the advantages that the parallel port has to offer.
So, without wasting anytime, lets start our session…your development time starts here…..


The Hardware:
Here is how the standard DB25 connector (parallel port connector) at the back-side of your CPU cabinet is configured:




Fig: Parallel port pin configuration


As the name refers, your data is transferred over data lines (bidirectional), Control lines are used to control the peripherals and of course, the peripherals return status signals back to computer through Status lines. These lines are connected to Data, Control and Status registers internally.


The details of parallel port signal lines are given below:



Pin No (DB25)Register – bitDirectionInverted
1
Control-0
Out
Yes
2
Data-0
In/Out
No
3
Data-1
In/Out
No
4
Data-2
In/Out
No
5
Data-3
In/Out
No
6
Data-4
In/Out
No
7
Data-5
In/Out
No
8
Data-6
In/Out
No
9
Data-7
In/Out
No
10
Status-6
In
No
11
Status-7
In
Yes
12
Status-5
In
No
13
Status-4
In
No
14
Control-1
Out
Yes
15
Status-3
In
No
16
Control-2
Out
No
17
Control-3
Out
Yes
18-25
-
-
-





You don’t generally need to bother about the control and status lines unless you are writing a parallel port driver.


And there is no great point in ‘reinventing the wheel’, so I guess you won’t bother to write the driver all over again unless it’s a device driver assignment given by your prof…


The data line is what will be of utmost importance to us, since we will either need to send out some navigational command (OUT) to our motor, or acquire some sensor input (IN).


Programming:
Before we start talking about programming, the register addresses are what we need to be aware of. Also downloading a port monitoring software would be a good idea to confirm our results when we are done.


Here is a link to download one such application: Click Here


Fig: Screenshot of parmon (parallel port monitor)


The numbers ‘378’, ‘379’ and ‘37A’ seen out here in the screen shot are parallel port register addresses. For a typical PC, the base address of LPT1 is 0×378 and of LPT2 is 0×278. The data register resides at this base address, status register at base address + 1 and the control register is at base address + 2. So once we have the base address, we can calculate the address of each registers in this manner. The table below shows the register addresses of LPT1 and LPT2



Register
LPT1
LPT2
data register (base address + 0)
0×378
0×278
status register (base address + 1)
0×379
0×279
control register (base address + 2)
0×37a
0×27a





Programming Concepts
Almost all programming languages allow programmers to access parallel port using some library functions. We will be discussing about the conventionally used ‘C’ language as well as MATLAB.


Parallel port access in ‘C’:
In C, there are following functions used for accessing the port:


outportb( PORTID, data);
data = inportb( PORTID);
outport( PORTID, data);
data = inport( PORTID);


outport() function sends a word to port, inport() reads a word from the port. outportb() sends a byte to port and inportb() reads a byte from the port. If you include DOS.H header, these functions will be considered as macro, otherwise as functions. Function inport() will return a word having lower byte as data at PORTID and higher byte as data at PORTID+2. So, we can use this function to read status and control registers together. inportb() function returns byte at PORTID. outport() writes the lower byte to PORTID and higher byte to PORTID+1. So this can be used to write data and control together. outportb() function write the data to PORTID. outport() and outportb() returns nothing.


A sample program for blinking LEDs connected at the parallel port at a constant frequency is as shown below:


#include”conio.h”
#include”dos.h”
#define PORT 0×378
void main()
{
while(!kbhit())
{
outportb(PORT, ~inportb(PORT) );
delay(1000);
}
}


NOTE: Don’t forget to start ‘parmon’ so that you can comfortably monitor your port’s real time status.


Also remember that the parallel port output is internally latched and hence it retains the same status till a new data is sent onto the parallel port. So, for a motor control application if you have a byte dedicated for movement, make sure you have a byte dedicated to halt the motor. This byte should be sent at the parallel port whenever you want to halt the motor, otherwise the latched output will make the motor run continuously.


Parallel port access in MATLAB:
Initially, we create a parallel port object as shown below,


parport=digitalio(’parallel’,’LPT1′);
Post this, we add the actual hardware lines to this newly created parallel port object as also define the direction of data flow as done below:


line=addline(parport,0:7,0,’out’);
We declare an array containing the data that we want to snd at the port pins,


pval = [1 0 1 0 0 0 0 0];
Finally, using ‘putvalue’, we send the data at the port pins.
putvalue(parport,pval);
Use ‘getvalue’ the read the status of the port.


Points to note:
In case you are using the parallel port to drive motors or any such load, beware!! There is a very high amount of risk involved in this as the parallel port might get loaded and cause damage to the motherboard.


Hence, it is always a good idea to connect an opto-coupler between the parallel port and the motor driving circuit. This ensures isolation and allows us to use the parallel port without bothering about the safety of the motherboard.


A schematic for motor control using parallel port can be found below:






It uses MCT2E, an opto-isolator along with L293D for driving 2 DC motors.
You can download the data sheets from: 424848_DS  and 1330  
So, go on and start programming. Your development time ends here!!!

How to communicate using serial port?

Parallel Communication:

Usually 8 or more bits are sent simultaneously.

Serial Communication:

Bits of a character are sent one by one.


Why go serial??
Parallel communication is faster but it has certain drawbacks. For transmitting data in parallel we need lot many number of wires (i.e. no of wires = no of bits to be transmitted at once).

For transmitting data to long distances this approach proves expensive. Also the signal degradation with distance in parallel transmission is faster.
Serial transmission can use a minimum of 2 wires (Ground and data if it is half duplex communication) or 3 wires (Ground, Reception, Transmission for full duplex)
Serial communication can also provide for error detection and correction facilities which in parallel would again require more number of wires. The obvious drawback of serial communication is the speed which definitely is lesser compared to ideal parallel data transmission.


UART (Universal Asynchronous Receiver Transmitter)
UART is block in the muC which aids in serial transmission of data. Inside the CPU all data processing and manipulations are done in parallel. But for the reasons stated above communication with devices far away from the muC are better of done serially. The UART block converts the data given by the CPU and converts it into serial stream of data with start, stop and parity bits as required/configured.


We can use the UART in an interrupt driven mode as well as full software control mode. An interrupt driven UART program would generally prove efficient than the other.
The below is an example of such a program.
A very essential thing to do before using the program is reading the datasheet. Go through the UART functional descriptions and the special functions registers.


#include”REG52MOD.h”
#include”delay.h”
#include”LCD.h”


unsigned char RXED,TXED;
void UART_INIT(void) //UART Initialization
{
SBUF=0×00; //Empty Serial Buffer
SM0=0; //Set UART
SM1=1; //in mode 1
SM2=0;


REN=1; //Receive Enable
TMOD=0×2F; //Set baud
TH1=253; //rate as 9600bps
TR1=1;
ES=1; //Enable serial interrupts
EA=1; //Global interrupt enable
}


void TX(unsigned char dat) //Transmit Data
{


SBUF=dat;
delay(10);


}
void RXTX_int(void) interrupt 4 //Serial interrupt ISR
{
if(RI==1)
{
RI=0; //Reset receive data bit
RXED=SBUF;


LCD_WRITE(RXED); //Display received character on LCD
}


if(TI==1)
{
TI=0; //Reset transmit data bit
}
}


void main(void)
{


LCD_INIT(); //Initialize LCD
UART_INIT(); //Initialize UART
delay(1);
TX(’S’);
TX(’t’);
TX(’a’);
TX(’r’);
TX(’t’);
while(1){}


}
The program should be self explanatory. But some queries that might arise I guess would be:
Why have I set RI = 0, TI=0 in the ISR??
These are the flags set when a bit is received or transmitted completely. They are not automatically reset when the program enters the ISR. So we need to reset them through software.


Note: All flags need not be reset manually. Some have auto reset facilities.
But it is a good practice to reset any interrupt flag when you enter the ISR if that extra instruction doesn�t cause much inconvenience to the performance of the code.

Why is TH1=253??
This particular count value gives us a baud rate of 9600bps.


In serial communication mode 1, the baud rate is determined by the overflow frequency of Timer 1. There are various ways in which we can configure timer 1 to overflow at particular frequencies. But a simple method is using the timer 1 in 8-bit auto reload mode.
To determine the value that must be placed in TH1 to generate a given baud rate, we may use the following equation
TH1 = 256 – ((Crystal / 384) / Baud)
Will this setting remain same for all crystal values??
No. It won�t. The timer is coupled with the oscillator frequency. So for different crystal values the count value to be loaded will be different.


Note: The crystal value 11.0392Mhz is a peculiar value of frequency which can generate all standard baud rates like 2400, 4800, 9600 etc.
For interfacing the UART with your PC you need to configure the Hyper Terminal in windows.
You can find it in Start > Programs > Accessories > Communications > Hyper Terminal


Step 1
Enter a name for the connection


Step 2

Select Port as COM1 (Generally)


Step 3
Step 4

USB Li-ion battery charger

This is a charger for lithium ion batteries which takes its power from the USB port of a computer. It uses the MCP73861 or MCP73863 Li-ion battery charger chip manufactured by Microchip.