
So far we've learned a little bit about what we can do with the 8253/54, and a little bit on how we will need to control this little beast. The following sections will describe in detail the different modes of the chip and how to make it work for you. The heart of this chip is the control register, before you can make the chip do what you want a certain degree of knowledge of this register is required.
The Control Register
This is the little baby that you have to tell what you want the chip to do today. This control register is a single port, there is one for each chip, and it controls the functions of the three counters within each chip.
By sending a particular number, or sequence of numbers, to the control register port will make the chip perform any of it's huge repertoire of tricks. But the biggest trick is knowing which number to send to the control register.
To know this we have to get down to a few nitty-gritties about the chip. We can only really start by learning about the control modes.
The Six Control Modes
I'll put this table here, the descriptions get a bit technical but you will need to keep refering back here during the following sections.
| Mode 0: Set Output Bit when timer done | |
| The output will start off zero. The count is loaded and the timer will start to count down. When the count has reached zero the output will be set high, and remain high until the next count has been reloaded. | |
| Mode 1: Programmable One-Shot | |
| The output will go low following the rising edge of the gate input. The counter will count and the output will go high once the counter has reached zero. | |
| Mode 2: Rate Generator | |
| The counter will continually count down, when the count reaches zero, the output will pulse low and the counter will be reloaded. | |
| Mode 3: Square Wave Generator | |
| This mode is similar to Mode 2 except the output remains low for half of the timer period and high for the other half of the period. | |
| Mode 4: Software Triggered Pulse | |
| The output will remain high untill the timer has counted to zero, at which point the output will pulse low and then go high again. | |
| Mode 5: Hardware Triggered Pulse | |
| The counter will start counting once the gate input goes high, when the counter reaches zero the output will pulse low and then go high again. |
To set up the mode we need to send a byte to the control register. As previously mentioned each chip has what is known as a base address. The base address for your chip depends on where you've set the jumpers on the card. Let's assume the base address is 300H. The H means we're talking Hexadecimal now. This may be an equivalent language to Swarhili to many people, but computers like talking in strange ways. Although we prefer to count using base ten arithmetic, computers like to be different and count in base sixteen, what this means is that after the number 9 comes the letter A, then B and so on through to F. In fact the main reason for this is that a hexadecimal digit represents four bits of binary. Therefore to represent an 8-bit byte needs two Hexadecimal digits, 16 bit words require 4 digits and so on.
Going back, a base address of 300H is exactly the same as 768 in normal decimal. The chip has four ports all numbered from the base address, the first is at address 300H (768), the next is at 301H (769), then 302H (770) and finally 303H (771).
This is a table of which registers are at what addresses
| Address ( Base=300H) | Base Address Offset |
8253/8254 Register | |
| Hexadecimal | Decimal | ||
| 300H | 768 | 0 | Timer / Counter 0 |
| 301H | 769 | 1 | Timer / Counter 1 |
| 302H | 770 | 2 | Timer / Counter 2 |
| 303H | 771 | 3 | Con trol Register |
And here's a table of control bytes.
| SC Function | Value | M Function | Value | RL Function | Value |
| Select Counter 0 | 0 | Mode 0 | 0 | Counter Latch | 0 |
| Select Counter 1 | 64 | Mode 1 | 2 | LSB Only | 16 |
| Select Counter 2 | 128 | Mode 2 | 4 | MSB Only | 32 |
| Mode 3 | 6 | LSB then MSB | 48 | ||
| Mode 4 | 8 | ||||
| Mode 5 | 10 | ||||
To use this table select one number from each of the three Value columns, add the three number together and send this number to the control register. As you may have noticed you will need to send three control bytes to set up the three counters.
Example: Suppose you want to make Counter 0 generate square waves, and uses LSB and MSB read/write loading. What is the proper control word?
Select Counter 0 gives a value 0, for square wave generation, you use Mode 3 giving value 6, and LSB then MSB counter loading gives a value of 48. Thus adding the values together gives 54 decimal. Thus you would load the control register with 54.
If you prefer, here's a calculator if you want to do it the easy way.
Many programmers put a little bit at the top of their program that lays out the base address and other register addresses and then uses these definitions throughout the remaining program. This makes it much easier later if you have to change the base address on the card to suit another machine.
For example:-
110 BaseAddress = 768
120 Timer0 = BaseAddress
130 Timer1 = BaseAddress + 1
140 Timer2 = BaseAddress + 2
150 Control = BaseAddress + 3
160 OUT Control, 54 REM Timer0 Mode3 LSB-MSB
By the way the REM statement signifies that a REMark follows, this allows the programmer to add comments to the program for future reference.
Ok so what's this about LSB and MSB? you may be asking. Well if you have already read the spec on these chips you may have noticed that they have 16 bit counters. Remember all ports have only 8 bits so, each counter has to be loaded in two chunks i.e. two 8 bit pushes. LSB stands for Least Significant Byte and MSB stands for Most Significant Byte. So when talking about a 16 bit word, you can express the upper half as being the MSB, and the lower half as being the LSB.
This can be done by a few methods you can just write one byte at a time or as normal, first write the LSB and immediatly follow this with the MSB.
With 16 bits, each counter can have values ranging from:
0000000000000000 (16 zeros) to 1111111111111111 (16 ones)
in binary, or 0 to 65535 decimal. For example, to load counter0 with 10,000 decimal, the LSB is 16 decimal, and its MSB is 39 decimal.
You're probably thinking how on earth, does that work?. Well, it's all down to that peculiarity of us wanting to speak decimal and computers wanting to speak binary. Each 8 bit byte has a range of 256, so the MSB value is how many 256's you want in you count and the LSB being the remainder. Simple eh!
Well maybe not if you're working in decimal, this is why many programmers speak in Hexadecimal, 'cause it's a lot easier to split a four digit hex number into two halves. For instance 10000 decimal is 2710H, splitting this into two halves gives the MSB=27H and the LSB=10H. But if you prefer to continue to work in decimal then follows is the way to do it using your trusty plastic brain (calculator).
If you need to check your results multiply the LSB by 256 than add your LSB and you should come back to the value you want.
And if you were really quick there you would have noticed that 27H is the same as 39 decimal and 10H is the same as 16 decimal.
You may find this calculator useful, if you prefer to work in decimal, for calculating the MSB / LSB values.
As we've told the chips control word that we are going to write 16-bit byte values with the LSB first followed by the MSB, our code will end up looking like the following:
110 BaseAddress = 768
120 Timer0 = BaseAddress
130 Timer1 = BaseAddress + 1
140 Timer2 = BaseAddress + 2
150 Control = BaseAddress + 3
160 OUT Control, 54 REM Timer0 Mode3 LSB-MSB
170 OUT Timer0, 16 REM LSB Load value = 10000
180 OUT Timer0, 39 REM MSB Load value = 10000
Ok so far we have only been sending data to the chip, it is also possible to read values from the chip. By reading the counter value you can determine how many pulses it has received. It must be remebered that rather than counting upwards (0,1,2..., etc.), the 8253/54's counters count downwards (10000, 9999,9998,.. etc.). In many of the operating modes, the counter will wrap around and start at 65535 after it has reached 0.
You can give a counter a preset value to start counting down from by writing this value to it, as with the code above, Timer0 starts counting down from 10000.
Clock Source
So far we have spent a lot of time talking about how to load values into the counters, but havn't mentioned much about what these counters are counting. Well simply put the counters will count pulses going into their CLK pin. On our cards there is the option of using the internal clock or to use an external clock. If we use a clock of 1MHz and the maximum counter value of 65535 then the timer will have finished in about a fifteenth of a second. Which as you may say, won't be a fat lot of good if we were to use this to cook our meal in the microwave.
To get around this problem we can string these counters together so that the first counter divides the master clock frequency down to something a little slower, then feed this slower rate into a second counter. To do this takes a little bit juggling about with the wiring as well as now loading values into two timers.
So if we use Timer 0 as our first counter in the chain, clocked by an internal source of let's say 1 MHz and do a divide by our 10000, then the output of this counter will be at a rate of 100Hz. Which is a much easier frequency to deal with. If we then use a bit of wire to connect the output of Timer 0 to the input of Timer 1, we can then program Timer 1 based on a 100Hz feed.
A Small Project
So now to make, lets say, a timer to give a 10 second pulse we need to feed Timer 1 counter register with 100(Hz) x 10(Secs)=1000. Now you will need to go through the calculations again to work out the MSB and LSB split, but to save time MSB=3, LSB=232. So if we just want to give a 10 second pulse, we program Timer1 for Mode 1, i.e. One Shot.
110 BaseAddress = 768
120 Timer0 = BaseAddress
130 Timer1 = BaseAddress + 1
140 Timer2 = BaseAddress + 2
150 Control = BaseAddress + 3
160 OUT Control, 54 REM Timer0 Mode3 LSB-MSB
170 OUT Timer0, 16 REM LSB Load value = 10000
180 OUT Timer0, 39 REM MSB Load value = 10000
190 OUT Control, 114 REM Timer1 Mode1 One Shot
200 OUT Timer1, 3 REM LSB Load value = 1000
210 OUT Timer1, 253 REM MSB Load value = 1000
That's it, now when you trigger Timer 1 by forcing the gate input high, the output of Timer 1 will go low for 10 seconds, try it.
You will need to connect up the chip to cascade the first two timers, i.e. you'll have to do a bit of wiring. If you are using one of our DC-0630 Terminal Boards then the following diagram may be useful.
The terminal board is for use with either our
DC-0600 or DC-0620
cards. On the card CLK0 should be set to internal source, and CLK1 to external,
i.e. JP1-1 linked & JP1-2 open. The LED can be any colour or size, the 'k'
or cathode is normally the longer leg of the two. The resistor values are not
critical, the one resistor is just acting against the push switch and can be
more or less any value. The other resistor limits the power into the LED, the
lower the value the brighter the LED, but don't go too low!.
As you can see programming the 8254 is not very complicated. The 8254's other modes can be programmed similarly.
Program mode 3 was illustrated to demonstrate the 8253/54 chip's square wave generating ability. And mode 1 illustrated a simple timer function. In the near future, we will be adding further tutorials to illustrate using the 8254 for the following:-