Lesson 41 of 48 advanced

8253/8254 Timer and Counter Basics

Generating Precise Timing with Hardware

Open interactive version (quiz + challenge)

Real-world analogy

The 8253 timer is like three separate hourglasses in one box. Each hourglass (counter) starts with a number of sand grains (count value) and loses one grain with every tick of a clock. When the sand runs out, an alarm goes off (output changes). You can set different amounts of sand and choose what happens when it runs out — ring once, ring repeatedly, or generate a steady beat. The control word is the instruction card telling each hourglass how to behave.

What is it?

The 8253/8254 Programmable Interval Timer contains three independent 16-bit down counters, each with CLK, GATE, and OUT pins. A control word selects the counter, read/load mode, operating mode (0-5), and BCD/binary counting. Mode 2 (rate generator) and Mode 3 (square wave) are the most commonly used. The timer is essential for generating periodic interrupts, producing audio tones, and creating precise time delays.

Real-world relevance

The IBM PC's 8254 timer at port 40h-43h is one of the most famous uses. Counter 0 drives the 18.2 Hz system tick (used by DOS for timekeeping), Counter 1 refreshes DRAM, and Counter 2 generates the iconic PC speaker beeps. Modern PCs still emulate the 8254 in their chipsets. Every time your computer beeps at POST or plays a simple tone, it is using the same timer architecture designed in the 1980s.

Key points

Code example

; =============================================
; 8253/8254 Timer — Multi-Mode Example
; =============================================
;
; Timer at base address 40h, CLK = 1.193182 MHz
;
; --- Counter 0: 1ms periodic interrupt ---
; Mode 2 (rate generator), count = 1193
; Freq = 1193182 / 1193 ≈ 1000 Hz (1ms period)
;
; Control: SC=00, RL=11, Mode=010, BCD=0
;          00 11 010 0 = 34h
;
  MOV AL, 34h
  OUT 43h, AL           ; control word for C0
  MOV AL, 0A9h          ; LSB of 1193 (04A9h)
  OUT 40h, AL
  MOV AL, 04h           ; MSB of 1193
  OUT 40h, AL           ; C0 now ticks at 1 KHz
;
; --- Counter 2: 440 Hz speaker tone ---
; Mode 3 (square wave), count = 2712
; 440 Hz = concert pitch A
;
; Control: SC=10, RL=11, Mode=011, BCD=0
;          10 11 011 0 = B6h
;
  MOV AL, 0B6h
  OUT 43h, AL           ; control word for C2
  MOV AL, 98h           ; LSB of 2712 (0A98h)
  OUT 42h, AL
  MOV AL, 0Ah           ; MSB of 2712
  OUT 42h, AL           ; C2 generates 440 Hz
;
; Enable speaker (connect C2 OUT to speaker)
  IN AL, 61h
  OR AL, 03h            ; set GATE2 + speaker enable
  OUT 61h, AL           ; speaker ON — hear 440 Hz!
;
; --- Read Counter 0 current value ---
  MOV AL, 00h           ; latch counter 0
  OUT 43h, AL
  IN AL, 40h            ; read LSB
  MOV CL, AL
  IN AL, 40h            ; read MSB
  MOV CH, AL            ; CX = current count snapshot

Line-by-line walkthrough

  1. 1. Title comment for the timer example
  2. 2. Separator line
  3. 3. Blank line
  4. 4. Timer base address is 40h, system clock is 1.193182 MHz
  5. 5. Blank line
  6. 6. Section: Counter 0 configured for 1ms periodic interrupt
  7. 7. Mode 2 rate generator with count 1193 produces 1000 Hz (1ms period)
  8. 8. Comment: output frequency = 1193182 / 1193 ≈ 1000 Hz
  9. 9. Blank line
  10. 10. Control word breakdown: counter 0, LSB+MSB load, Mode 2, binary
  11. 11. Binary: 00110100 = 34h
  12. 12. Blank line
  13. 13. Load control word 34h into AL
  14. 14. Write to control register at port 43h
  15. 15. Load LSB of count value 1193 (hex 04A9) — A9h
  16. 16. Write LSB to Counter 0 at port 40h
  17. 17. Load MSB of count value — 04h
  18. 18. Write MSB to Counter 0 — counting begins immediately at 1 KHz
  19. 19. Blank line
  20. 20. Section: Counter 2 for 440 Hz speaker tone (concert pitch A)
  21. 21. Mode 3 square wave with count 2712 produces 440 Hz
  22. 22. Blank line
  23. 23. Control word: counter 2, LSB+MSB, Mode 3, binary = B6h
  24. 24. Blank line
  25. 25. Load control word B6h
  26. 26. Write to control register
  27. 27. Load LSB of 2712 (hex 0A98) — 98h
  28. 28. Write LSB to Counter 2 at port 42h
  29. 29. Load MSB — 0Ah
  30. 30. Write MSB — Counter 2 now generates 440 Hz square wave
  31. 31. Blank line
  32. 32. Enable the speaker by setting bits in port 61h
  33. 33. Read current value of port 61h
  34. 34. OR with 03h to set bit 0 (GATE2) and bit 1 (speaker enable)
  35. 35. Write back — speaker now audibly produces the 440 Hz tone
  36. 36. Blank line
  37. 37. Section: Reading Counter 0 while it runs
  38. 38. Counter latch command: 00h latches counter 0's current value
  39. 39. Write latch command to control register
  40. 40. Read LSB from counter 0
  41. 41. Store LSB in CL
  42. 42. Read MSB from counter 0
  43. 43. Store MSB in CH — CX now holds the snapshot of the running count

Spot the bug

; Generate 1000 Hz on Counter 0, Mode 3
; CLK = 1.193182 MHz
; Count = 1193182 / 1000 = 1193 (04A9h)
;
  MOV AL, 36h          ; control: C0, LSB+MSB, Mode 3
  OUT 43h, AL
  MOV AL, 04h          ; MSB of 1193
  OUT 40h, AL
  MOV AL, 0A9h         ; LSB of 1193
  OUT 40h, AL
Need a hint?
When RL=11 (LSB then MSB), which byte must be written first?
Show answer
The MSB and LSB are written in the wrong order. When RL=11, the 8253 expects LSB first, then MSB. The code writes MSB (04h) first and LSB (A9h) second, so the counter loads 0A904h instead of 04A9h. Fix: swap the two OUT instructions — write A9h first (LSB), then 04h (MSB).

Explain like I'm 5

Imagine three countdown clocks on your desk. You set each one to a different number and they tick down together. When one reaches zero, it does something — maybe rings a bell (Mode 0), maybe restarts and rings every time it finishes (Mode 2), or maybe flashes a light on and off steadily (Mode 3). The 8253 timer is exactly that — three countdown clocks that the CPU programs with numbers and rules.

Fun fact

The 1.193182 MHz clock frequency used by the IBM PC timer was not chosen for any elegant reason. It was simply 14.31818 MHz (the NTSC color burst frequency, already available on the motherboard for the video card) divided by 12. This awkward frequency means the 18.2 Hz system tick cannot divide evenly into seconds — DOS had to add a correction every 65536 ticks to keep time accurate!

Hands-on challenge

Program the 8254 to generate a 2 KHz square wave on Counter 2 for a speaker tone. Then, using Counter 0 in Mode 0, create a one-shot delay of exactly 50ms. Calculate the required count values for a 1.193182 MHz clock. Write the complete assembly code including control words and count loading.

More resources

Open interactive version (quiz + challenge) ← Back to course: Microprocessor A–Z