↑ 基板全景





↑ 接続コード付きでした

全ての販売基板がコード付きとは限らない
価格もまちまちの様な感じがします。









超安価なTM1638制御LED基板

AMAZONで購入した超安価な中華LED基板です。
接続コード付きで1セット300円位で5セット購入しました。
付属コード使用でそのままPICキットにしっぽりと接続できました。
今回は何一つハードウエア製作はしていません。

と言う訳で、制御関数を作ってみる事にしました。
TM1638のマニュアルをネットで探すと、以前のTM1637と違って英文マニュアルが出て来ました。
英語は読めないが中国語よりマシですHi

インターフェイスは3線シリアルで一見SPIそっくりですが微妙に違う様です。
データ出力ピンも無いですし、当局版SPI関数では動作しません。

参考文献
 TM1638マニュアル TITAN MICRO ELECTRONICS
 XC8用DFR0090制御関数ライブラリ JA0QONホームページ


↑ PIC側との接続は5ピン

 今回の回路図はありません

 実際はPICキットの14ピンCPU基板にこのTM1638LED基板を付属のコードで接続しただけ・・・


TM1638への接続は3線SPIモドキで接続・制御

基板のピンレイアウトを参照して下さい。
PICのデジタルI/Oを3ポート使用します。
これらをSPI機器開発用実験基板に接続して実験し始めました。
以下はマニュアルのタイミング表から推察しています。(文字はよく解らん)

(1)基板側のピン機能
  CLKピン クロック入力
        送信の場合 ↑でDIOピンのビットデータをTMが認識
        受信の場合 ↓でTM1638がデータを提示
              CLK=Lにして1uS位経ってから読み込む
              ↑でCPU側が読み取り終了とTMが認識
  DIOピン データビット本体
  STBピン チップセレクト(↓でデータ受付開始、↑でラッチ)
  VCCピン 5V
  GNDピン 
  注)基本的に各パルスエッジから1uS後に次のアクションが良さげ

(2)TM1638データ送信基本シーケンス
  これは単発コマンド送信等で使用する
  送信ビットはLSBから順に提示

  ①バス・アイドル状態
   CLK=1、DIO=ANY、STB=1
  ②STB=0とする
  ③CLK=0とし、DIO=1or0、任意のビットデータをセット
  ④CLK=1とすると、シフトレジスタにデータが取り込まれる
  ⑤③に行く、これを8回繰り返し
  ⑥STB=1とし、送信終了、コマンドが反映される
   バス・アイドル状態になる

(3)TM1638連続送信シーケンス
  これはコマンドとデータを一気に送信するのに使用

  ①バスアイドル状態
  ②STB=0とする
  ③CLK=0とし、DIOをセットしてCLK=1、
   これを8回繰り返し(コマンド)
  ④CLK=0とし、DIOをセットしてCLK=1、
   これを8回繰り返し(データ1)
  ⑤CLK=0とし、DIOをセットしてCLK=1、
   8回繰り返し(データn)
  ⑥⑤を必要回数繰り返し
  ⑦STB=1とし、送信終了、データが反映される
   バス・アイドル状態になる

(4)TM1638マトリックススイッチデータ受信シーケンス
  これは基板上のタクトスイッチの接点状態を把握する
  受信ビットはBYTE1のLSBから提示される
  次のBYTE2もLSBから提示される
  BYTE1からBYTE4の32ビットを連続受信する

  ①バスアイドル状態
  ②STB=0とする
  ③CLK=0とし、DIOをセットしてCLK=1、
   これを8回繰り返し(受信コマンドを送信)
  ④2usウェイト、DIOピンを入力モードにTRIS変更
  ⑤CLK=0とし、DIOポート読込してCLK=1、
   これを32回繰り返し
  ⑥STB=1とし、受信終了
  ⑦DIOピンを出力とし受信シーケンス終了、バス・アイドル状態になる




↑ 今回の構成

PICキット、14ピンCPU基板
TM1638付属のコードで、
 RC0→CLKピン
 RC1→DIOピン
 RC2→STBピン
と接続
RA4,5にはLEDモジュールを接続

ただし、プログラムの初期作成時は、当局版SPI開発用実験基板にTM1638を接続して基本関数の作成をしました。
初期関数の動作確認をしてから、今回の構成に移行して、デバッグやデモプログラム等の作成をしています。





TM1638コマンド概要

とりあえず動作に必要なコマンドを調べてみました。
コマンドは8ビットで構成され、大別すると3種類存在します。

(1)コマンドの種類
   コマンドバイトのbit7,bit6で振り分けられます。
B7 B6  インストラクション
 0  1   データ・コマンド
 1  0   ディスプレイ・コントロール・コマンド
 1  1   アドレス指定コマンド


(2)データ・コマンド
  NA:このビットには機能が割り振られていません

B7 B6 B5 B4 B3 B2 B1 B0  機能
 0  1 NA NA  X  X  0  0  データ書き込み①
 0  1 NA NA  X  X  1  0  データ読み込み②
 0  1 NA NA  X  0  X  X  オートインクリメント③
 0  1 NA NA  X  1  X  X  固定アドレス④
 0  1 NA NA  0  X  X  X  ノーマルモード⑤
 0  1 NA NA  1  X  X  X  テストモード⑥
 
 1)データ読み書き系コマンド
   B1とB0でデータの読み書きモードの指定をします。
   他のビット③~⑥の機能を加える事で機能が変化します。
   通常下記の3つで事足りると思います。
  ① 40H:ノーマルモード、オートインクリメントで書き込み
    44H:ノーマルモード、固定アドレスで書き込み
  ② 42H:ノーマルモード、32ビット連続読み込み
 2)ノーマルモード
   B3=0で指定します。
   テストモードを指定すると、どうなるのか実験していませんし、
   興味も無いです、申し訳ありません。

(3)アドレス指定コマンド
   基板には7セグLEDが8個、その真上に単LEDが8個並んでます。
   アドレスとは7セグLEDおよび単LEDの位置の事です。
   ここでは左からLED1、LED2・・・LED8とします。
   それぞれのアドレスには8ビットのデータを書き込みます。
   7セグLEDは全8ビットが有効で、単LEDはbit0のみ有効です。
   ビット=1で点灯、ビット=0で消灯となります。

 1)アドレス 対象LED
    C0H 7セグLED1
    C1H 単LED1  (B0=1でON、B0=0でOFF)
    C2H 7セグLED2
    C3H 単LED2
    C4H 7セグLED3
    C5H 単LED3
    C6H 7セグLED4
    C7H 単LED4
    C8H 7セグLED5
    C9H 単LED5
    CAH 7セグLED6
    CBH 単LED6
    CCH 7セグLED7
    CDH 単LED7
    CEH 7セグLED8
    CFH 単LED8

 2)ビットとセグメントとの関係
   bit=1でON、bit=0でOFF


     ( a )
   ( )   ( )     B0:a
   (f)   (b)     B1:b
   ( )   ( )     B2:c
     ( g )       B3:d
   ( )   ( )     B4:e
   (e)   (c)     B5:f
   ( )   ( )     B6:g
     ( d )  (dp) B7:dp


 3)各LEDアドレスへのアクセス方法
    記載事項はマニュアルのタイミング表もご参照ください
    言葉よりも図の方が解り易いと思います。

  a)アドレス連続アクセス(オートインクリメント)
   ①単発コマンドシーケンスで40Hを送信・いったん終了
   ②連続コマンドシーケンス開始
    STB=0とし、
     ③開始アドレス8bitをLSBから送信(例:C0H)
     ④7セグ用セグメントデータ8bitをLSBから送信(例:FFH)
     ⑤単LED用データ8bitをLSBから送信(例:01H)
     ⑥ ④⑤を8回繰り返し
    STB=1とし、終了
    (例データ)の結果、全てのセグメントと単LEDが発光します。
    ⑥の繰り返しを3回ならば、左から3個のLEDのみがすべて発光
   補足事項
    一度①の固定アクセスコマンドを送信すると、以後有効のままですが、
    再設定で変更されます。
    ②の連続シーケンスのみを繰り返しても有効です。
    1回の連続コマンドシーケンスで最大17バイトまでが有効です

  b)アドレス固定アクセス
   ①単発コマンドシーケンスで44Hを送信・いったん終了
   ②連続コマンドシーケンス開始
    STB=0とし、
     ③指定アドレス8bitをLSBから送信(例:C4H)
     ④7セグ用セグメントデータ8bitをLSBから送信(例:7DH)
    STB=1とし、終了
    結果、左から3番目の7セグLEDが’7’と表示します。
    他のLEDはアクセス以前と変化ありません。
   補足事項
    一度①の固定アクセスコマンドを送信すると、以後有効のままですが、
    再設定で変更されます。
    ②のシーケンスのみを繰り返しても有効です。
    1回の連続コマンドシーケンスで必ず2バイト送信が有効です。
    7セグLEDのみアクセスする場合、アドレスが1つ置きの偶数値、
    単LEDのみアクセスする場合、アドレスが1つ置きの奇数値となる。
    それぞれのLEDに対して、アドレス+データの2バイト送信する


(3)ディスプレイ・コントロール・コマンド
  NA:このビットには機能が割り振られていません

B7 B6 B5 B4 B3 B2 B1 B0  機能
 1  0 NA NA  X  0  0  0  光度1/16
 1  0 NA NA  X  0  0  1  光度2/16
 1  0 NA NA  X  0  1  0  光度4/16
 1  0 NA NA  X  0  1  1  光度10/16
 1  0 NA NA  X  1  0  0  光度11/16
 1  0 NA NA  X  1  0  1  光度12/16
 1  0 NA NA  X  1  1  0  光度13/16
 1  0 NA NA  X  1  1  1  光度14/16
 1  0 NA NA  0  X  X  X  Display OFF
 1  0 NA NA  1  X  X  X  Display ON

   補足事項
    一度このコマンドを送信すると、以後有効のままですが、
    再設定で変更されます。


(4)キーパッド・データ
   マニュアルには8×3のマトリックス上にキーパッドが配置されています。
   それをBYTE1~BYTE4の32bitで送信されてくるようです。
   その内、全バイトのbit3とbit7は割り振られていない様です。
   残りの24ビットのどこかに基板上のスイッチが割り振られています。
   調べた結果が下記の通りでしたが、全ての基板がこの通りかは不明です。
   当局が入手した基板はbit0とbit4に割り振られていました。

 スイッチは左からS1、S2・・・S7、S8、です。。

B7 B6 B5 B4 B3 B2 B1 B0  
 -  0  0 S5  -  0  0 S1  BYTE1
 -  0  0 S6  -  0  0 S2  BYTE2
 -  0  0 S7  -  0  0 S3  BYTE3
 -  0  0 S8  -  0  0 S4  BYTE4

   補足事項
    スイッチがONの場合、そのビットが1となります。
    スイッチがOFFの場合、そのビットは0となります。
    その他のビットは常に0として取得されました。
TM1638LED基板 
XC8制御関数群 Ver1

ヘッダーファイル

 TM1638v1.h


関数群ファイル

 TM1638v1.c




TM1638の3線シリアルインターフェイスの気になる点

①I/Oピンの操作を低レベル関数だけで完結出来ない
②SPI程通信速度は出せない
PIC16Fアッセンブラでノンウェイトで記載できるSPIの様な通信速度は出せず、I2C並の速度
③ラインは10KΩでプルアップされているみたいだ
TM1638側の入出力構成が不明

XC8用TM1638制御ライブラリVer1 概要

今回は当局版DFR0090用制御ライブラリVer2を移植しました
移植に当たっては、当局内のSPI機器開発用実験基板で行いました。
LCDで動作状況を確認しながらLED基板を操作するのでデバッグが楽
低レベル関数のちょっくらちょっとの変更で、上位関数は無変更、(名前だけ変更)
それで一見動作しちゃいました・・・ (^_^;)
新たに作成したのは低レベル関数と受信関数のみと言う、超手抜き作業でした。
今の所、アッセンブラ版は有りません。 <m(_ _)m>
ソースファイルには、なるべく多くコメントを記しています。
ソース自体も複雑な書き方をしていません(できない)ので、
読むと基本的な制御が分かり易いと思います。


デフォルトI/Oポート
 CLK=RC0
 DIO=RC1
 STB=RC2

ヘッダーファイル デフォルトの定義

#define CLK LATCbits.LATC0 クロックポート指定
#define DIO LATCbits.LATC1 データポート指定
#define STB LATCbits.LATC2 ストローブポート指定
#define DRP PORTCbits.RC1  DIO 読み込みポート指定
#define TRD TRISCbits.TRISC1 DIOポートのI/O設定

 ※ポート変更はヘッダーファイルの上記マクロ設定を変更
  DIO線がPICKIT3ライタ等と接続状態の場合、
  書き込みは大丈夫ですが、読み込み動作が不安定になります
  ライタを抜くと正常動作します。
  ポートをRA0-RA2等にに割り振る時はご注意ください

TM1638制御関数群

(1)通常モードでの使用関数

1) TM1638_WRTD(unsigned char)
   文字コードを指定変数の位置に表示します
   指定変数は「DSP_ADR」で、0-7を指定します
   連続送信しても表示位置は関数側が自動インクリメントします
   printf()等で使用する低レベル関数はこれを指定します
   その際は事前に「DSP_ADR」は0を指定しておきます
   引数:8bitの文字コード
   戻値:無

2) TM1638_PUTC(unsigned char1,unsigned char2)
   指定の表示位置に1文字を表示します
   引数1:文字コード1バイト
   引数2:表示位置アドレス(0-7)
   戻値:無

3) TM1638_PUTL(unsigned char1配列,unsigned char2)
   指定の表示位置から文字列を表示します(最大8文字)
   引数1:文字列格納配列アドレス
   引数2:表示開始位置アドレス(0-7)
   戻値:無

4) TM1638_PUTL1(unsigned char配列)
   LED1行目の最左側から文字列を表示(最大8文字)
   引数:文字列格納配列アドレス
   戻値:無

5) TM1638_CLR(void)
   7セグLEDのバッファおよび表示をクリア、アドレスはホーム位置
   引数:無
   戻値:無

6) 広域変数 DSP_ADR(8bit unsigned char)
   ディスプレイの表示開始位置アドレス(0-7)を格納する広域変数
   今の所、DFR90_WRTD()関数で事前設定します。

(注意点)
ドット’.’は1桁分で単独表示では無く、直前桁のドットを発光させます。
つまり、’7’、’.’、’8’、’.’と4バイト分連続書き込みすると、
「7.」と「8.」の2桁分が表示されます。
ドット’.’の書き込みではDSP_ADRは自動インクリメントされません。
ただし、先頭位置では除きます

(その他)
 使用方法については左記デモ・プログラムをご参照下さい。


(2)printf関数を使用しないメモリ節約モード

通常モード関数と同時使用すると表示がおかしくなります
printf関数を使用しない分メモリ消費が少なくて済みます。
BCD関数が含まれています。
無線周波数を表示する事を目的にしています。

 基本的な使用方法
  ①32bit符号無し整数(16進バイナリ数値)を用意
  ↓
  ②BCD関数(32bit16進数値を32bitBCDに変換)
  ↓
  ③SET_SBUF関数 (LED_BUF[ ]にデータ生成)
  ↓
  ④XFER_LED1関数(TM1638にセグメントデータ転送)

節約モード関数群

1) SET_SBUF(unsigned long 引数1,unsigned char 引数2)
   32bitBCDからフラグビットを添加し専用広域変数に展開します
   引数1:32bit符号無し整数(32bitBCD)
   引数2:8bitフラグバイト(詳細はソースファイルのコメントにて)
   戻値:専用広域配列 LED_BUF[8] に収納

2) XFER_LED1(void)
   LED_BUFのデータからセグメントデータを生成、
   TM1638に送信・表示します
   引数:広域変数 LED_BUF[ ]
   戻値:無

3) unsigned long BCD24(unsigned long)
   32bit16進バイナリ数値を40bitBCDに変換します
   引数:32bit16進バイナリ数値(0H~FFFFFFFFH)
   戻値:変換した40bitBCDの上位8bitを切り捨て、
      32bitBCDで返す


4) TM1638_CLR7SEG(void)
   7セグLEDすべてをクリアします
   引数:無
   戻値:無

5) TM1638_SET7SEG(unsigned char1,unsigned char2)
   指定のLEDにデータを送信します。
   7セグ及び単LED両方を制御できます
   引数1:LEDの指定番号1バイト(注)
   引数2:送信するデータ1バイト(0H~FFH)
   戻値:無
    注)LEDの指定番号
     00:7セグLED1
     01:7セグLED2
     02:7セグLED3
     03:7セグLED4
     04:7セグLED5
     05:7セグLED6
     06:7セグLED7
     07:7セグLED8
     16(10H):単LED1
     17(11H):単LED1
     18(12H):単LED1
     19(13H):単LED1
     20(14H):単LED1
     21(15H):単LED1
     22(16H):単LED1
     23(17H):単LED1


6) TM1638_CLRLED(void)
   単LEDすべてをクリアします
   引数:無
   戻値:無


7) TM1638_SETLED(unsigned char)
   単LEDのみを制御します
   引数:制御ビット(8ビット)(注)
   戻値:無
    (注)制御ビット
    bit7 単LED8:1=ON、0=OFF
    bit6 単LED7:1=ON、0=OFF
    bit5 単LED6:1=ON、0=OFF
    bit4 単LED5:1=ON、0=OFF
    bit3 単LED4:1=ON、0=OFF
    bit2 単LED3:1=ON、0=OFF
    bit1 単LED2:1=ON、0=OFF
    bit0 単LED1:1=ON、0=OFF


(3)両モード共通で使用する関数

1) TM1638_INIT(void)
   イニシャライズを行う。
   7セグLEDおよび単LEDの表示をクリア
   ディスプレイコントロール設定も最大光度で行います。
   一度実行すれば後は実行する必要はありません。
   引数:無
   戻値:無

2) unsigned long TM1638_RCV(void)
   TM1638のマトリックスデータを読み込みます
   引数:無
   戻値:32bitの読み込みデータ
      bit31-24:BYTE4
      bit23-16:BYTE3
      bit15-8 :BYTE2
      bit7-0  :BYTE1

3) unsigned char TM1638_KEY(void)
   TM1638基板のキーパッドのデータを読み込みます
   引数:無
   戻値:8bitのスイッチ状態データ
      bit7:S8 1=ON、0=OFF
      bit6:S7 1=ON、0=OFF
      bit5:S6 1=ON、0=OFF
      bit4:S5 1=ON、0=OFF
      bit3:S4 1=ON、0=OFF
      bit2:S3 1=ON、0=OFF
      bit1:S2 1=ON、0=OFF
      bit0:S1 1=ON、0=OFF


(4)TM1638低レベル関数

1) SEND_COM(unsigned char)
   TM1638へコマンドを送信します。
   引数1:8bitのコマンド
   戻値:無

2) SEND_DATA(unsigned char1,unsigned char2)
   TM1638へデータを送信します
   引数1:データを送信するアドレス1バイト(C0H~CFH)
   引数2:送信するデータ1バイト(0H~FFH)
   戻値:無

3) SEND_BYTE(unsigned char)
   1バイトのデータをLSBから送信します。
   STB線の制御は行いません
   引数:送信する8bitデータ
   戻値:無

4) unsigned char RCV_BYTE(void)
   8ビット分をLSBから受信処理する
   STB線は制御しない
   DIO線のTRIS制御はしない
   引数:無
   戻値:受信した8bitデータ




(その他)
 使用方法についてはデモ・プログラムのソースファイルをご参照下さい。
追加や修正・バグ等ありましたらこのページにて追記したいと思います
TM1638LED基板
 デモプログラム




↑ printf関数使用




↑ pirntf関数を使用しない




↑ 受信関数使用のデモ

SW1とSW8を同時ONにしてます
その結果、
LED1とLED8が点灯、
7セグ表示では、
BYTE1のビット1、そして
BYTE4のビット4
が”1”となりました

タクトスイッチをONさせるには結構力が必要で、使い勝手は悪いです。



デモプログラム1
 主にメモリ消費が少な目な関数使用

  XC8_16F1705_TM1638_DEMO1.c


 受信関数使用デモ

  XC8_16F1705_TM1638_RCV_DEMO01.c


 メモリ消費大きい

  XC8_16F18326_TM1638_DEMO01.c






XC8用TM1638制御ライブラリのデモンストレーション

PICキット、14ピンCPU基板の、
 PIC16F1705
 PIC16F18326
この2つの基板にTM1638を接続して動作させています。
付属のコードはTM1638ポートピンにはゆるい様で接触不良気味です。
PIC基板側は問題ありません。
TM1638側は細ピン用に変更した方が動作安定すると思います。


(1)PIC16F18326CPU基板でのデモ

  主にpirntf関数を使用したデモです
  倍精度も扱いましたので、16F1705ではメモリオーバーとなります


(2)PIC16F1705CPU基板でのデモ

  主にprintfを使用しない関数を使用しました。
  とは言っても、普通にprintf関数も使用しています。
  ただし、倍精度は扱いません。


(3)PIC16F1705CPU基板でのデモ

  受信関数を使用したデモプログラムです。
  TM1638のマトリックスデータとスイッチ状況を表示します。

   7セグ1・2:BYTE4のデータ16進表示
   7セグ3・4:BYTE3のデータ16進表示
   7セグ5・6:BYTE2のデータ16進表示
   7セグ7・8:BYTE1のデータ16進表示

   単LED1 :スイッチ1 ON=発光 OFF=消灯
   単LED2 :スイッチ2 ON=発光 OFF=消灯
   単LED3 :スイッチ3 ON=発光 OFF=消灯
   単LED4 :スイッチ4 ON=発光 OFF=消灯
   単LED5 :スイッチ5 ON=発光 OFF=消灯
   単LED6 :スイッチ6 ON=発光 OFF=消灯
   単LED7 :スイッチ7 ON=発光 OFF=消灯
   単LED8 :スイッチ8 ON=発光 OFF=消灯

ただし、単LEDの発光は当局入手の基板と同じスイッチ配線に限ります。
多分流通しているどの基板も同じだとは思いますが、証拠はない。
7セグLEDの表示は全てのビットを示します。
これにより、お使いのTM1638LED基板上のスイッチが、
受信した4バイトのどのビットに反映しているかが解ります


最後に・・・
 関数のソースを見て頂けると解ると思いますが、バッファメモリにアクセスしていない制御関数があります。
その関数だけでもTM1638の殆どの制御は可能です。
ここでは分類していませんが、それらの関数のみの使用なら、バッファRAM定義および不要関数を削除し、メモリの少ないPIC16F1823等でもTM1638を使用可能です。
ご要望があればスリム化したバージョンも用意しますが・・・



感想
いや~、
ここ1年半以上ぶりのPICプログラミングでした・・・ (-_-;)
すっかり忘れているので、簡単な事から復習がてらのプログラミングです。
昨年は強電ばかり考えて勉強してました・・・
今年の春から初夏にかけては鉢植え植物の勉強?をしていました・・・
もう一つ手を付け始めたのもあるが今は言えない・・・
時間も先立つ物も無い癖に趣味を広げていました。
でも、植物はお金が無くとも楽しめるのですよね、
ホムセンで枯れかけた売れ残りポットが数十円で買えるし、(^^♪
結局枯れたのも有りましたが、生き残ったのは、現在綺麗に咲いています。
植物の全能性に驚きながら、復活・成長したお花に癒されます・・・
強電関連は工具が高いので、乏しい工具と正規の材料を揃えながら、
自宅内工事をボチボチと楽しめます (^_^;)
PICと電工は、年齢的に後5~6年程度が楽しめる限界かな・・・
残り少なくなってきた健康寿命ですが、精一杯色々と楽しまないとね。

2021年8月20日 JA0QON
現在、追記はありません

追記 年 月 日

戻る  実験・製作の記録TOPへ戻る