HT16K33 Seven-Segment Display

This application is for a 4-digit 7-segment display controlled by an HT16K33 [1] driver chip. This handles the multiplexing of the display, and provides an I2C interface.


The display is available from Adafruit [2], or Proto-Pic in the UK [3]. It's available in a range of colours.

You can select from eight I2C addresses using solder links on the back of the board; the default I2C address with no links is #x70 or 112.

Defining the seven-segment patterns

The variable seg defines the seven-segment display patterns for the digits 0 to 9:

(defvar seg '(#x3F #x06 #x5B #x4F #x66 #x6D #x7D #x07 #x7F #x6F))

Initialising the display

Next the routine on initialises the display and sets the brightness to a value between 0 and 15:

(defun on (bri)
  (with-i2c (str #x70)
    (write-byte #x21 str)
    (restart-i2c str) 
    (write-byte (+ bri #xe0) str)
    (restart-i2c str)
    (write-byte #x81 str)))

Displaying a value

Here's the routine tim to display a four-digit value, such as the time:

(defun tim (hr min col)
  (with-i2c (str #x70)
    (write-byte 0 str)
    (dolist (c (list
                (nth (/ hr 16) seg) 
                (nth (mod hr 16) seg) 
                (nth (/ min 16) seg)
                (nth (mod min 16) seg)))
      (write-byte c str)
      (write-byte 0 str))))

For each display digit you have to write two bytes to the display; this is for compatibility with Adafruit's other displays, and for this display the second byte is always zero. Curiously, there are effectively five digits, with the colon counted as the third digit, and to light it you have to write the value 2.

For example, to display 23:45 you can do:

(tim #x23 #x45 2)

  1. ^ HT16K33 Datasheet on Adafruit.
  2. ^ Adafruit 0.56" 4-Digit 7-Segment Display w/I2C Backpack on Adafruit.
  3. ^ Adafruit 0.56" 4-Digit 7-Segment Display w/I2C Backpack on Proto-Pic.