Thursday, 27 December 2007

Serial Port Communications With The PIC

A Word about computer interfaces

Although the current interface of choice is the USB Port, it is much harder to program for than its predecessors. The Parallel port is very convenient as it is possible to send byte-wide data with just one clock pulse. It is also simple to program with on the PC side using C# or Visual Basic, and requires no extra processing on the PIC’s part since the raw bytes can be simply shunted from the parallel port straight to the LCD, it would even be possible to do away with the PIC altogether. So far so good, however Parallel port cables and connectors are large, expensive and power-hungry. Also they are becoming rarer on computers especially on laptops. To top all of this, Parallel ports, put plainly, are boring. Serial ports on the other hand are much smaller, efficient and elegant, not to mention more interesting to study.

A word about the Serial Port

A serial port has 9pins, however only three of them actually do anything interesting. These are the Transmit Data (TD), Receive Data (RD) and Ground (GND). The Ground pin must be connected to the ground on the device so that it is common to both. This is a full duplex system whereby each communication direction has a dedicated cable. The other pins are for ‘Digital Handshaking’ which I will mention later. Because there is only one cable for all the transmitted data to be sent down, a protocol is necessary to ensure that both devices know when to expect / send data. This protocol is RS232 and it is a simple, yet widely used one, which is straight forward to program (in a PIC at least).

A Word About The RS232 Protocol

The data to be sent is split into words of 8 or 7 bits (more on this later) and is sent one bit at a time. A digital high is signified by a negative voltage (-15V) and a digital low is signified by a positive voltage (+15V). In practice, these voltages vary and are generally lower, but this is not significant. The data line is normally low (+15V). Just before a byte is sent, the line goes low for one clock period (the Start Bit), the data bits are then sent sequentially with least significant bit sent first. Finally after the last data bit the line goes (digitally) low for two clock periods (the Stop Bits) to signify the end of the word. In this project, only the PC sends data, the PIC only receives data and doesn’t send anything back to the computer.

A Word About Line Levels

Since we have to use a PIC to interpret the stream of bits, we cannot make a direct connection from Transmit Data line to an input pin on the microcontroller, since the PIC uses CMOS positive 5V signals and the serial line uses ±15V. To get around this I used a dedicated chip which converts 15V to 0V and -15V to +5V, and vice versa, allowing both PIC and Serial to work in harmony. I used the MAX202 as it offers two CMOS to RS232 and two R3232 to CMOS channels, thus allowing further expansion of the project. The chip requires 5 capacitors of equal 10uF value to act as charge pumps, this means it only requires a standard 5V supply and does away with the need for a dual rail power supply. Here is a circuit diagram of the setup I used.

The PIC Program

In my previous blog entry I published the assembler code for a PIC16F84 which initialised an LCD screen and provided a subroutine to display ASCII characters on the screen. I have now modified the code to include another subroutine which converts the incoming serial RS232 data into a single byte, stores it in a register and then displays it on the screen. The code is set up for a data rate of 4800 Baud, which means that the PIC requires a crystal of at least 4MHz to work. The program for extracting information from serial port signal is essentially a complicated shift register which listens for the start bit, then shifts the value at the input pin into a register every 200us (approximately) until the all eight bits have been received (i.e. the register is full). I adapted the code from a website I found a while ago at http://www.boondog.com/tutorials/pic16F84/pic16f84.html which has many other interesting project ideas and resources.

The Assembler code is provided here.

(This program will continually listen out for new ASCII characters on the RS232 input and display them on the LCD. The cursor is automatically repositioned at the end of each line)

Testing The Program And HyperTerminal

In order to test the program you will need to send RS232 data down the serial port on your computer. The easiest way to do this is to use a windows program called Hyper Terminal to make a connection to the PIC. If you have never used Terminal before, you need to select a new connection, and tell it about the device you’re trying to connect to. The necessary settings are shown in this screenshot of HyperTerminal running on my computer (Windows XP). It is then a matter of simply typing on the keyboard to send ASCII coded characters to the device, which should then relay them to the display.


FAQs:

When I type I get random characters displaying on the LCD:

This is because there is too much noise in the signal and ASCII characters are confused. I found the easiest way to improve the accuracy is to increase the power supply to the MAX202 chip to greater than 6V.


Only the first character I type is displayed correctly the others are wrong or missing:

It may be that you are typing too quickly and the PIC has not finished displaying the last character yet. In the Properties option under ASCII Setup increase the line delay until the error is no longer present.

The ‘Enter key’ does not move the cursor to the next line:

It’s not supposed to. The enter key’s ASCII code is not recognised by the LCD as an instruction to move the cursor. Instead the PIC must listen out for the new line character and generate the required code to change lines. This feature will be included and uploaded in future posts.


Problems with contrast on the LCD:

I experienced shadows behind each of the characters on the LCD at one stage which I later found out to be the result of too high a power supply to the LCD module. To correct this I added a standard junction diode in series between the 5V supply and the +Ve pin of the LCD module. This reduced the supply by ~1V and the contrast was much stronger as a result.

No comments: