Micro Projects Home Page

Home

 Microprocessor Basics

Micro Basics

Site Projects

Site Projects

Construction Techniques

Construction

Programming concepts

Software

Projects

Projects

8085 page

8085 page

Fault Finding

Fault Finding

Data Sheets

Data Sheets

EEprom Programmer

Programmer

Video Information

VIDEO info

Peripheral Circuitry

Peripheral circuitry

Central Heating and Z280's

Z280 and  Central Heating  Controllers

Concluding Ideas

Concluding ideas

Links

Links

 Writing Simple Routines

Whilst I never intended to write a page detailing how to write simple / basic software routines, I seem to be being asked to do this so many times, I guess I’ve bowed to pressure in the end. However, there are STILL great problems in doing this so as to cover as many processor devices as possible. Thus I’ve drawn up a couple of simple rules for myself. Firstly, I am not proposing to use any specific Assembler mnemonics so as not to confuse users of another processor. Mnemonics can be particularly annoying with processors using the same HEX coding AND instructions, yet the mnemonics are different for each device e.g.

Z80

8080

LD H,VALUE

LX1 H,VALUE

LD A,C

MOV A,C

DEC B

DCR B

All three of these codes are common to both of these processors and they both use the same OP codes too! Users familiar with the 8085 processor that ALSO uses these same codes will notice that it uses the 8080 mnemonics rather than those belonging to the Z80...

Another ruling I set myself was to try NOT to use special multi-operation code specific to one processor, like the LDIR, LDDR, CPIR AND CPDR Z80 codes. These are very useful routines that perform multiple operations with the programmer simply entering values into certain specified registers and pressing the ‘Go’ button. Really like a sub-routine already built into the processor.

My last rule was to avoid ‘tidy’ and elegant’ pieces of coding that use ‘clever’ techniques to achieve the required goal. Unfortunately they generally involve a measure of ‘Nellie knowledge’ and therefore might not be well understood by someone new to the subject; thus all the coding here is SIMPLE to the extreme - BUT will enable the micro project builder to write his or her code that will  work! There’ll be time to tidy up the code and make it look more ‘professional’ at a later date.

Picture

I /O routines are the bread and butter of all micro code as without it your program cannot inform you of the results or accept your input. Some processors treat any I/O as memory, whereas other devices give the I/O it’s own special routines and even timing. At the end of the day there is not a lot of difference to the software writing as you simply pick the appropriate instruction. If we use a couple of the site projects as examples here, this will be better explained. Note that both the EEPROM programmer (Z80 based) and the AT  Keyboard interface (6809 based)

use the same DUAL serial comms chip, namely the Zilog 8530 SCC. Thus you will be able to see the same commands needed to be sent by both processors; the Z80 with it’s specific I/O ones and the 6809 ones that call everything ‘memory’.

Sample of code used to begin initialising the 8530 SCC chip:

Z80 HEX

does what?

6809 HEX

does what?

what are we attempting to achieve by this?

3E

LOAD A REG

86h

LOAD A REG

The 8530 needs two instructions to allow the processor to talk to

09

WITH 09h

09h

WITH 09h

any of it’s many registers. Here we tell it we want access to Reg 9

D3

SEND TO

B7h

SEND TO

We send this register ‘request’ to the address of the control regs.

21

I/O 21h

80h

ADDRESS

for the ‘A’ half of the SCC. Note that the Z80 uses a specific I/O

3E

LOAD A REG

01h

8001h

address, in this case 21h, whereas the 6809 thinks of it as memory.

C0

WITH C0H

86h

LOAD A REG

This is the second part of the instruction where we now send the

D3

SEND TO

C0h

WITH C0H

value we want to send to Register 9. This instruction is a Reset.

21

I/O 21h

B7h

SEND TO

Note that the instruction is sent to the same address as before. The

   

80h

ADDRESS

internal workings of the SCC will have directed the value where

   

01h

8001h

we wish it to go.

Hopefully all will have been able to understand the above instruction. To use one half of the dual SCC device, one has to set up a number of different registers with different values for baud rate, data bits, stops bits, interrupts etc. All are entered in the same way as above and in the case of the Z80 use up a total of 56 (decimal) bytes - and this doesn’t include the final instructions to either ENABLE the receiver or transmitter!

Picture

MULTIPLE BYTES TO BE SENT..

There will be occasions when there are several bytes to be sent at once. In the example above we sent each one to the same address, but in the case of others like the displays to the left, each digit will have it’s OWN specific location. Now it’s up the programmer to decide when the time is right to .

‘optimise’ the code rather than simply repeating the same code over and over again until the job is done. In the case of displays like these with built in driver chips, it is customary for the device to have a pair of address lines to take to the Address Bus. (4 digits will need only 2 address lines to select any one of them). In the example to the left we are using 2 x displays (8 digits) so how you connect them ‘hardware-wise’ will determin how you address them in the software. In the case of the Site Programmer, I took both of their A0’s and A1’s to appropriate address connections, and then took each chip select (/CE) line to a different output of the 74LS139 decoder chip I’d designed into the circuit - The right hand one to output Q0 and the left hand one to Q1. With Address Bus lines A4 and A5 taken to the ‘139, this meant that the far right digit would be addressed as 00h with the next to the left being 01h, 02h, 03h, with the fifth digit (the far right of the SECOND display) being addressed as 10h, with the next as 11h, 12h and lastly 13h for the far left. Confusing? Indeed! Take a few minutes to work it out yourself and it’ll all come clear.

Whilst I’m afraid that it would be of little help to show the display load routine from the EEprom Programmer program as it incorporates the OUTI instruction which is unique to the Z80, so for this example I will show that used in the 8085 project - which will of course work equally well on the Z80 or the 8080. In keeping with my liking  for retaining similarities in my designs, the addressing for the displays in both the Programmer and the 8085 Site Project are identical. Note that the ‘HL’ pair is simply two 8 bit registers combined to form one single 16 bit one. Most processors have at least one that can perform this operation. In the case of the 6809, there are two indexed registers (the X and The Y) which may be used in a similar manner. Although users of  the 6502 only have two single byte (8 bit) index registers, these have full increment,  decrement and compare facilities, and may be used to transfer messages etc. if the lowest part, or the ‘Zero page’ area of the memory is used. Essentially, it’s a case of getting to know and using to the full, the instructions that come with the micro you are planning on using.

Picture

First and foremost, before this Display SUBROUTINE is run, the physical ADDRESS of the first byte of the 4 digit word to be outputted to the display has to be loaded into the HL register pair. The HL pair will then point to a 16 bit address in ROM or RAM, and place the contents into the ACCUMULATOR.

In the case of these processors, namely the 8080, 8085 and the Z80, the op-code is a 21h with two further digits to tell it what immediate values to load into registers H and L. i.e:

21h

LOAD HL PAIR WITH

  

68h

68h  (address low)

Note that this series of micro,

00h

00h  (address high)

puts the LSW (the 68) FIRST

If you are feeling really keen :) you can check the example above with the 8085 site project program listing at 0039/003A/003Bh

IMPORTANT!

Note that this program subroutine with it’s four digits is a border line case where it is questionable whether it would have been better to tidy up the code and use another register or memory location to keep track of the passes, thus making it only necessary to write the ‘Load/Send/Increment’ bit only once.Obviously in the case of eight or more consecutive digits one would try not to write out the same piece of coding eight times over!

Subroutine to display 4 x digits in one pass

7Eh

LOAD Accumulator with where HL is pointing (0068h here)

D3h

SEND TO I/O ADDRESS (display far LH digit)

13h

13h

23h

INCREMENT HL (from this example’s 0068h-0069h)

7Eh

LOAD Accumulator with where HL is pointing (0069h here)

D3h

SEND TO I/O ADDRESS

12h

12h

23h

INCREMENT HL (from this example’s 0069h-006Ah)

7Eh

LOAD Accumulator with where HL is pointing (006Ah here)

D3h

SEND TO I/O ADDRESS

11h

11h

23h

INCREMENT HL (from this example’s 006Ah-006Bh)

7Eh

LOAD Accumulator with where HL is pointing (006Bh here)

D3h

SEND TO I/O ADDRESS (display far RH digit)

10h

10h

C9h

RETURN FROM SUBROUTINE

Of course the moral to any sort of programming at this level is to be sure that what you are about to use does what you think it will. If you are at all unsure then delve deeper and find out - or alternatively don’t use it for the time being, and simply go for a more tried and tested solution, even though it may well use up a few more bytes of code, until you have the time to experiment with the ‘unknown’.

Picture

Time for a quick word of wisdom. ALWAYS use the correct software manual with the correct micro. Even some that look very similar might not be - and don’t assume either! One can never be sure that a particular instruction  with one micro will affect the same condition bits as with another!! Been there, done that... your talking to a professional here... :)

KEYPADS AND SWITCHES

I can’t remember how many times I’ve been asked for advice on interfacing even the simplest of switches into a micro. I shall therefore go into the basics, which should be transportable to more complex arrangements. This time let’s use the 6809 as an example with a simple inport arrangement with two switches to the outside world, which can easily be expanded up to a total of EIGHT without any hardware changes - except for the extra switches of course!

HARDWARE

With simple 68xx and 65xx systems, a nice and convenient I/O and memory decoding arrangement is by using a 74LS138 decoder chip to divide up the 64K addressing space into 8 x 8K chunks. That’s 8K for a 2764 ROM, 8K for a RAM, leaving a total of 6 more possible addresses without any further hardware. If the ‘138 is connected like described, then the three address lines from the chip will need to go to A13, A14 and A15. In addressing terms, this means that the ROM is at the top where it has to be, i.e. E000h to FFFFh. The RAM might as well be connected to 138 pin 9 to give it the space from C000h to DFFFh (assuming that it’s a full 8K of course), thus leaving start addresses from: 0000h, 2000h, 4000h, 6000h, 8000h and A000h. So which to use? OK lets go for one in the middle; 4000h. Remember that this address can be either used to read or write - or both, so you could theoretically connect a display to this address AND a 8 bit keypad.   FYI, the 6809 PC AT Keypad decoder successfully used the simple 74LS138 arrangement.

AND NOW FOR THE SOFTWARE...

Picture

The simplest way to connect switches into a micro is through an octal driver like the 74LS244 as depicted above. Why not the LS240, LS241, LS245, the smaller LS125, or even the 8155 / 8255 parallel device? (or similar) No reason other than the fact that I have shed loads of the 244’s! As for the 8155/8255, if you are going to need more than one 8 bit port or wish to use some of the other options it offers then go for it. It’s very easy to program and easy to obtain. However, the 244 is a very useful device where just one simple 8 bit port is needed, as in our example here.

Assuming that our 244 is connected to the data bus with it’s enables on pins 1 and 19 connected to pin 13 of the 138 (to enable it at address 4000h), all the inputs (2, 4, 6, 8, 11, 13, 15 and 17) should be tied high with separate pull-up resistors (say, 1 - 2.2K) then connect the push switches between our chosen two inputs, pins 2 and 4, and ground.

To READ in the switches in a simple application like this you POLL them periodically to see if either of them have been pressed down. To do this, first of all you have to decide whether the processor cannot do anything until one or more of the switches is pressed. This routine will therefore be an endless loop. The short routine below shows an example of this:

To test for a condition on the second switch connected to Data Bus bit 1 (thru the 244) the AND WITH value should be 02h. Where you have a succession of buttons or switches to test, it will obviously make more programming sense if you were to AND with FFh, COMPLEMENT the value in the accumulator (which makes every ‘1’ a ‘0’and visa versa) then check if the whole word is zero. If it is NOT, then you know that a button is pressed and a full scan of the buttons can be actioned. Of course if you want to make things interesting and check for a particular combination of keys where you have several in the bank, then all you do is do a COMPARE with an immediate value that applies to those keys being pressed. For our two keys in this example, the value to compare with would be FCh only when both are down together.

Endless loop switch poll

6809 HEX

means?

What we’re trying to achieve here:

B6h

READ IN FROM:

This is a simple memory read from location

40h

40h

4000h. Note that with our simple example, the

00h

00h

value could be anything from 4000-5FFFh

84h

AND WITH:

Logical AND the result in the Accumulator with:

01h

01h

01h. This will only give a 1 if switch 1 is UP

26h

JUMP if NOT zero

6809 conditional Branch, will jump relative by:

F9h

F9h (relative)

F9h  - i.e. BACK6 locations to READ again

......

 

Condition met and switch down....continue

DELAYS

Picture

Yes, the software delay is one of the subjects that comes up most frequently in your Feedback! For that reason I’ll finish off this page with a few useful delay routines. First and foremost one must realise that it is not that easy to predict what a delay is going to be unless one is prepared to sit down and calculate how long each particular instruction takes in MICRO seconds - with a certain value of system clock In all honesty, I never have the time or the patience to do this so I

generally ‘cheat’ by picking a rough value, then run the program as a loop and adjust the values until it is within the parameters I want to achieve.Here are a few examples of routines I’ve used recently. Remember that a software delay is precisely that; namely a lot of instructions to waste the processor’s time. It is always a good idea to make them SUBROUTINES so that you can accesss them from anywhere within a program - and double them up for longer delays by running two or more of the same sub’ one after the other.

34h

PUSH A, B, X, Y

36h

 

35h

PULL A, B, X, Y

36h

 

39h

RETURN FROM SUB

How simple can things be sometimes? 6809 routine to give an 18uS delay with a 4MHz crystal.

34h

PUSH A, B

06h

 

86h

LOAD ACCUMULATOR

10h

WITH 10h

4Ah

DECREMENT ACCUM.

26h

BRANCH NOT ZERO

FDh

BACK TO DECR. ACC.

35h

PULL A, B

06h

 

39h

RETURN

Another 6809 routine that may be easily copied for use with other processors. We use the PUSH and PULL instructions to save anything already in the Accumulator that we may wish to use after the delay is finished. By altering the value in A (here we see it set at 10h) you can vary this delay to run it well into the Milli-Second range. Delay for this one is about 115uS from a standard 4MHz crystal again.

F5h

PUSH A,F

3Eh

LOAD ACCUM.

FFh

WITH FFh

3Dh

DECREMENT ACC.

20h

JUMP REL. NOT ZERO

FDh

BACK FD.

F1h

POP A,F

C9h

RETURN

For your reference, I used a more complex version of the above delay in the AT Keyboard interface where I decremented the Accumulator from FFh to 00h and then the B register from FFh to 00h. This produced a delay of almost 0.3 secs.

Picture

A nice little 1mS delay for the Z80. In order to use this code with the 8080 and 8085 which has no relative jump (the 20h x) the ordinary Jump if not zero code will have to be used (C2h x x)

BACK to Izabella’s Programming Class

http://www.hampshire-shops.co.uk

Hopefully this page of programming examples will be of help to those who may have experienced problems when starting out in writing machine code or assembler. If you need help with something specific that is not here, there are at least many good books around on the subject.