| ホーム |     私の電子工作作品集

193. 7セグメントLED表示時計 II ( MAX7219 版)

[ 初公開日:2021年11月8日 ]

 PIC による時計の製作を私が初めて行ったのは、今からもう 15 年ほども以前のことで、私が PIC に対してほんの駆け出しの頃でした。 その頃 "ELECTRONICS SHELVES" というサイトがあって(現在、行方不明中)、 そのサイト内に "PIC,16F84を使った7セグメントLED表示の時計" という製作ページがあり、そのページを参考にして私も製作をしてみたのが始まりでした。

 その私が製作をした時計については、別ページ "014. 7セグメントLED表示時計" で既に紹介済みですが、そのページでも触れているように、 その頃、私自身がアセンブラ命令を覚えるためのトレーニング用題材として選択をし、製作をしてみたのがそのときの一番の目的でした。

 それ以降も PIC といろいろな表示器を組み合わせた時計の製作をしてきましたが、今回は再び7セグメントLEDを表示器とした時計の製作です。 ただし、前作 "014. 7セグメントLED表示時計" では "時分" の4桁表示でしたが、 今回紹介するものは "時分秒" の6桁のLED表示時計としました。 また、回路構成も「リアルタイムクロックモジュール」、「8桁LEDディスプレイドライバ用 IC "MAX7219"」を使用して一新を図ってみました。

上: PIC16F684、下: MAX7219

■ 回路図 ■


 注1.上回路図では、7セグメントLEDの D1 桁と D3 桁間、および D4 桁と D6 桁間の c 〜 g セグメントのコモン線が切れていますが、必ず結線をすること。
 注2.従来の 回路図 では、ICSP 廻りにダイオードを挿入してありましたが、不要なので上回路図のように変更をしました。
    なお、プリント基板(1)パターン図 等には反映をしてありませんので、製作をする場合には注意をしてください。 ( 2024/7/5 更新 )

 冒頭でも述べたように本機の最大の特徴は、「8桁LEDディスプレイドライバ用 IC "MAX7219"」を使用したことで、PIC の使用ポート数を大幅に減少させたことです。 多桁の7セグメントLEDをドライブするためには、 通常ではダイナミック点灯をさせますが、それでもセグメント用として 7 〜 8 本(A 〜 G, DP)+ 桁数(4桁表示では 4 本、6桁表示では 6 本)の多数のポート数を、"MAX7219" を使用しなかった場合には PIC で必要とします。

 それに対して、本機では「8桁LEDディスプレイドライバ用 IC "MAX7219"」を採用したことによって、上回路図を見ても分かるように、PIC との接続にはたった3本だけのポート数ですべてのLEDをドライブすることが可能です。 そのため、本機ではピン数の少ない 14 ピンの PIC16F684 を使用することにしました。

 実はこの IC "MAX7219" は、別ページ "189. ドットマトリクス 8 x 8 LED 表示時計 II ( MAX7219 版)" で使用をした、「ドットマトリクス LED モジュール」内に 組み込まれていた IC と同じもので、今回はドットマトリクス LED ではなく、7セグメントLEDをドライブするために使用をしています。

 なお、"MAX7219" を使用して7セグメントLEDをドライブする場合には、必ずカソードコモン型のLEDでなければならず、アノードコモン型のLEDはドライブすることができません( 念のため)。 ドットマトリクス 8 x 8 LED の場合には、パッケージ内でカソード側もアノード側も 8 個ずつのコモン配線が取られているため、カソード側を "MAX7219" の各デジット(桁)に、アノード側を各セグメントに接続をします。 ( "189. ドットマトリクス 8 x 8 LED 表示時計 II ( MAX7219 版)" の 回路図 を参照。)

 また、「リアルタイムクロックモジュール」についても、既に "189. ドットマトリクス 8 x 8 LED 表示時計 II ( MAX7219 版)"、"190. I2C IF モジュール + LCD(1602A) 表示時計" で使用をしたものとまったく同じもので、RTC IC の "DS3231" を核としています。 詳細は "190. I2C IF モジュール + LCD(1602A) 表示時計" の "リアルタイムクロックモジュール" 、 "リアルタイムクロックモジュールのプログラミング" を参照してください。

 このように、本機では極力ピン数の少ない 14 ピンの PIC を使用することに拘ったため、機能的には "年月日" と "時分秒" 表示だけのシンプルな時計となっています。

| 回路図 (Clock7LEDII3.CE3) | ページトップ |

■ ケース外観と内部の様子 ■

| ページトップ |

■ 機能と使用法 ■

  • 本機の電源を投入すると、"ピポッ" と開始ブザー音を出力後、7セグメントLEDの各桁セグメントLEDの、点灯チェックを兼ねたデモ表示が数十秒間行われ、続いて 1 秒間全桁消灯の後、 0.5秒間ずつ9から0までの数字をカウントダウンしながら、7セグメントLED全6桁分の表示テストを計5秒間行う。 (このとき、MODE / SET スイッチを押しながら電源を投入すると、数十秒間のデモ表示だけを省略することができる。)

  • 次に、1 秒間全桁消灯の後、プログラムのバージョン番号が7セグメントLEDに約5秒間表示される。
    		バージョン番号		[ _x.xx___ ]
    

  • その後 1 秒間全桁消灯の後、RTC(リアルタイムクロック)モジュールの状態がチェックされ、初めて電源を入れたときや、バックアップ用バッテリーが異常なとき等に、次のエラーメッセージが7セグメントLEDに表示されるとともに、 "ブッブー" ブザー音が出力される。
    		エラーメッセージ	[ Er.3231 ]
    

  • ユーザはバックアップ用バッテリーの状態等を確認してその対処を行った後、5つのスイッチの内のどれかを押して応答をする。

  • すると、RTC(リアルタイムクロック)モジュールが初期設定され、エラーフラグがクリアされるとともに、年月日、時分秒が本機をプログラミングしたときの初期値、 "2021/01/01"、 "00:00:00" に設定がされて時計機能が開始される。 この状態を NORMAL モード という。 しかし、これらは現在値とは異なるため、スイッチ操作による手順で現在の年月日、時分秒に設定をし直す必要がある。
    		時間表示		[ xx:xx:xx ]
    
    初期設定がされて時計機能が開始

  • その手順の説明の前に、本機における表示モードを先に説明をしておく。 (このときのモードの意味は上述の NORMAL モードと対比するものではなく、単に表示する内容の種類を表している)。 本機には上述の時間表示の他に、 年月日表示(年表示は西暦4桁の内、下2桁のみ表示)の機能を持っている。
    		モード 0          	  		モード 1
    		時間表示 [ xx:xx:xx ]			年月日表示 [ xx.xx.xx ]
    

  • なお、上述のモード 0 、モード 1 の他にモード 2 もあって、これらは MODE / SET スイッチ を押すごとにモード番号が増加をし、7セグメントLEDに表示される内容が切り替わる。 そして モード 2 の次は再び モード 0 に戻る。
    		┌─→ 時間表示 ─→ 年月日表示 ─→ オートモード ──┐
    		│  (モード 0)   (モード 1)    (モード 2)   │
    		│                          │
    		└──────────────────────────┘
    
    
  • オートモード(モード 2) を選択したときには、モード 0 、モード 1 の個々の内容表示を、次図に示すように自動的に 10 秒ごとに内容を切り替えて、それぞれの表示を繰り返す。
          		毎 00 〜 09, 20 〜 29, 40 〜 49 秒の間:	時間表示
          		毎 10 〜 19, 30 〜 39, 50 〜 59 秒の間:	年月日表示
    
    		 (_____: 時間表示、NNNNN: 年月日表示)
    
    		00        10        20        30        40        50        00
    		.    .    .    .    .    .    .    .    .    .    .    .    .
    		__________NNNNNNNNNN__________NNNNNNNNNN__________NNNNNNNNNN
    
    
  • 本機では12/24時間の両表示機能を持ち、通常の NORMAL モード中であれば UP スイッチ を押すことによって、いつでも切り替えることができる。 すなわち、時間表示(モード 0) 中だけでなく、 年月日表示(モード 1) 、オートモード(モード 2) 中であっても切り替えられる。 ただし、年月日表示(モード 1) 中のときには切り替わったことを目で確認することはできない。

  • 次に、24時間表示と12時間表示の両者の対応を示すが、本機では、24時間表示では "時" の表示に "xx" と常に2桁で表示するのに対して、 12時間表示では先頭が "0" であった場合には、ゼロサプレスをして表示しないようにしている。
    		(24H)  00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
    		(12H)  12  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11
    		       am am am am am am am am am am am am pm pm pm pm pm pm pm pm pm pm pm pm
    
    
  • 12時間表示の場合には午前と午後との区別をさせるため、最左端の十時の桁の "F" セグメントを点灯させることで午前を表し、また "E" セグメントを点灯させることで午後を表している。 次の写真は、12時間表示での午前と午後、および24時間表示でのそれぞれの表示例を示す。

    (12H 表示例) AM 01 : 23 : 45 (12H 表示例) PM 01 : 23 : 45 (24H 表示例) 01 : 23 : 45

  • さて、ここで話を戻して、年月日、時分秒の設定を変更する手順としては、現在、時間表示(モード 0) 〜 オートモード(モード 2) のどの内容が表示されている場合においても可能で、まず、表示内容(モード)を切り替えるときのように "チョン押し" ではなく、同じ MODE / SET スイッチ を "長押し" することによって、年月日、時分秒を自由に変更することができる SET モード に移行をする。

  • すなわち、MODE / SET スイッチ を3秒以上 "長押し" をしていると、マトリクス LED に次のメッセージが表示されて、NORMAL モードから SET モード に移行をしたことを知らせる。 (7セグメントLED全6桁の "G" セグメントだけを点灯させる。)
    		SET モード に移行	[ -- -- -- ]
    

  • ユーザはそれを確認してスイッチから指を離すと、次には必ず年月日の表示パタンが表示される。 そして、"年2桁" のデシマルポイント(DP)がブリンク点灯(200 ミリ秒点、200 ミリ秒滅)をし、 これから変更することが可能な対象項目であることを表している。 (年表示は西暦4桁の内、下2桁のみ表示)
    					  vv		... vv の位置 "年2桁" の DP がブリンク点灯
    		年月日表示		[ xx.xx.xx ]
    

  • ここで変更が必要であれば、UP スイッチ を押すごとに現在値より1ずつ増加し、また DOWN スイッチ を押すごとに1ずつ減少するので、適宜希望する値に変更をする。 また、このときの増減幅を大きくしたい場合には、 UP スイッチ、または DOWN スイッチを押したままにしていると、1秒当たり 4 〜 5 の増減幅で更新をするようになる。

  • "年2桁" の変更が済んだら、再び MODE / SET スイッチ を押すと、次には "月2桁" のデシマルポイント(DP)がブリンク点灯をし、変更の対象項目が次に移動したことを示す。 同様に変更が必要であれば、 UP スイッチ、または DOWN スイッチを押すことによって、適宜希望する値に変更をする。
    					     vv		... vv の位置 "月2桁" の DP がブリンク点灯
    		年月日表示		[ xx.xx.xx ]
    

  • 同様に、SET スイッチ を押すごとに "年"、"月"、"日"、"時"、"分"、"秒" と変更の対象項目(2桁ずつ)が移動するので、該当の項目を選択後 UP または DOWN スイッチ によって値を変更設定する。 このとき、"日" から "時" に対象項目が移動すると、時間表示パタンに切り替わる。 両者での見かけ上の違いは、各項目間の区切り記号表示が前者ではピリオド(.) 、後者ではコロン(:)となる。

  • そして、最後の "秒" 設定後にもう一度 SET スイッチを押すことによって、年月日、時分秒の設定変更の処理が終了をし、SET モードから抜け出して再び NORMAL モード に移行をして、必ず時間表示(モード 0) に戻り、 新たに設定をし直した時分秒から時(とき)を刻み続ける。

  • この SET スイッチによって対象項目を選択中に、誤って希望する項目を通り過ぎてしまったような場合には、BACK スイッチ を押すごとに、ひとつずつ前の項目に戻ることができる。 ZERO / BACK スイッチは、"年"、"月"、"日"、"時"、"分"、"秒" の設定中(SET モード)にはこのような機能を有する。
    		               BACK   BACK   BACK   BACK   BACK
    		               ←─   ←─   ←─   ←─   ←─
    		           SET    SET    SET    SET    SET    SET    SET
    		3つのどれかのモード ─→ 年 ─→ 月 ─→ 日 ─→ 時 ─→ 分 ─→ 秒 ─→ 時間表示モード(モード 0) 
    		             │                   ↑
    		           BACK└───────────────────┘
    
  • なお、NORMAL モードのときに12時間表示に設定がされている場合には、SET モードに移行後もその表示が反映されるため、SET スイッチによって項目の "時"、"分"、"秒" を選択時には、左列の :(コロン)の上側 LED点灯 + 下側 LED消灯で AM を、上側 LED消灯 + 下側 LED点灯で PM を、それぞれ表現をする。 また、この場合には先頭の1桁目(左端)のゼロサプレスも行われる。

  • ZERO/BACK スイッチは、SET モード中で "年"、"月"、"日"、"時"、"分"、"秒" の設定のときには、上述のように BACK スイッチとして機能をするが、それ以外の NORMAL モード中には、毎正時プラス・マイナス5分以内に押された場合に限り、 00 分 00 秒に設定するための ZERO スイッチとして機能 をする。

  • また、このように NORMAL モード中で、毎正時プラス・マイナス5分以内には ZERO スイッチ機能が優先するが、毎正時プラス・マイナス5分以外のときにZERO/BACK スイッチ を押しながら UP スイッチ、 または DOWN スイッチ を押す ことによって、LEDの 輝度調節として機能 をする。

  • 本機では、輝度調節のレベルを 0 から 9 までの 10 段階 * を、変更設定することができる。 すなわち、ZERO/BACK スイッチを押しながら、UP スイッチを押すごとに現在値より1ずつ増加し、 また DOWN スイッチを押すごとに1ずつ減少する。 ただし、このときにそれぞれの限度値になってから尚も、UP スイッチ、または DOWN スイッチを押しても、それぞれの限度値を超えることはない。 (デフォルト値 = 4)

      * 本機で使用したIC MAX7219 では 16 段階で変更することが可能であるが、LEDの安全性を考慮して上限を 9 までに制限をした。

  • このとき設定された輝度調節のレベルの値を、"月2桁"、または "分2桁" の位置に同数字2桁で表示をするとともに、デシマルポイント(DP)をブリンク点灯させて知らせる。 これらの表示は、スイッチ操作によって設定値が変更されるごとに、 1秒間だけ表示される。
    					     vv	            vv	      ... vv の位置 "2桁" の DP がブリンク点灯
    		輝度レベル表示		[ xx.xx.xx ] / [ xx:xx:xx ]
    

  • 年月日カレンダー機能について、うるう年の計算は 2001年〜2399年までの範囲で対応をしている。 ただし、年の表示は下2桁のみになる。

  • SIGNAL スイッチ は、毎時の時報音出力のブザー音を、押すごとに有効/無効に交互に設定をする。 このときの設定状態は視覚的な表示がないため、有効になったときには "ピピピッ" 音を、無効になったときには "ブー" 音を、 それぞれ鳴らして知らせる。 なお、電源を投入した直後は有効状態に設定がされている。 また、有効に設定時には、時間表示(モード 0) 以外のモードにおいても、毎時の時報音は有効(鳴る)なので注意が必要である。

| ページトップ |

■ プログラム ■

 冒頭でも述べたように、7セグメントLEDを表示器とした "014. 7セグメントLED表示時計" を既に紹介済みですが、再び7セグメントLEDを表示器として本機を製作したのには、実は訳があります。

 前回公開をした "189. ドットマトリクス 8 x 8 LED 表示時計 II ( MAX7219 版)" では、「8桁LEDディスプレイドライバ用 IC "MAX7219"」を多数カスケード接続をしたときの プログラミングを行いましたが、今回のように MAX7219 を単体で使用したときのプログラミングもぜひ行ってみたい、とそのときから思っていました。

 そのような訳で、 MAX7219 を使用して再び7セグメントLEDを表示器とした本機の製作を通して、MAX7219 単体でのプログラミングをしてみたのです。 単体でのプログラミングと、多数カスケード接続をしたときのプログラミングとでは、 自ずからその力点が異なってきます。


● MAX7219 単体使用でのプログラミング

 以下の説明では、前回の "189. ドットマトリクス 8 x 8 LED 表示時計 II ( MAX7219 版)" のプログラムの項と、重要な事項については重複する部分も多いのですが、逆に希薄な部分については前回のプログラムの項の MAX7219 制御の基本的な考え方 、または Maxim Integrated 社の MAX7219 データシート(日本語版) を参照してください。

 なお、以下の図1と表1〜 表 6、およびピン配置図は、いずれも Maxim Integrated 社の MAX7219 データシート(日本語版) から抜粋をしたもので、これらの図表を参考にしてプログラミングを行いました。

 まず初めに、次の図1は、DOUT を除いた3本のインタフェース線で PIC と通信を行うときのタイミングを図に表したもので、いずれの信号もすべて PIC から MAX7219 に送られます。 なお、DOUT については、カスケード接続をするときに必要となる信号(MAX7219 から出力される)で、今回の単体での使用では必要がありません。
 PIC からは DIN に次の表1のフォーマットで、常に 16 ビットのシリアルデータとして MAX7219 に送られます。 そして、それらのビットを送る前には、まず LOAD を "Low" にします。 DIN 送られてきた各ビットは CLK の立上りエッジごとに MAX7219 のシフトレジスタにシフトインされ、最後(16 番目 = D0)のビットを送出後に LOAD を "High" にすることで(その立上りエッジで)、桁レジスタまたは制御レジスタのいずれかに取り込まれます。

 なお、桁レジスタまたは制御レジスタの種類は表1の ADDRESS (D11 〜 D8) で指定をし、DATA (D7 〜 D0) にはそれらのレジスタに設定するデータを指定します。 XXXX (D15 〜 D12) はダミービットのため 1 でも 0 でも構いません。
 また MAX7219 の桁レジスタまたは制御レジスタには次の表2に示す種類がありますが、桁レジスタ(Digit 0 〜 Digit 7)は最も頻繁に操作をすることになります。 次に頻度の高い(今回のプログラミングを通して)のが デコードモードレジスタ(Decode Mode)でした。

 No-Op レジスタは主にカスケード接続をしたときに必要となる制御レジスタで、今回の単体での使用では無視をしても構いません。 他の制御レジスタについては、MAX7219 の初期設定時に一度設定をすれば、 後は設定をし直す必要はほとんどないと思います。 なお、輝度レジスタ(Intensity)については、本機で使用の7セグメントLED(C-552SRD)では、デューティサイクルを 9/32(0xX4)と設定して使用をしました。 (これはLEDの光り具合を私が見た感覚で決めました。)
    後日、本機が NORMAL モード中のときには、スイッチ操作によっていつでも設定値の変更ができるように、機能追加 をした。(0xX4 はデフォルト値)
 本機において、年月日や時分秒の表示用の各桁7セグメントLED、区切り記号のコロン(:)やピリオド(.) 表示用の単体LEDと、MAX7219 の桁レジスタ(Digit 0 〜 Digit 7)との実際の対応を、次表に示します。
    < 本機においての各桁LEDの対応表 >
    MAX7219 の桁レジスタ Digit 7 Digit 6 Digit 5 Digit 4 Digit 3 Digit 2 Digit 1 Digit 0
    本機のLED 7セグ "HH" 桁 7セグ "HL" 桁 左側コロン(:) 7セグ "MH" 桁 7セグ "ML" 桁 右側コロン(:) 7セグ "SH" 桁 7セグ "SL" 桁
 上表の中で、7セグメントLEDには主目的である "年"、"月"、"日"、"時"、"分"、"秒" の数字を表示させるために、予め対応する桁に、次の表4に示すデコードモードレジスタ(DECODE MODE)でデコードを有効に設定をしておくと、 桁レジスタには表示をさせたい数値を送るだけで、表5に示すコードBフォントを発生させることができます。
 例えば、予め次のようにデコードモードレジスタに設定(Digit 7,6,4,3,1,0: デコードあり、Digit 5,2: デコードなし)をしておくと、
      			:
      			:
      		movlw	h'09'		;デコードモードレジスタ
      		movwf	reg_addr
      		movlw	b'11011011'	;Digit 5,2: デコードなし
      		movwf	reg_data
      		call	max_reg_cont
      			:
      			:
      
      ;		MAX7219 のレジスタ制御
      
      max_reg_cont
      		bcf	PORTC,maxLOAD	;maxLOAD="L"
      		movf	reg_addr,W	;レジスタアドレス
      		call	max_byte_send
      		movf	reg_data,W	;レジスタデータ
      		call	max_byte_send
      		bsf	PORTC,maxLOAD	;maxLOAD="H"
      		return
      
      ;		データ 1 バイト送信 
      
      max_byte_send
      		movwf	maxtmp		;Wレジスタの内容を一時保存
      		movlw	8
      		movwf	mbit_cnt	;ループカウンタにセット
      
      mbsend01	bcf	PORTC,maxDIN	;maxDIN="L"
      		btfsc	maxtmp,7	;送り出しデータの 7ビット目 = 1 か?
      		bsf	PORTC,maxDIN	;Yes, maxDIN="H"
      		bsf	PORTC,maxCLK	;maxCLK="H"
      		nop
      		bcf	PORTC,maxCLK	;maxCLK="L"
      
      		rlf	maxtmp,F	;送り出しデータを 1ビット左にシフト
      		decfsz	mbit_cnt,F	;8ビット送信した か?
      		goto	mbsend01	;No
      
      		return		
      
 次に、"SL" 桁の7セグメントLED(Digit 0 レジスタに対応)に、数字 "8" の文字を表示したいような場合には、次のように
      			:
      			:
      		movlw	h'01'		;Digit 0 レジスタ
      		movwf	reg_addr
      		movlw	h'08'		;
      		movwf	reg_data
      		call	max_reg_cont
      			:
      			:
      
とすることで、次図の MAX7219 の各セグメント SEG A 〜 SEG G 端子には、"8" の文字を形成するために上表5のように、すべて 1(High)が出力されます。
    ピン配置図
 このときデコードの出力対象となるのは、表5のようにセグメント SEG A 〜 SEG G のみで、デシマルポイント(DP)の SEG DP は含まれません。 もしも、同時にデシマルポイント(DP)も点灯をさせたいときには、
      			:
      			:
      		movlw	h'01'		;Digit 0 レジスタ
      		movwf	reg_addr
      		movlw	h'08' + h'80'	;
      		movwf	reg_data
      		call	max_reg_cont
      			:
      			:
      
のように、桁レジスタに送るデータの bit7 = 1 とする(+ h'80')ことによって、SEG DP 端子から 1(High)が出力されます。 このように、上記の 本機においての各桁LEDの対応表 に示した6個の7セグメントLEDは、同様にして SEG A 〜 SEG G 制御、および SEG DP 制御をすることができます。

 また、各桁LEDの対応表に示した Digit 2 と Digit 5 については、7セグメントLEDではなく2個ずつの単体のLEDでコロン(:)を構成し対応をさせています。 そして、本機では 回路図 に示すように、 それぞれのLEDは SEG A と SEG B に結線をしています。 上に示したリストでデコードモードレジスタの設定部分だけを再掲すると、
      			:
      			:
      		movlw	h'09'		;デコードモードレジスタ
      		movwf	reg_addr
      		movlw	b'11011011'	;Digit 5,2: デコードなし
      		movwf	reg_data
      		call	max_reg_cont
      			:
      			:
      
のように Digit 2, 5 については、7セグメントLEDではないためデコードなしで設定をしています。 Digit 2, 5 はもちろんですが、他の Digit 0, 1, 3, 4, 6, 7 に対応させた7セグメントLEDの場合にも、 もしもデコードなしで設定をした場合には、次の表6に示すように SEG A 〜 SEG G、および SEG DP を、桁レジスタに送るデータの各ビットに対応させているので、点灯させたいセグメント SEG x に対応した bit x = 1 として桁レジスタに送れば、ダイレクトに SEG A 〜 SEG G、および SEG DP を制御することができます。
 例えば、もしも Digit 0 をデコードなしで設定をした場合には、
      			:
      			:
      		movlw	h'01'		;Digit 0 レジスタ
      		movwf	reg_addr
      		movlw	b'01111111'	;h'7f'
      		movwf	reg_data
      		call	max_reg_cont
      			:
      			:
      
のように桁レジスタ Digit 0 に、ダイレクトなデータ bit 6 〜 0 = 1(h'7f')を送ることによって、 SEG A 〜 SEG G 端子から 1(High)が出力されます。(これは、先のデコードありで設定をした場合に、 データ h'08' を送ったときと同等の結果になる。)

 次のリストの例では、桁レジスタ Digit 2 にデータ h'60' を送っています。
      			:
      			:
      		movlw	h'03'		;Digit 2 レジスタ
      		movwf	reg_addr
      		movlw	b'01100000'	;h'60'
      		movwf	reg_data
      		call	max_reg_cont
      			:
      			:
      
 この場合には、右側コロン(:)の制御のときに、SEG A と SEG B 端子から 1(High)を出力しています。 (すなわち、記号のコロン(:)を形成させている。 回路図 を参照)

 以上のように、MAX7219 を使用して7セグメントLEDや単体LEDの制御方法を述べてきましたが、これらの基となる、私がプログラミングをした MAX7219 単体使用での基本制御ルーチンを、次にまとめておきます。 なお、輝度レジスタ関連の変更が反映されていなかったので、正しいリストに差し替えを行いました。 ( 2021/11/9 更新 )
      ;==========================================================================
      ;		定数の定義と変数のレジスタ割付け
      ;==========================================================================
      
      			:
      maxDIN		equ	2		;MAX7219 DIN 制御	;┐
      maxLOAD		equ	3		;MAX7219 LOAD 制御	;│PORTC
      maxCLK		equ	4		;MAX7219 CLK 制御	;┘
      			:
      
      		cblock  h'20'		;
      			:
      reg_addr				;MAX7219 のレジスタアドレス
      reg_data				;レジスタへの書き込みデータ
      maxtmp					;送信データの一時保存
      mbit_cnt				;ループカウンタ
      mlpcnt1					;ループカウンタ
      mlpcnt2					;ループカウンタ
      mlpcnt3					;ループカウンタ
      segment					;Segment データ変数
      digit					;Digit データ変数
      intensity				;bit7: 輝度更新フラグ, bit3-0: 輝度調節値
      			:
      			:
      
      ;==========================================================================
      ;		マクロ命令定義
      ;==========================================================================
      
      ;		maxRegSet マクロ
      
      maxRegSet	macro	@reg,@dat
      		movlw	@reg		;レジスタアドレス
      		movwf	reg_addr
      		movlw	@dat		;データ
      		movwf	reg_data
      		call	max_reg_cont	;MAX7219 のレジスタ制御
      		endm
      
      ;==========================================================================
      ;		MAX7219 レジスタの基本制御
      ;==========================================================================
      
      		; MAX7219 LED ドライバの初期化
      
      max_reg_init
      		movlw	h'0f'		;ディスプレイテストレジスタ
      		movwf	reg_addr
      		movlw	h'00'		;通常動作
      		movwf	reg_data
      		call	max_reg_cont
      
      		movlw	h'09'		;デコードモードレジスタ
      		movwf	reg_addr
      		movlw	h'00'		;デコードなし
      		movwf	reg_data
      		call	max_reg_cont
      
      		movlw	h'0a'		;輝度レジスタ
      		movwf	reg_addr
      		movlw	h'04'		;9/32
      		movwf	reg_data
      		movwf	intensity	;輝度調節値: デフォルト設定		; (Ver.1.01) で追加
      		call	max_reg_cont
      
      		movlw	h'0b'		;スキャン制限レジスタ
      		movwf	reg_addr
      		movlw	h'07'		;スキャン対象 8桁
      		movwf	reg_data
      		call	max_reg_cont
      
      		movlw	h'0c'		;シャットダウンレジスタ
      		movwf	reg_addr
      		movlw	h'01'		;通常動作
      		movwf	reg_data
      		call	max_reg_cont
      
      		call	digit_reg_clr	;全 Digit レジスタのクリア
      		return		
      
      ;--------------------------------------------------------------------------
      
      ;		MAX7219 のレジスタ制御
      
      max_reg_cont
      		bcf	PORTC,maxLOAD	;maxLOAD="L"
      		movf	reg_addr,W	;レジスタアドレス
      		call	max_byte_send
      		movf	reg_data,W	;レジスタデータ
      		call	max_byte_send
      		bsf	PORTC,maxLOAD	;maxLOAD="H"
      		return		
      
      ;		MAX7219 指定レジスタのクリア
      
      max_reg_clr
      		bcf	PORTC,maxLOAD	;maxLOAD="L"
      		movf	reg_addr,W	;レジスタアドレス
      		call	max_byte_send
      ;		movf	reg_data,W	;レジスタデータ
      		clrw			;クリア
      		call	max_byte_send
      		bsf	PORTC,maxLOAD	;maxLOAD="H"
      		return		
      
      ;--------------------------------------------------------------------------
      
      ;		データ 1 バイト送信 
      
      max_byte_send
      		movwf	maxtmp		;Wレジスタの内容を一時保存
      		movlw	8
      		movwf	mbit_cnt	;ループカウンタにセット
      
      mbsend01	bcf	PORTC,maxDIN	;maxDIN="L"
      		btfsc	maxtmp,7	;送り出しデータの 7ビット目 = 1 か?
      		bsf	PORTC,maxDIN	;Yes, maxDIN="H"
      		bsf	PORTC,maxCLK	;maxCLK="H"
      		nop
      		bcf	PORTC,maxCLK	;maxCLK="L"
      
      		rlf	maxtmp,F	;送り出しデータを 1ビット左にシフト
      		decfsz	mbit_cnt,F	;8ビット送信した か?
      		goto	mbsend01	;No
      
      		return		
      
      ;--------------------------------------------------------------------------
      
      ;		全 Digit レジスタのクリア
      
      digit_reg_clr
      		movlw	h'08'		;Digit レジスタ数
      		movwf	reg_addr	;ループカウンタ にセット
      
      dclr01		call	max_reg_clr	;指定レジスタのクリア
      		decfsz	reg_addr,F	;ループカウンタ - 1 = 0 か?
      		goto	dclr01		;No
      
      		return
      
      ;--------------------------------------------------------------------------
      
      ;		LED を 1 秒間消灯
      
      led_1s_off
      		movlw	h'0c'		;シャットダウンレジスタ
      		movwf	reg_addr
      		clrf	reg_data	;シャットダウン(LED 消灯)
      		call	max_reg_cont
      
      		call	wait_1sec	;1 秒 ウェイト
      
      		movlw	h'0c'		;シャットダウンレジスタ
      		movwf	reg_addr
      		movlw	h'01'		;通常動作
      		movwf	reg_data
      		call	max_reg_cont
      		return		
      
 なお、上リスト中に定義がしてある maxRegSet マクロ命令については、プログラミングの終盤になってから作成したのと、作りにあまり汎用性がなかったこともあり、本機のプログラム内では一部の使用に止まっています。

 また、MAX7219 を使用した7セグメントLEDの各セグメントを制御する応用例が、ソースファイル (Clock7LEDII.asm) リスト中の最後部にある、7セグメントLED の点灯移行デモ-1(demo1_display)〜 点灯移行デモ-3(demo3_display) サブルーチンとして収録がしてあるので、興味がある方はリストをご覧になってみてください。

● リアルタイムクロックモジュールのプログラミング

 リアルタイムクロックモジュールには、別ページ "190. I2C IF モジュール + LCD(1602A) 表示時計" と同様に "DS3231" を採用しました。 したがって、プログラミングについては、そのページの "リアルタイムクロックモジュールのプログラミング" の項で詳細に述べているので、そちらを参照してください。

現在の最新バージョン: Ver. 1.01

| ページトップ |

■ プリント基板の部品配置 ■

 本機で使用したプリント基板(1) は、"秋月電子" の "片面ガラス・ユニバーサル基板 Bタイプ(95×72mm) めっき仕上げ(通販コード P-00518)" ですが、この基板を ケース加工図 で示したケース内に収納するためには、下図の上下サイズがほんのちょっぴりですが大きいために、少しばかり無理が生じます。 したがって、パーツ類を取り付ける前に 0. 数ミリ程度ですが、現物合わせで上下辺をやすり等で削っておくと良いでしょう。

 また、使用した7セグメントLEDは1つのパッケージ内に7セグが2連となったものですが、これを単連のLED2個とは物理的に異なるために、この基板を使用した場合には単純に置き換えることはできません。 それは2連のものでは上下の足ピンが 9 本ずつですが、単連のものでは上下の足ピンが 5 本ずつのため、下右図<参考>のようにLED2個では 10 本ずつになってしまいます。
<参考>

 なお、プリント基板(2)(タクトスイッチ用)のプリント基板の加工については、別ページ "190. I2C IF モジュール + LCD(1602A) 表示時計" の プリント基板の加工と部品配置 で述べたこととまったく同様なので、そちらを参照してください。

| プリント基板パターン図 (部品面) (Clock7LEDII_PC0.CE3) | ページトップ |

■ プリント基板(1)パターン図 (部品面) ■

 基板には5個のタクトスイッチが取り付けてありますが、これらは必ずしも必要ではありません。 基板上にスペース的な余裕があったために取り付けたもので、本基板をケース内に収納したときには、 これらのスイッチを操作することはできません。 私はケース外でのプログラムのデバッグ中だけに使用をしました。

 下の写真には写っていませんが、左右の2組のコロン(:)用の LED(計4個)には、光拡散キャップ Φ3 白(OS-CAP-3MK-1)を被せて使用しています。

 別ページ "189. ドットマトリクス 8 x 8 LED 表示時計 II" でも述べましたが、「リアルタイムクロックモジュール」には、コネクタとして初めからL型のピンヘッダが取り付けられていますが、 そのままのL型で使用をすると取り付けたときに、プリント基板に対して垂直となって邪魔な位置になるため、ストレート型のピンヘッダに取り替えて、プリント基板の平面と平行になるようにしました。

 また、「リアルタイムクロックモジュール」の、RTC IC の DS3231 が搭載されている面側には LED も付けられていて、この LED が異常なくらいに眩しく光るので、この面が正面を向かないように(裏側を向くように)、 電池ホルダーが取り付けられている面が正面を向くように、ストレート型ピンヘッダを取り付けました。

(なお、本機ではこのピンヘッダとプリント基板(1) に特殊加工が必要になりました。 詳細は後述の ケースへのプリント基板の取り付け の項を参照してください。)

| プリント基板パターン図 (部品面) (Clock7LEDII_PC.CE3) | ページトップ |


 改めて述べる項目欄がないので、ここで「リアルタイムクロックモジュール」のバックアップ用の電池について、少々触れておきます。

 使用したモジュールは、充電池(二次電池) LIR2032 を使用することを想定したものなので、そのままでは一般的な一次電池の CR2032 を使用することはできません。 したがって CR2032 を使用する場合には、 モジュールの少しばかりの改造が必要になります。 その方法を別ページ "190. I2C IF モジュール + LCD(1602A) 表示時計" の リアルタイムクロックモジュール で説明をしているので、そちらを参照してください。

■ プリント基板(1)パターン図 (ハンダ面) ■

| プリント基板パターン図 (ハンダ面) (Clock7LEDII_PC1.CE3) | ページトップ |

■ プリント基板(2)パターン図 (部品面) ■

 本機では、タクトスイッチをプリント基板(2) に取り付けるときには、スイッチの底面を基板にぴったり押し付けて取り付けることが必要です。 (詳細は、後述の ケースへのプリント基板の取り付け の項を参照してください。)

コネクタ, ケーブルを 取り付け前の様子 , 取り付け後の様子

| プリント基板(2)パターン図 (部品面) (Clock7LEDII_2PC.CE3) | ページトップ |

■ プリント基板(2)パターン図 (ハンダ面) ■

コネクタ, ケーブルを 取り付け前の様子 , 取り付け後の様子

| プリント基板(2)パターン図 (ハンダ面) (Clock7LEDII_2PC1.CE3) | ページトップ |

■ ケースへのプリント基板の取り付け ■

 上図の プリント基板(1)パターン図 、および プリント基板(2)パターン図 で作製をしたプリント基板を、下図の ケース加工図 で使用したケース内に収納するのには、かなり無理がありました。 そのために下加工図に示した各サイズは、ギリギリのところで許容したものとなっています。

 プリント基板(1) で使用したサイズの基板を、このケースに収納する場合には今後も要注意です。 もしも、ケースの縦、横、高さのサイズが現物より数ミリずつ大きければ、すべての無理が解消する?のですが ・・・ 残念です。

 まず初めの問題点は、プリント基板(1) をこのケースに取り付けるのには、M3のビス、ナット、ワッシャ、スペーサー等が使用できない ―― と、今までずっと思っていたことです。 スペーサーの外径サイズが Φ6 のためと、ケースがテーパー状(入口より底部分の方が狭い)になっているためで、スペーサーがケースの底部分の内側面と干渉して、実際に取り付けは無理でした。 そのために、1サイズ下のM2.6 のビス類を使用することとして、M2.6 用のスペーサーは入手が困難なために自作( )をしてきました。

 ところが、干渉するのは中空(○型)のスペーサーを使用したためで、最近入手をした外径が 5.5 mm の六角スペーサーでは、ギリギリ(ピッタリ?)で使用が可能なことを発見しました。 これですごく手間がかかる、スペーサーの自作作業からは解放されることになりました。
    (例) 左側4個: 中空スペーサー、 右側4個: 六角スペーサー
 あとはスペーサーの長さが問題になりますが、今回は手持ちの関係もあって、13 mm 長の M3 オネジ+メネジ六角ジュラコンスペーサー(廣杉計器 BS-313W)を使用することにしました。

 このスペーサーによってプリント基板(1) の下面とケース底上面の間にできる、空間のケース左側面には電源供給用の 2.1Φ DC ジャックを、右側面にはプリント基板(2) を取り付けなければなりません。 また、プリント基板(1) の上面とケース上蓋の下面との間の空間には、基板上面に取り付けられた部品すべてが収まらなくてはなりません。

 しかし、「リアルタイムクロックモジュール」をプリント基板に取り付けるために、通常のピンヘッダ(オス)(実装高さ:8.6mm)と、通常のピンソケット(メス)(実装高さ:8.5 mm)を使用したのですが、 プリント基板(1)パターン図 (部品面) で述べた理由で、コイン型の電池ホルダー側を上向きにしたために、プリント基板(1) の上面の背が高くなってしまい、結果、 ケース上蓋を被せたときに、ケース上蓋の下面と電池ホルダーが強く接触をして、ケース上蓋を被せることができなくなってしまいました。

 これは上述のように、13 mm 長のスペーサーを使用したときの話で、この長さをもっと短くすれば接触は回避できるようになりますが、反対に、基板下に DC ジャック等を取り付けることが できなくなってしまいます。 13 mm 長というのは基板下のことを考慮すると、ギリギリの選択肢なのです。

 他の方法として、モジュール基板で背が高いのは電池ホルダー側なので、反対のIC側をもう一度上向きに戻すということも考えられますが、そうした場合には LED が眩しいという問題が再燃するとともに、 今度はモジュール下の空間にある電解コンデンサと、電池ホルダーが接触をしてしまう、という新たな問題が発生をしてしまいます。

 そこで仕方なく、モジュール側に取り付けたピンヘッダ(オス)の黒色樹脂部分(高さ:2.5 mm)を取り除き、かつ、ピン長の 6.1 mm を残し、増分の 2.5 mm をニッパーでカットして使用する、 という大胆(やけくそ?)ともいえる方法を取りました。 カットした断面は鋭くなるのでやすりをかけておきました。
    "秋月電子" ホームページの添付データシートから抜粋 加工後のピンヘッダ
 次の問題点は、プリント基板(2)(タクトスイッチ用)のケース右側面への取り付けについてですが、使用したケースの横幅サイズが小さいために、そのほとんどの空間をプリント基板(1) が占めてしまって、 プリント基板(2) に残された余地はほんの僅かです。

 タクトスイッチをプリント基板に取り付ける場合に、私は個人的に、スイッチの底面を基板から少し浮かせて取り付けることが多い(利点:浮かせたスイッチ下の空間に配線を通すことができるなど。 その )のですが、本機では空間をなくしてスイッチの底面を、基板にぴったりと押し付けて取り付けることが必要です。

 それはスイッチの取り付け高さを少しでも小さくするために、下図の赤矢印で示す 4 mm だけにしたいためです。 そして、この高さを保つためにプリント基板(2) のケースへの取り付けには、 同サイズ 4 mm のスペーサーが必須です。 このスペーサーは○型でも六角でも構いません。 (下図も "秋月電子" ホームページの添付データシートから抜粋)  また、下のケース加工図の(下箱右側面図)で、プリント基板(2) の取り付け位置が外形底面から 12 mm に指定をしてありますが、本来ならもっと左右位置の中央(左)寄りにしたいのですが、 前述のプリント基板(1) 下の 13 mm 長のスペーサーとの兼ね合いもあって、12 mm 以上の中央寄りにすることができないギリギリの許容値なのです。

 プリント基板(1) の左右の取り付け位置についても同図の(下箱上面図)において、6個の7セグメントLEDの左右位置をバランスよくさせるために、もっと右寄りにしたかったのですが、 プリント基板(2) と干渉するのでこれ以上右寄りにすることができません。 同図のように、スペーサーの取り付け位置は左右で 1 mm の差が限界でした。

 このように様々な考慮をしたのにもかかわらず、プリント基板(2) のハンダ面の部分的な盛り上がりのため(タクトスイッチの足ピンをハンダ付け)に、実際には、そのハンダの盛り上がりとプリント基板(1) の右端とが干渉し合って、そのままではプリント基板(1) を取り付けることができなくなってしまいました。  仕方がないので最終的には上の写真のように、プリント基板(1) の右端で干渉し合う部分をやすりで窪みを付け、どうにか取り付けることができるようになりましたが、その結果としてプリント基板(1) は惨めな姿になってしまいました。 無理に小さなケースに押し込むことよりも、もっと余裕のあるサイズのケースを探した方が良いのかもしれません。 (しかし、条件に合ったケースを探し出すというのも、実に大変な作業になる、とは思いますが ・・・)

| ページトップ |

■ ケース加工図 ■

 使用したケースは、100均(セリア)で購入した "クリアケース ミニ (L-8033) サナダ精工" という、ポリスチレンケースです。

 下の加工図中の下箱右側面図では、縦に並んだ7個の各穴の間隔が便宜上、小数点以下2桁のミリ指定がしてありますが、実際にこの値をケースに写し取る方法を、別ページ 174. グラフィック液晶表示 万年カレンダーケース加工においてのヒント で紹介しているので、そちらを参照してください。


| ケース加工図 (Clock7LEDII_CS.CE3) | ページトップ |

■ 使用部品表 ■

(主要部品: IC, トランジスタ等)

(データシート)
PICマイコン .................... PIC16F684
8桁LEDディスプレイドライバ .................... MAX7219
7セグメントLED .................... C-552SRD
RTCモジュール .................... ( DS3231 )

 本機で使用をした "MAX7219" は、IC 単体で購入したものでなく、以前に「 8 x 8 LED ドットマトリクス・ディスプレイモジュール」として、アマゾンで安価に購入をした DIP パッケージのもので、IC "MAX7219" だけを本機に流用しました。 "秋月電子" などでも IC 単体で入手は可能ですが、少々、高価のようです。

| 部品表 | Excel ファイル (Clock7LEDII_parts.xls) | ページトップ |

■ 参考資料・サイト ■

MAX7219 データシート(日本語版) .......... https://akizukidenshi.com/download/ds/maxim/max7219_max7221_j.pdf
DS3231 データシート .......... https://datasheets.maximintegrated.com/en/ds/DS3231.pdf

| ページトップ | ホーム |


Copyright (C) 2021-2024 やまもとみのる
初版:2021年11月8日、初公開:2021年11月8日、最終更新:2024年7月5日