Our First Program and the HD44780 Display Driver

So far our work with the DS5000 has been to assemble a program, and load and run it in the simulator. Now starts the process that we will repeat many times throughout the rest of the course. We will take one of the example programs from a previous lesson and download it to the DS5000 and watch it execute.

start: mov a,p1        ;read the switch
       mov p0,a        ;write to the led
       sjmp,start      ;go to start

This is prob02.asm from lesson 6. This is an ultra simple program. It won't look like much when we run it but it is, however, a program that does something. It reads a switch and lights an LED. The switch will be a jumper that we connect or disconnect and not a real switch. We will use p1 bit 0 (P1.0) as the switch input and p0 bit 0 (P0.0) for the LED. The logic probe will be the LED. Connect the probe to P0.0 and a jumper between GND and P1.0 .

Make sure the LOAD / RUN switch is in the LOAD position and the RS-232 connected to the PC. Apply power to the system. The LED should be lit because all of the port lines on the DS5000 are at a high impedence state when in the LOAD condition. On your PC type A51 PROB02 . This will assemble the program. Now type DNLOAD PROB02 . This will download it to the DS5000. Now place the LOAD / RUN to the RUN position. The LED should go out. Now remove the jumper from P1.0 . The LED should lite. Re-connect the jumper to P1.0 . The LED should be go out. If this didn't work, check your connections.

We have just traced all the steps that take us through the development process. First a program is written or modified with a text editor. The program is assembled into an object file. The object file is downloaded to the DS5000 and executed. Operation is monitored with the logic probe to note any problems or whether a change has produced the desired result. If there is a problem, the program is loaded into the simulator and execution is monitored to reveal the problem. And then you do it all over again. This cycle is repeated many times before even a crude system is written, and then many more times to get to a workable prototype. Then lots more debugging and refining the system.

This is just a rough outline of the actual process. You may or may not use the logic probe in each cycle of process, nor the simulator. I sometimes use the test led and an instruction to light it placed at the suspected problem area for software debugging, instead of the simulator. The simulator is good for initial testing of a program, but ultimately you wll want to know which path a conditional jump took when a certain event occured.

Construction of microprocessor based hardware is unique in the computer field, I think, because you work both sides of the problem, both hardware and software. In most other fields of computers, you normally specialize in either the hardware area or the software area. When a problem comes up, the software people always point to the hardware as the problem and the hardware people point to the software as the culprit. Typically, the hardware people know very little, if any, software. And the software people know very little, if any, hardware. So, when either side views a problem, a totally different view of the problem is arrived at by both sides.

In our area, microprocessor system design, a problem is viewed in a sort of stereo, seeing both from a hardware point of view and at the same time, from a software point of view. This stereo view gives an insight into a problem that will ultimately cause the correct diagnosis to be arrived at, usually much quicker than the two sides together could. This is because, when looking at a problem from a hardware - only point of view, no consideration is given to software timing when trying to solve a problem, for instance. Conversely when a softhead is trying to solve a problem, the ac ripple in the system power supply is not up for consideration.

As we move through this course, I will attempt to keep a dual track, both hardware and software, to reflect this stereo view so that you will eventually develope this insight yourself.

At this point I want to review what my expectations are of you and what minimum skills you should have attained by now.

1. You should be able to read a schematic, understanding that the schematic shows only the electrical connections, but not the physical connections.You should be able to convert the electrical connections into physical connections.

2. You should be able to solder. How to twist and tin a stranded wire.

3. You should be able to use a voltmeter and the logic probe. The black (-) lead of the voltmeter is normally connected to GND, and the red (+) lead is used for taking the reading. That the voltmeter must be on the right function, ohms, volts, etc., and if necessary, the right range, 1,10,100, etc.

4. You should be able to use a text editor to type in a program

5. You should be able to use the assembler to assemble it.

6. You should be able to use the simulator to debug it.

7. You should be able to download the program to the DS5000.

8. You should know the function of the LOAD / RUN switch.

9. You should understand the physical layout of the protoboard. That it is made up of an arrangement of tie strips, each having 5 tie points. That there are 4 power busses, 2 VCC busses and 2 GND busses. You should be able to make a jumper from a piece of solid #24 insulated wire and plug the ends into the protoboard. You should be able to connect two parts together using a tie strip on the protoboard, realizing that no other parts can touch the unused tie points in this stip.

10. You should be able to use the pinout help file and the schematic to connect to the correct pin of a part on the protoboard.

11. You should be able to read the resistor color code.

12. You should be able to "talk" to the DS5000 using the loader and your PC.

13. You should be able to use basic tools; hammer, screwdriver, pliers, cutters, etc.

Don't be disturbed by my list. I don't mean that you are currently experts at any of these skills, just that you realize that these skills are necessary to understanding the rest of the course. I'm not going to mention how to connect the voltmeter to read a voltage, I'm just going to say "the voltage at this point should read 3.55 VDC". I'm not going to say open up the editor and load prob02.asm and...". I'm going to say "edit prob02.asm and... ".

For me to complete this course in some reasonable span of time, I must be able to talk to you on a technical level, without describing the gory details each time. As usual, any time something new comes up, I will describe it in as much detail as I can. But after that, you will be expected to remember it, or at least to remember that you need to refer to it from time to time.

So consider that you have reached technical puberty, and that I'm going to talk to you as adolesents instead of children, a transition that I've been eagerly anticipating. Any time you feel that I'm moving too fast, drop me a note, with a question, and I'll give you extra instruction.

I've had it brought to my attention that there are several wires not connected on the protoboard that are on the schematic. We will eventually get to these, as they are needed. The two wires from the power supply that are just hanging loose, make sure that these don't touch together or to any other part of the protoboard.

We are going to connect the LCD display to the system next. Looking at the schematic, there are 11 connections between the DS5000 and the display, not counting power. Eight of these are the data bus, and 3 lines are for control of the display data bus. This display uses the Hitachi HD44780 display driver chip. This gives us a display that can be directly connected to the DS5000 with minimal effort. The display is really a microprocessor itself, with the interface logic to connect to the LC display hardware.

On the display board, there is a 14 pin connector area along the top left corner of the board, looking at it right side up from the front (Refer to the pinout help files). I mentioned in the previous lessons that I bought a connector male and female and used a 12" piece of 14 conductor ribbon cable for the display cable. You can just solder the ribbon directly to the display, eliminating the connectors entirely. It will work just as well this way, with extra care given to not flexing these connections any more than absolutely necessary. However you do it, the ribbon at the protoboard end will be a bunch of twisting and tinning to get solid ends to plug into the protoboard. I find that about a 1/4" finished end on ribbon wires will be sufficient to plug into the protoboard. I would separate the individual colored wires on this end for about 6" of the cable. This will allow you to plug the wires in anywhere on the protoboard.

So now you've got a display with 12" of 14 conductor ribbon cable connected to the display and the other end of the cable stripped out 6" and the individual wires tinned a 1/4" on the ends. That rolled off my tongue pretty quick, but it takes a while to do this. The easiest way to solder the ribbon to the display is to separate the colors back about an inch and strip, twist and tin about an 1/8th inch. Then solder the two outside wires to the two outside connection points. This will hold the wires up to the display for easier soldering. Solder the rest of the wires, one to each connection point, until you have them all. A really useful device in all this is a vacuum base vise. This little beauty sucks down on the table with a lever, and stays there for a long time. I use one all the time for making up connectors or connections to a part. It gives you a "third hand" that is indespensible. They cost around $60. Digikey has a Panavise that is part# 303PV-ND and 380PV-ND (it takes both numbers) for $56 total. This is like the hot glue gun, you'll wonder how you ever got along without one.

Now looking at the schematic, connect all the lines up to the DS5000. A method I use when doing this is to check off each line as I plug it in. If you do this for all connections you make on the schematic, a quick glance will reveal whether a particular connection has been made, when trouble shooting. Other than the 11 lines previously mentioned, there are 3 other lines. Pin 1 is the GND pin and pin 2 is the VCC pin. Pin 3 is the display contrast adjustment line. You will need to tie a 330 ohm (R5) and a 10K ohm (R4) resistor together with the 10K connected to VCC and the 330 connected to GND. Then connect pin 3 of the display to the junction of R4 and R5. Suggestion: find an unused tie strip and plug one end of the 10K into VCC and the other end into the tie strip. Plug one end of the 330 into GND and the other end into the same tie strip. Then plug the wire from pin 3 of the display into the same tie strip.

Double check all your connections, particularly power and ground, but they all have to be right. You should have checked off all 14 connections to the display.

The Hitachi HD44780 Display Driver

I need to now go into an explanation of the HD44780 Host interface. As I said earlier, 8 of the connections to the display are for 8 bit data, although only 4 have to be connected for nibble operation. The other 3 are the ones that need explanation. One is the E line. This is an active high control line. Active high means that when this line is low, it is inactive, it is serving no function. It could have been more accurately named STROBE. This line, on it's rising edge, strobes data either to or from the data bus. The second line is the R/W line. If this line is high, data is transfered from the display. If this line is low, data is transferred to the display. The last line is the RS line. If this line is high, the display is in the data mode and if this line is low the display is in the command/status mode.

A typical display routine will first read the status of the display to see if it is busy, and then make a transfer with the display. Data can be written or READ from the display. I don't normally read data from the display, but that option is available. Each interaction with the display is prefaced by reading the display status and waiting until the display isn't busy. This concept of waithing until something is ready is due to the fact that the display is really a dedicated microcontroller that's running it's own program, being a display. When you write a byte to the display, you've really just handed it off to the microprocessor in the display and now it goes through it's program doing what displays do and eventually showing us a visual feedback, through looking at the display. This all takes time for the display to do, so if you start him doing something, in all likelyhood, it will be many microseconds before he will be ready to do something else. So we wait for the display to get through with anything it may already be doing, and then tell him something else to do. This holds true for many of the peripheral chips, like A/D converteres, who are micros themselves with execution times. Notice that this type of interface is a polling interface, not an interrupt driven interface. I can't know anything about the status of the display without reading status from it. There is no way for the display to signal it's state of readiness to the DS5000, except by polling status from the display.

To read status from the display and wait until the display is ready, the following steps would be taken. Normally the E line will be low, the RS and R/W lines can be anything, and must be assumed to be wrong, so they are set each time an operation is required:

1.              set the RS line to a low (status)
2.              set the RW line to high (read)
3. over1:       set the E line high
4.              read the display
5.              clear the E line
6.              Test Bit 7 (BF) in the acc and loop to over1 if a one (busy)
7.              If bit 7 is a zero, the display is ready

Step 1: sets the display bus for a read operation

Step 2: sets the display bus for a command/status operation.

Step 3: enables the display bus.

Step 4: reads in the status from the display bus into the accumulator

Step 5: disables the display bus.

Step 6: tests the READY bit to see if it is a ONE and if not, loops back to step 3

Step 7: the end of routine.

Here are the actual commands that we will use

        setb    lcrw
        clr     lcrs
over1:  setb    lcde
        mov     a,p0
        clr     lcde
        jbz     acc.7,over1

The label will be different, but these are the commands that will be used.

There are some mechanical software procedures that must be used with the HD44780 every time you apply power to the system or reboot (RESET) occurs to the system. First, a sequence of bytes must be written to the display, in a timing order, to reset the display and set it to the proper system operating parameters. It follows a sequence that is described in the Hitachi data sheet for the HD44780.

Following is the actual segment from our operating software that deals with the display. There are several subroutines that this initialization uses. Their description and code follows this initialization routine.

Subroutine: INLCD - This routine initializes the display after power up or a system reboot. First we initialize the 3 control lines to the display.

inlcd: clr   lcrs   ;clear rs to set data bus to command (write) / status mode (read)
       clr   lcrw   ;clear rw to set data bus to write mode
       clr   lcde   ;clear E to disable display bus

The first thing that must be done is to initialize the display after power up. This is done by first waiting at least 15 msec (milliseconds) after power up. I used 16 just to make sure.

       mov a,#h'10  ;wait
       lcall waitp  ;16 milliseconds

The next thing is to write a 38h to the display and wait 5 milliseconds. The 38h says that we want an 8 bit data bus, a 5 X 7 font, and a 4 line display (it is really functionally only a 2 line display, but I'll explain that later).

       mov p0,#h'38 ;write
       lcall strob  ;38 to lcd
       mov a,#h'05  ;wait
       lcall waitp  ;5 milliseconds

The next thing is to write a 38h to the display and wait 1 millisecond

       lcall strob  ;38 to lcd
       mov a,#h'01  ;wait
       lcall waitp  ;1 millisecond

The next thing is to write a 38h to the display, actually checking the busy bit (reading display status). The previous writes to the display were using instruction timings to wait different amounts of time. This is a requirement of the display to guarantee that it is initialized. Normally all transactions with the display are prefaced by reading display status and waiting until not busy, before actually doing the deed. These are the only examples where this rule isn't strictly followed.

       mov a,#h'38  ;38h to
       lcall wclcd  ;display

Next output a 0ch to the display. This turns on the display, turns off the cusor, and sets the cursor to increment (move to the right).

       mov a,#h'0c ;write
       lcall wclcd ;0c to display

Next output a 01h to the display. This clears the display and places the cursor at the home position.

       mov a,#h'01 ;write
       lcall wclcd ;01 to lcd

Next output a 06h to the display. This sets the cursor to increment (move to the right), and no display shift (characters would move off the left side of display when too many characters had been displayed).

       mov a,#h'06 ;write
       lcall wclcd ;06 to lcd

Next output a 10h to the display. This sets the cursor to move, the display not to shift, but if it did shift, shift to the left.

       mov a,#h'10 ;write
       lcall wclcd ;10h to lcd
       ret

This ends the startup initialization needed for the HD44780. Following are the subroutines used by the display initialization routine.

Subroutine: WCLCD - This routine writes a command to the display. This function is used when ever a command is written to the display. The routine enters with the command in the acc. R7 is used for temporary storage of the command by the subroutine. When the routine exits, the data has been transfered.

wclcd: mov r7,a        ;save the command in r7
       clr lcrs        ;set lcd to command
       setb lcrw       ;set lcd to read
wc001: setb lcde       ;set E
       mov a,p0        ;read display status
       clr lcde        ;
       clr E
       jb acc.7,wc001  ;if busy then doit again
       mov a,r7
       clr lcrw        ;set lcd to write
       mov p0,a        ;write data to lcd
       setb lcde       ;set E
       clr lcde        ;clr E
       mov p0,#h'ff    ;tristate p0
       ret

Subroutine:WAITP - This routine waits for an amount of milliseconds in acc. Using a clock frequency of 11.0592 Mhz, the loop count value needs to be an e6h for both 8 bit timers. This routine enters with the acc holding the count in milliseconds that the routine is to wait. . Uses r7 for temporary storage of count. This routine is two simple 8 bit counters cascaded together so that each time r6 is decremented to zero, r5 is decremented once. R6 is the low byte and r5 is the high byte.

waitp: mov r7,a        ;save # milliseconds
wtx02: mov r6,#h'e6    ;initialize
       mov r5,#h'e6    ;counters
wtx01: djnz r6,wtx01   ;decrement r6 and jump not zero
wtx03: djnz r5,wtx03   ;decrement r5 and jump not zero
       djnz r7,wtx02   ;decrement count and jump not zero
       ret             ;done, return

Subroutine:WDLCD - This routine writes a byte of data to the display. This routine is always used to transfer a byte of data to the display. The routine enters with the acc holding the byte of data. R7 is used by the subroutine to temporarily store the byte of data. When the routine exits, the byte of data has been transfered.

wdlcd: mov r7,a        ;save the data temporarily in r7

First we initialize the control lines to the display

       clr lcrs        ;set lcd to command
       setb lcrw       ;set lcd to read

Next we wait until the display is ready.

wd001: setb lcde       ;set E
       mov a,p0        ;read lcd busy
       clr lcde        ;clr E
       jb acc.7,wd001  ;if busy then doit again

We get the data, initialize the control lines

       mov a,r7
       setb lcrs       ;set lcd to data
       clr lcrw        ;set lcd to write

Write the data to the display

       mov p0,a        ;write data to port
       setb lcde       ;set E
       clr lcde        ;clr E

Any time we write any data out on the data bus (p0) we must always return them to all 1's when we are done. This keeps the tristate bus working properly for the other speakers on the bus.

       mov p0,#h'ff    ;tristate p0
       ret

Subroutine:STROB - This routine strobes the E line to the display.

strob: setb lcde       ;set E
       clr lcde        ;clr E
       ret             ;

Display Commands

The display is ascii character based. There are commands to clear the display, home the cusor, define the cursor, set the cusor to a character position, and read and write display data.

Command             HEX    Description

Clear display        01    Clears the display and homes the cursor.

Return home          02    Homes the cursor

Function set         38    Sets the data bus to 8 bits, 4 line display, and 5 X 7 font

Entry mode set       06    Sets the cursor direction to right with no display shift

Display ON/OFF       0C    turns on the display, turns off the cusor, no blinking cursor

Cursor / Display     10    Cusor move, no display shift

Set cursor position  80    This is the start of the top display line (20 characters)
                     C0    This is the start of the second display line     "
                     94    This is the start of the third display line      "
                     D4    This is the start of the bottom display line     "

Here is how we could send the word "Hi" to the first two character positions on display line 1 (far left side)

Oneln:   mov a,#h'80       ;set cursor to
         lcall wclcd       ;start of line 1
         mov a,#'H'        ;mov a ascii 'H'
         lcall wdlcd       ;to the display
         mov a,#'i'        ;mov a ascii 'i'
         lcall wdlcd       ;to the display

The display should now have the letters "Hi" in the first two character positions of the top line on the display. (See the table that describes the HD44780 instructions).

I am giving you an initial test program that will test your display and output a message to it if it is working. This program is called disptest.asm .If it works, your display should have the message "Hi there" in it. The rest of the display may look wierd, but don't worry about that. If the program dosen't work, check your connections.

Here is a link ADC0808/ADC0809 8-Bit MuP Compatible A/D Converters with 8-Channel Multiplexer to the A/D Converter data sheets, in PDF format. Here is a link DS5000(T) to the DS5000 data sheet in PDF format.

With the ONELN example above, you should be able to modify DISPTEST.ASM and write any characters you wish to any place on the display. Give it a try.

In the next lesson we start looking at the ADC0808 A/D converter chip and it's interface.

My home page is http://www.hkrmicrop.com/personal/index.html .

On to lesson 15.