8253/8254 Timer and Counter Basics
Generating Precise Timing with Hardware
Open interactive version (quiz + challenge)Real-world analogy
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
- 8253/8254 Overview — The 8253 (and its improved version 8254) is a programmable interval timer with three independent 16-bit counters (Counter 0, 1, 2). Each counter has a CLK input (clock), a GATE input (enable), and an OUT output. The CPU loads a count value, and the counter decrements on each clock pulse. When it reaches zero, the output changes based on the selected mode. The 8254 adds a read-back command.
- Control Word Format — The control word (written to base+3) selects the counter, read/load mode, operating mode, and BCD/binary format. Bits 7-6 select the counter (00=C0, 01=C1, 10=C2). Bits 5-4 select read/load (01=MSB only, 10=LSB only, 11=LSB then MSB). Bits 3-1 select the mode (000-101). Bit 0 selects binary (0) or BCD (1) counting.
- Mode 0 — Interrupt on Terminal Count — In Mode 0, the output starts LOW. The CPU loads a count value N. The counter decrements on each CLK pulse. When it reaches zero, the output goes HIGH and stays HIGH until a new count is loaded. This mode is used for one-shot timing events — like generating a single interrupt after a precise delay.
- Mode 2 — Rate Generator — Mode 2 produces a periodic LOW pulse. The output stays HIGH for N-1 clock cycles, goes LOW for 1 clock cycle, then reloads and repeats automatically. This creates a divide-by-N frequency divider. If CLK is 1.19318 MHz (IBM PC) and N=65536, you get about 18.2 Hz — the famous PC timer tick rate used by DOS for timekeeping.
- Mode 3 — Square Wave Generator — Mode 3 produces a symmetrical square wave. For even N, the output is HIGH for N/2 clocks and LOW for N/2 clocks — a perfect 50% duty cycle. For odd N, it is HIGH for (N+1)/2 and LOW for (N-1)/2. This mode is used in the IBM PC to drive the speaker (Counter 2) for generating audible tones of different frequencies.
- All Six Modes Summary — Mode 0: Interrupt on terminal count (one-shot, OUT goes HIGH at zero). Mode 1: Hardware-retriggerable one-shot (pulse output, triggered by GATE rising edge). Mode 2: Rate generator (periodic LOW pulse, divide-by-N). Mode 3: Square wave generator (50% duty cycle). Mode 4: Software-triggered strobe (one-shot LOW pulse). Mode 5: Hardware-triggered strobe (GATE-triggered LOW pulse).
- GATE Input Behavior — The GATE pin controls whether counting is enabled. In Modes 0 and 2-3, GATE must be HIGH for the counter to decrement (GATE=LOW pauses counting). In Modes 1 and 5, a rising edge on GATE starts/restarts counting (hardware trigger). In the IBM PC, Counter 0 and 1 have GATE tied HIGH (always enabled), while Counter 2's GATE is controlled by a port bit to enable/disable the speaker.
- Reading the Current Count — You can read the current count value while the counter is running. Method 1: Counter Latch — write a latch command (RL=00 in control word) to freeze the count in a latch register, then read LSB and MSB without stopping the counter. Method 2 (8254 only): Read-Back command — read count and/or status from one or more counters simultaneously.
- IBM PC Timer System — The IBM PC uses an 8254 at I/O ports 40h-43h with a 1.193182 MHz clock. Counter 0 generates the ~18.2 Hz system timer interrupt (IRQ0). Counter 1 triggers DRAM refresh (about every 15 microseconds). Counter 2 drives the PC speaker. This architecture persisted through decades of PC evolution — your modern PC still emulates these three timers for backward compatibility.
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 snapshotLine-by-line walkthrough
- 1. Title comment for the timer example
- 2. Separator line
- 3. Blank line
- 4. Timer base address is 40h, system clock is 1.193182 MHz
- 5. Blank line
- 6. Section: Counter 0 configured for 1ms periodic interrupt
- 7. Mode 2 rate generator with count 1193 produces 1000 Hz (1ms period)
- 8. Comment: output frequency = 1193182 / 1193 ≈ 1000 Hz
- 9. Blank line
- 10. Control word breakdown: counter 0, LSB+MSB load, Mode 2, binary
- 11. Binary: 00110100 = 34h
- 12. Blank line
- 13. Load control word 34h into AL
- 14. Write to control register at port 43h
- 15. Load LSB of count value 1193 (hex 04A9) — A9h
- 16. Write LSB to Counter 0 at port 40h
- 17. Load MSB of count value — 04h
- 18. Write MSB to Counter 0 — counting begins immediately at 1 KHz
- 19. Blank line
- 20. Section: Counter 2 for 440 Hz speaker tone (concert pitch A)
- 21. Mode 3 square wave with count 2712 produces 440 Hz
- 22. Blank line
- 23. Control word: counter 2, LSB+MSB, Mode 3, binary = B6h
- 24. Blank line
- 25. Load control word B6h
- 26. Write to control register
- 27. Load LSB of 2712 (hex 0A98) — 98h
- 28. Write LSB to Counter 2 at port 42h
- 29. Load MSB — 0Ah
- 30. Write MSB — Counter 2 now generates 440 Hz square wave
- 31. Blank line
- 32. Enable the speaker by setting bits in port 61h
- 33. Read current value of port 61h
- 34. OR with 03h to set bit 0 (GATE2) and bit 1 (speaker enable)
- 35. Write back — speaker now audibly produces the 440 Hz tone
- 36. Blank line
- 37. Section: Reading Counter 0 while it runs
- 38. Counter latch command: 00h latches counter 0's current value
- 39. Write latch command to control register
- 40. Read LSB from counter 0
- 41. Store LSB in CL
- 42. Read MSB from counter 0
- 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, ALNeed a hint?
Show answer
Explain like I'm 5
Fun fact
Hands-on challenge
More resources
- 8253/8254 Timer Explained (Neso Academy)
- 8254 Programmable Interval Timer (GeeksforGeeks)
- Intel 8254 Datasheet (Intel)
- PC Speaker Programming (Ben Eater)