カソードコモンの8セグメントLEDへ表示する(HT16K33を使う)


久しぶりに新しいLEDドライバーを入手しました。
LED専用ドライバーのHT16K33を 使って8セグメントLEDを表示する方法を紹介します。
このチップは汎用のLEDドライバーで、16*8のLEDを制御することができます。
このチップには20ピン 24ピン 28ピンの製品が有りますが、今回は28ピンの製品を使いました。
これらの製品の違いは以下のようになります。

IC2アドレス
制御可能LED
20ピン
0x70固定
8*8
24ピン
0x70-0x73
12*8
28ピン
0x70-0x77
16*8

このチップも電流制限機能を持っていますので、電流制限用の抵抗はまったく必要ありません。
また各LEDのON/OFFはチップ内のトランジスタが高速で行いますので、チラつきも無く非常に綺麗な表示です。


このチップは内部に8Bit*16個のレジスターを持っていて、このレジスターに値を設定することでLEDをON/OFFします。
レジスターは以下の様に8Bit単位にアクセスすることができます、

ROW0〜7
ROW8〜15
COM0
0x00H
0x01H
COM1
0x02H
0x03H
COM2
0x04H
0x05H
COM3
0x06H
0x07H
COM4
0x08H
0x09H
COM5
0x0AH
0x0BH
COM6
0x0CH
0x0DH
COM7
0x0EH
0x0FH

4桁の8セグLEDで使う場合、以下の様に4つのLEDを制御することができます。
4つの4桁LEDなので、合計16桁となります、

ROW0〜7
ROW8〜15
COM0
LED1 Digit1
LED2 Digit1
COM1
LED1 Digit2
LED2 Digit2
COM2
LED1 Digit3
LED2 Digit3
COM3
LED1 Digit4
LED2 Digit4
COM4
LED3 Digit1
LED4 Digit1
COM5
LED3 Digit2
LED4 Digit2
COM6
LED3 Digit3
LED4 Digit3
COM7
LED3 Digit4
LED4 Digit4

例えば以下の値をレジスターに設定すると
COM0がLOWになると同時に、ROW0〜7に0b00000011、ROW8〜15に0b11000000を出力します。
その結果、LED1の1桁目とLED2の1桁目が表示されます。

COM0がHIGH、COM1がLOWとすると、ROW0〜7に0b00001100、ROW8〜15に0b00110000を出力しま す。
その結果、LED1の2桁目とLED2の2桁目が表示されます。

ROW0〜7
ROW8〜15
COM0
0b00000011 0b11000000
COM1
0b00001100 0b00110000
COM2
0b00110000
0b00001100
COM3
0b11000000
0b00000011
COM4
0b00000000
0b00000000
COM5
0b00000000
0b00000000
COM6
0b00000000
0b00000000
COM7
0b00000000
0b00000000

4桁のLEDを2つ使う場合の結線は以下の通りです。
もし、4桁のLEDを4つ使う場合は、COM4からCOM7も使います。
HT16K33のピン番号 LED1への接続(ピン番号) LED2への接続(ピン番号) Raspberryへの接続(ピン番号)
1(VSS)

GND
2(COM0) Digit1 Common Digit1 Common
3(COM1) Digit2 Common Digit2 Common
4(COM2) Digit3 Common Digit3 Common
5(COM3) Digit4 Common Digit4 Common
6(COM4)


7(COM5)


8(COM6)


9(COM7)


10(ROW15)
Segment D.P
11(ROW14)
Segment g
12(ROW13)
Segment f
13(ROW12)
Segment e
14(ROW11)
Segment d
15(ROW10)
Segment c
16(ROW9)
Segment b
17(ROW8)
Segment a
18(ROW7) Segment D.P


19(ROW6) Segment g


20(ROW5) Segment f


21(ROW4) Segment e


22(ROW3) Segment d


23(ROW2) Segment c


24(ROW1) Segment b


25(ROW0) Segment a


26(SCL)

5(SCL)
27(SDA)

3(SDA)
28(VDD)

5V

ソースコードは以下の通りです。
初期化コードなどは、こちらの Arduinoのコードを参考にしました。
セグメントへの表示パターンは内蔵していないので、表示パターンは自分で作る必要があります。
/*
 Raspberry Pi driving the HT16K33
 port from here
 https://github.com/lpaseen/ht16k33
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define I2CADR 0x70 // I2Cアドレス

// HT16K33コマンド
#define HT16K33_DDAP          0x00 // Display data address pointer: 0000xxxx
#define HT16K33_SS            0x20 // System setup register
#define HT16K33_SS_STANDBY    0x00 // System setup - oscillator in standby mode
#define HT16K33_SS_NORMAL     0x01 // System setup - oscillator in normal mode
#define HT16K33_KDAP          0x40 // Key Address Data Pointer
#define HT16K33_IFAP          0x50 // Read status of INT flag
#define HT16K33_DSP           0x80 // Display setup
#define HT16K33_DSP_OFF       0x00 // Display setup - display off
#define HT16K33_DSP_ON        0x01 // Display setup - display on
#define HT16K33_DSP_NOBLINK   0x00 // Display setup - no blink
#define HT16K33_DSP_BLINK2HZ  0x02 // Display setup - 2hz blink
#define HT16K33_DSP_BLINK1HZ  0x04 // Display setup - 1hz blink
#define HT16K33_DSP_BLINK05HZ 0x06 // Display setup - 0.5hz blink
#define HT16K33_RIS           0xA0 // ROW/INT Set
#define HT16K33_RIS_OUT       0x00 // Set INT as row driver output
#define HT16K33_RIS_INTL      0x01 // Set INT as int active low
#define HT16K33_RIS_INTH      0x03 // Set INT as int active high
#define HT16K33_DIM           0xE0 // Dimming set
#define HT16K33_DIM_1         0x00 // Dimming set - 1/16
#define HT16K33_DIM_2         0x01 // Dimming set - 2/16
#define HT16K33_DIM_3         0x02 // Dimming set - 3/16
#define HT16K33_DIM_4         0x03 // Dimming set - 4/16
#define HT16K33_DIM_5         0x04 // Dimming set - 5/16
#define HT16K33_DIM_6         0x05 // Dimming set - 6/16
#define HT16K33_DIM_7         0x06 // Dimming set - 7/16
#define HT16K33_DIM_8         0x07 // Dimming set - 8/16
#define HT16K33_DIM_9         0x08 // Dimming set - 9/16
#define HT16K33_DIM_10        0x09 // Dimming set - 10/16
#define HT16K33_DIM_11        0x0A // Dimming set - 11/16
#define HT16K33_DIM_12        0x0B // Dimming set - 12/16
#define HT16K33_DIM_13        0x0C // Dimming set - 13/16
#define HT16K33_DIM_14        0x0D // Dimming set - 14/16
#define HT16K33_DIM_15        0X0E // Dimming set - 15/16
#define HT16K33_DIM_16        0x0F // Dimming set - 16/16

#define NLEDS   8       // Number of Digit

// グローバル変数
//unsigned short buf[8];     // 8x16ドットパターン


// HT16K33 コマンド送信
void ht_command(int i2cd, uint8_t reg, uint8_t cmd) {
  int ret;
  ret = wiringPiI2CWrite(i2cd, reg | cmd);
//  printf("reg=%02x cmd=%02x ret=%d\n",reg,cmd,ret);
}

#define SA      0x01
#define SB      0x02
#define SC      0x04
#define SD      0x08
#define SE      0x10
#define SF      0x20
#define SG      0x40
#define SDP     0x80

void ht_8segment(int i2cd, int digit, int display) {
  uint8_t pattern[] = {
    SA+SB+SC+SD+SE+SF,          // 0
    SB+SC,                      // 1
    SA+SB+SD+SE+SG,             // 2
    SA+SB+SC+SD+SG,             // 3
    SB+SC+SF+SG,                // 4
    SA+SC+SD+SF+SG,             // 5
    SA+SC+SD+SE+SF+SG,          // 6
    SA+SB+SC,                   // 7
    SA+SB+SC+SD+SE+SF+SG,       // 8
    SA+SB+SC+SD+SF+SG,          // 9
    SG,                         // -
    SB+SC+SE+SF+SG,             // H
    SA+SD+SE+SF+SG,             // E
    SD+SE+SF,                   // L
    SA+SB+SE+SF+SG,             // P
    0                           // Space
  };

  int addr;
  if (display > 15) return;
  uint8_t data = pattern[display];
  if (digit < 4) {
    addr = digit * 2;
  } else {
    addr = (digit-4) * 2 + 1;
  }
//  printf("display=%d addr=%d data=%02x\n",display,addr,data);
  int reg = HT16K33_DDAP | addr;
  int ret = wiringPiI2CWriteReg8(i2cd, reg, data);
}

void displayNumber(int i2cd, int digit, uint32_t number) {
  int i;
  uint8_t data;

  uint32_t num = number;
  for(i=0;i<digit;i++) {
    data = num % 10;
//    printf("data[%d]=%d ",i,data);
    ht_8segment(i2cd, i ,data);     // displays the 1 digit number
    num = num / 10;
  }
//  printf("\n");
}

int main(int argc, char **argv){
  int i2cd;
  i2cd = wiringPiI2CSetup(I2CADR);
  if (i2cd < 0 ) {
    printf("wiringPiI2CSetup error %d\n",i2cd);
    return;
  }

  // Wakeup
  ht_command(i2cd, HT16K33_SS, HT16K33_SS_NORMAL);
  // Display on and no blinking
  ht_command(i2cd, HT16K33_DSP, HT16K33_DSP_ON | HT16K33_DSP_NOBLINK);
  // INT pin works as row output
  ht_command(i2cd, HT16K33_RIS, HT16K33_RIS_OUT);
  // Brightness set to max
  ht_command(i2cd, HT16K33_DIM, HT16K33_DIM_16);


  /*
  Display Memory is 16 byte(Register Address is 0x00-0x0F)

           ROW0-7       ROW8-15
  COM0     00H=Digit1   01H=Digit5
  COM1     02H=Digit2   03H=Digit6
  COM2     04H=Digit3   05H=Digit7
  COM3     06H=Digit4   07H=Digit8

  COM4     08H=Digit9   09H=Digit13
  COM5     0AH=Digit10  0BH=Digit14
  COM6     0CH=Digit11  0DH=Digit15
  COM7     0EH=Digit12  0FH=Digit16
  */

  int addr;
  int reg;
  int ret;

  // Clear all memory
  for(addr=0;addr<16;addr++) {
    reg = HT16K33_DDAP | addr;
    ret = wiringPiI2CWriteReg8(i2cd, reg, 0);
  }

  int digit;
  int display;
  for(display=0;display<16;display++) {
    for(digit=0;digit<NLEDS;digit++) {
      ht_8segment(i2cd, digit, display);
    }
    delay(500);
  }

  uint32_t number = 1;
  for(digit=0;digit<NLEDS;digit++) {
    displayNumber(i2cd, NLEDS, number);
    number = number * 10 + (digit+2);
//printf("number=%d\n",number);
    delay(500);
  }

  // Change Brightness
  int bright;
  for(bright=0x0f;bright>0;bright--) {
    ht_command(i2cd, HT16K33_DIM, bright);
    delay(500);
  }

}

このチップを使って、8x8のマトリクスLED2個を制御する方法がこ ちらに公開されています。

次回はカソードコモンの7セグメントLED専用ドライバーのCD4543Bを紹 介します。