7セグメントLEDドライバTM1637は電子工作の代名詞的なLED表示器をシリアル通信で6桁までドライブできて安価なので重宝しています。

TM1637を表示だけに使っていたのですが,16個までキースキャニングできる機能もあるので試してみました。


機材は手持ちの以下です。
MPU:ATtiny402
7segLED:TOT5321BS-9B(3桁)
LEDドライバ:TM1637
スイッチ:タクトスイッチ,5個




大まかな構成と接続です。




キースキャニングして1byteのスキャン値を表示してみました。
何も押されていない時の値は"255"で,各スイッチは3bitとK1, K2の組み合わせで表現されます。






TM1637の表示とキースキャンのソフトの概要

TM1637のシリアル通信はI2Cのようでスレイブアドレスなどが無い独自の様式ですね(^^)。


1.表示のコマンドと流れ








2.キースキャンニングのコマンドと流れ





☆ 注意が必要な点

・TM1637のACKは8回目のクロックを終えた時にデータ線のLOWで表現されます。この時はホスト側の出力もLOWにしておき,その後ホストからクロックを1回出してACKを終了させます。

・キースキャンのバイトを読み込み,ACKを終えたらデータピンを出力に戻さないと"END"の出力もできません(^^;;;;;;;。



ま,何とか無事にキースキャンもできました。8pinのMPUなどでボタンスイッチが何個か欲しい時には便利そうです。

以下に,チェックプログラムをメモしておきます。1KB未満のプログラムなのでATtiny202でも動かしてみようかなと思っています。


/**** Check_Program for ATtiny402, 412
3digit LED & Key (TM1637) */


// I/O Pin for TM1637 LED Driver
#define dataPin 0
#define clockPin 1

// 7Seg LED Data 0,1,,,9
byte segData[10]={0x3F,0x06,0x5B,0x4F,0x66,
0x6D,0x7D,0x07,0x7F,0x6F};

byte dispN[3]; // 3digit

void setup() {
pinMode(dataPin, OUTPUT ); // Set Pin for TM1637
pinMode(clockPin, OUTPUT );

delay (100); // waiting 100ms

/* Init TM1637, Command1 */
// 0b0100 0S00, S=0/1(Auto increment /fix Address)
sStart();
s1byte(0b01000000);
sEnd();

}

void loop() {
byte nm=rData(); // Read Key status
dispN[0]=segData[nm/100];
dispN[1]=segData[(nm%100)/10];
dispN[2]=segData[nm%10];

// send data (start position, number of digits)
sData(0, 3);

sCommand3(); // show the data
delay (50);

}

/* send data: Command2(set RAM Address) and write data */
void sData(byte st, byte dig){
sStart();
s1byte(0xC0+st); // TM1637 Address (0xC0-C5)
for(byte i=0; i < dig; i++){
s1byte(dispN[i]);
}
sEnd();
}

/* read Key : command1 (key enable), read key */
byte rData(){
byte kv=0; // key value
// 0b0100 0SR0, S=0/1(Auto increment /fix Address), R=1(Read)
sStart();
s1byte(0b01000010); // set read key mode

pinMode(dataPin, INPUT ); // Set Pin for read key
kv=shiftIn(dataPin, clockPin, LSBFIRST); // Read 1byte
digitalWrite(clockPin,HIGH); // 9th pulse
digitalWrite(clockPin,LOW);

pinMode(dataPin, OUTPUT ); // Reset Pin for output
digitalWrite(dataPin,LOW);
sEnd();

sStart();
s1byte(0b01000000); // Reset write mode
sEnd();

return kv;
}


// Command3,Display and Brightness setting
void sCommand3(){
sStart();
// 0b1000 DBBB (D:on/off Brightness:000-111)
s1byte(0b10001011);
sEnd();
}

/* Start signal of serial comm. */
void sStart(){
digitalWrite(dataPin,HIGH) ; // DIO High
digitalWrite(clockPin,HIGH) ; // Clock High
digitalWrite(dataPin,LOW); // DIO High->Low
}

/* End signal of serial comm. */
void sEnd(){
digitalWrite(clockPin,HIGH) ; // Clock High
digitalWrite(dataPin,HIGH); // DIO Low->High
}

/* send 1byte of command or data */
void s1byte(byte byteData){
digitalWrite(clockPin,LOW); // Set clockPin LOW
shiftOut(dataPin, clockPin, LSBFIRST, byteData); // send 1byte
digitalWrite(dataPin,LOW); // for Ack
digitalWrite(clockPin,HIGH); // 9th pulse
digitalWrite(clockPin,LOW);
}