SNSへはこちら

LEDドライバTM1627を使ってみた(For 7セグLEDの点灯)

たまには使った IC についての記事投稿とかをします。

今回は、LED ドライバ IC である、TM1627 を使ってみました。使用目的は 7セグLED の駆動のためです。
下の秋月電子の説明では最大7個(7 digits)の 7セグLED が使用可能とありますが、回路構成を考えるとアノードコモンのものを用いると最大 10個(10 digits)使用可能と考えられます

電子部品,通販,販売,半導体,IC,マイコン,電子工作7セグメント用LEDドライバーIC(最大7個) TM1627秋月電子通商 電子部品通信販売

また、マトリクス上のキー入力検出(パラ→シリ変換)にも対応していますが、今回はよくわからないので割愛します。タイトルのカッコは「今後やるかもしれん」という意味合いがあります(本当か??)

特長

なんといっても安いことが特長です(1個70円)。そして

  • 電流値を内部で制御してくれるので、抵抗器が不要
  • 3ピンで最大10桁の7セグを制御できる
  • ダイナミック点灯は IC が高速に行ってくれるから考慮が要らない
  • たった3ピンで制御可能なので、ピン数の節約になる

ことがメリットでしょう。一方デメリットもあって、

  • 通信方式が独特(I2C っぽかったり SPI っぽかったりするが、どちらでもない)なため、自分で波形をパタパタさせる必要がある
  • dp(小数点) は別途制御しなければならない
  • データシートが中国語しか無いので翻訳が面倒(筆者は第2外国語としてドイツ語を履修)
  • 通信に必要なウェイトが大きく、結果動作が遅くなっている

ということです。特に通信方式は若干面倒くさいです。

データシートの言語と通信方式が面倒だったので記事にしたためた次第です。

データシートのめもみたいなもの

仕様やピンの役割等を知りたい時にいちいち中国語を翻訳にかけるのは面倒なことこの上ないので、とりあえず「これさえあれば 7セグLED を点灯できるだろう」という内容をまとめた PDF を用意しました。どうぞ。

なお、アノードコモンの LED を用いた際のめもであることをご注意あれ。
TM1627使用メモ

取り敢えずこれで内部のレジスタ構成、コマンドの理解はできるでしょう。

通信方式

厄介なところです。他の似ている TM16xx シリーズでは1バイト送出後に9クロック目を入れて ACK の返答を確認せねばならなかったりするものがありますが、この TM1627 には ACK 確認はありません

また、データの送受信を行う DIO ピンですが、これは双方向にデータのやり取りができるように(というより、信号が衝突しないように)、オープンドレイン とする必要があります。
以上を含めて、ハマり注意ポイントを列挙しておきましょう。

  • どことなく I2C に近いが、STB(SPI の CS#)があったり、ACK 確認がなかったり、アドレス + R/W の送出がなかったりと、微妙に I2C とは違う
    • スタートコンディション・ストップコンディションはしっかりやろう。
    • LSB Firstです。
    • コマンド間のウェイトでは CLK を下げること無く High に保つ必要がある。これでだいぶハマった。
  • DIO ピンのみオープンドレイン。IC 内部でプルアップされているので、外部抵抗不要。
    • その他の CLK, STB は全て通常のプッシュプルで OK。
  • K1, K2 はガン無視で OK。

通信のための擬似コード

ご参考にどうぞ。というか僕がオレオレライブラリを用いて動かしているのですが、そのままのコードを貼り付けます。十分読めると思いますが。

また、何処にどのデータを書けば良いのか?についてはデータシートを参考にしてください。

#include <stm32f3xx.h>
#include <gpio.hpp>

#include <new>

static char buf_stb[sizeof(Gpio)];
static char buf_dio[sizeof(Gpio)];
static char buf_clk[sizeof(Gpio)];
static Gpio *stb; // #18, GPIOA8
static Gpio *dio; // #19, GPIOA9
static Gpio *clk; // #20, GPIOA10

namespace serial {
void init() {
    GpioConfig cfg;
    cfg.mode = GpioConfig::PinMode::GPIO_OUTPUT;
    cfg.outputtype = GpioConfig::PinOutputType::OD;
    stb = new(buf_stb) Gpio(GPIOA, 8, GpioConfig::PinMode::GPIO_OUTPUT);
    dio = new(buf_dio) Gpio(GPIOA, 9, cfg);
    clk = new(buf_clk) Gpio(GPIOA, 10, GpioConfig::PinMode::GPIO_OUTPUT);

    *stb = 1;
    *dio = 0;
    *clk = 1;
}

static void wait() {
    for(volatile int i = 0; i < 10; i++);
}

static void startCondition() {
    *stb = 0;
    wait();
    *clk = 0;
    wait();
}

static void stopCondition() {
    *clk = 1;
    wait();
    *stb = 1;
    wait();
}

static void stbPulse() {
    *stb = 1;
    wait();
    *stb = 0;
    wait();
}

static void sendBit(bool bit) {
    *clk = 0;
    *dio = bit;
    wait();
    *clk = 1;
    wait();
}

void sendByte(uint8_t data) {
    for(int i=0; i<8; i++) {
        sendBit(data & 0x01);
        data >>= 1;
    }
}

void sendLEDData(uint8_t *array) {
    startCondition();

    sendByte(0x03);
    stbPulse();

    sendByte(0x40);
    stbPulse();

    sendByte(0xC0);
    for(int i=0; i<14; i++) {
        if( array != nullptr ) {
            sendByte(array[i]);
        }else{
            sendByte(0x00);
        }
    }
    stbPulse();

    sendByte(0x8A);
    stopCondition();
}
}

動作させた例

スイッチを使ってインクリメント、デクリメントの例をやってみました。こんな感じに動きます。

終わりに

独自の通信方式を使っているということだけあって、データシートの波形をしっかり読んで、しっかりそれに従うのが大事だと知りました。
色々と適当な判断をしたせいでハマりにハマり、かなり時間を溶かしてしまいました。悲しい。

Ad
Ad

SNSへはこちら

RSS等はこちら