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

201. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー II

[ 初公開日:2025年2月16日 ]

 私のオリジナル作品として、ホームページ上に "174. グラフィック液晶表示 万年カレンダー" を公開してから、早いもので丁度 10 年程が経ちました。 おかげさまで評判もまずまずで、現在までに、多くの方々にそのクローンを作製して頂いています。

 今回の作品は、一見、前作とほぼ同等機能のようにも見えますが、詳細なところでは随所で機能アップを施しており、また、回路構成もまったく一新させています。 前作では PIC とグラフィック液晶(SG12864A)とのインタフェース線が、何と 14 本も必要でしたが、今回作では I2C インタフェースを使用するため、有機 EL (OLED) モジュールとのインタフェースは、たったの2本だけで済んでしまいます。

 そのため使用した PIC も、前作では 28 ピンの PIC16F886 でしたが、今回作では半分の 14 ピンの PIC16F1705 としました。 14 ピン PIC には PIC16F ファミリにもありますが、今回 PIC16F1 ファミリを採用したのは、 本機のようなカレンダーのプログラム規模(大きさ)になると、どうしてもサブルーチン等のネストが深くなってしまい、 PIC16F ファミリではスタックメモリをオーバーフローさせる(私の場合)ことが、しばしば起こります。

 スタックメモリのサイズは、PIC16F ファミリでは 8 レベル分しか存在しませんが、PIC16F1 ファミリでは2倍の 16 レベル分が存在するために、その分余裕があって私には安心してプログラム作成に取り組むことができます。

 また、プログラムメモリについても PIC16F1705 では PIC16F886 と同じ 8K ワードが存在しているので、その点でも十分な余裕があります。 もちろん、スタックメモリやプログラムメモリのサイズの問題だけではなく、両者ではアーキテクチャが異なっていて、 PIC16F1 ファミリでは便利な命令が多く追加されています。


 また、万年カレンダーとしての基本的なクロック源には、前作では超高精度クリスタルモジュール( KTXO-18S )を使用していましたが、今回作では最近の私のホームページ上ではお馴染みの、リアルタイムクロックモジュール( DS3231 For PI )(改造が必要)を使用し、 バックアップ用の電池も搭載して、停電中も時刻の継続を確保しています。

 他に、前作では据え置き型専用としての使用を想定して製作をしましたが、今回作の本機では携帯性も持たせるために、バッテリー(18650 リチウムイオン電池)駆動としています。 そして、そのためのリチウムイオン電池の充電機能も持たせるように考慮がしてあります。

■ 回路図 ■

*注.  入力ポート RA0, RA1, RA4, RA5, RC5 は、内部プルアップ機能を ON にして使用。 また、SLEEP 中には それらのポート に状態変化割り込み機能を使用。

 上回路図内には、有機 EL ディスプレイ(OLED)( SSD1306 )モジュールの電源 VCC に、トランジスタ 2SA1015Y が挿入されていますが、実はこのトランジスタは不要でした。 そのことが分かったのは、回路図通りのハードウエアが完成した後の、 プログラム作成に着手してからのことだったので、結果、そのままにしてあります。

 当初の考えでは、もちろん、PIC から SSD1306 の VCC をコントロールするためで、本機がスリープモードに入ったときに、省エネのために SSD1306 の VCC も OFF にして、ディスプレイ表示をさせないようにするのが目的でした。

 しかし、プログラム作成を進めて行く内の SSD1306 のデータシートを調べている過程で、PIC からコマンドを送ることによって SSD1306 をスリープさせることも可能で、結果、その消費電流を抑えることができる ― ということが分かりました。

 したがって、もしも本機のクローンを作製される方は上述のように、トランジスタ 2SA1015Y は不要なため挿入を省略することができます。 PIC のポート RC2 の先に接続されている抵抗 3.3 KΩと 2SA1015Y を取り外し、 SSD1306 の VCC を本機の VCC と直結してください。

 本機のプログラムでは、電源の POWER スイッチを ON に操作した直後に、PIC のポート RC2 を Low にして 2SA1015Y が ON するようにしていますが、ポート RC2 の先に何も接続されていなくても何ら問題はありません。 プログラムでは、その後のポート RC2 に対する操作は一切ありません。

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

■ 本機で使用した各モジュール ■

 上回路図を見ていただくと分かるように、本機では3つのモジュール(黄色に塗りつぶしたもの)を使用しています。 そして、それらは私にとっては初めて使用するモジュールも含まれているため、私が感じた問題点やその他のことなどを交えて、次に順に挙げていきます。
● 有機 EL ディスプレイ(OLED)( SSD1306 )モジュール

 前回製作した "174. グラフィック液晶表示 万年カレンダー" では、作品名のように、横 128 x 縦 64 ドットのグラフィック液晶(SG12864A)を使用しましたが、本機では、有機 EL (OLED) を用いた I2C 制御の 128 x 64 グラフィックディスプレイモジュールを使用しました。 後者のモジュールには SSD1306 という制御チップが使われていて、前者とは制御方法がまったく異なっています。

 このモジュールについては、私がアマゾンの中華モールなるものの存在を知ってから初期の 2020 年 8 月ごろに、複数種類の異なった OLED モジュールとともに購入したものの中の一つで、現在まで4年以上眠らせたままになっていましたが、 ようやく本機で日の目を見ることになりました。

 カタログ写真を見ていると、発光色としては、白色、青色、上2列黄色で下6列青色、の3種類のモジュールが存在するようですが、私は白色のモジュールを選択購入しました。


 外観は上写真のようなものですが、実際のサイズはかなり小さなもので 0.96 インチと商品説明には書かれており、写真左側の中央に位置する横長の長方形スクリーン部分のサイズは、実測で約 24.5 x 13.5 mm 程のものです。 実際に表示をさせてみても小さ過ぎる感が強く、実用的にはもっと大きな表示器を選択した方が良いと思います(しかし、価格もそれなりに高価になりますが ・・・)。 今回はこの OLED( SSD1306 )モジュールを使用することも、私にとっては目的の一つなのでこのまま製作を進めます。

 価格的には、安価に販売をしているアマゾン内のショップ等では、私が購入をした当時とあまり変わっていないようで、現在でも 500 円少々程度で購入が可能なようです。 ちなみに、"秋月電子" でも大きな差はなく 580 円(2024 年 11 月現在)となっています。 本機のようなお遊びとしての製作物では、お手頃価格?かと思います。

 また、このモジュールについても、Arduino や Raspberry Pi 用には各種のライブラリが存在しているようですが、本機のように PIC(特にアセンブラ言語)を使用した場合には、既成のライブラリの存在はまったく期待することはできません。 したがって、プログラム面においてはすべてを自分自身で作成することになります。

● リアルタイムクロックモジュール( DS3231 For PI )

 本機 "有機 EL ディスプレイ(OLED) 表示 万年カレンダー II" のクロック源には、既に公開済みの "199. 多機能携帯デジタル時計" や、"200. 6桁ニキシー管時計 III(IN-17)" で使用した RTC モジュールと同じ "DS3231 For PI" を使用しました。

 "DS3231 For PI" についての詳細は、前者 "199. 多機能携帯デジタル時計" の リアルタイムクロックモジュール( DS3231 For PI ) で述べているので、そちらを参照して頂くとして本ページでは、 外観写真と回路図だけを次に再掲しておきます。


 また、今回、本機で使用した RTC モジュール個体では、簡単には交換ができないバックアップ用のコイン電池の電圧が、約 2.7 V 程度しかありませんでした。 そのためにも、いつでもコイン電池の交換ができるように変更することと、 上右図の赤線で示した SQW 信号の外部取り出しのための改造が必要になります。 その具体的な改造方法を、既に、後者 "200. 6桁ニキシー管時計 III(IN-17)" の、リアルタイムクロックモジュール( DS3231 For PI ) で詳述しているので、そちらを参照してください。

(注意-1)
 改造を行う場合には十分に注意をして行ってください。 今回の改造では恥ずかしながら、私は大失敗をしてしまいました。 改造中にはまったく気が付かなかったのですが、改造が終了した時点で改めてモジュール基板の上面を眺めてみると、 抵抗が1つ剥がれて無くなっていました。

 正常な状態では左上の写真のように、IC の左横に奥側から手前に向かって、2個のチップ抵抗と1個のチップコンデンサが並んでいるのですが、一番奥側の 4.3 KΩチップ抵抗、すなわち、SCL 用のプルアップ抵抗が無くなってしまいました。 改造作業中のいつの時点で剥がれてしまったのかは分からないのですが、恐らく 5P のピンソケットをモジュール基板から外している途中で、熱の加わったチップ抵抗もハンダが融けて剥がれてしまったのではないか、と想像をしています。

 しかも、かなり小さなチップ抵抗なので、どこへ紛失をしてしまったのかテーブル上を眺めてみても、そこら辺りには見当たりません。 日頃私は、ほとんどチップ部品を使用するようなことはないので、したがって、4.3 KΩチップ抵抗の持ち合わせもありません。 仕方がないので、値の近い 4.7 KΩ 1/6 W カーボン抵抗を、メイン基板側の裏側でモジュール基板の近くに、訳あり ― ということが分かるように、わざと目立つように取り付けておくことにしました。

(注意-2)
 そしてもう一つ、大々失敗をしてしまったことをついで(?)に白状しておきます。 当初、プリント基板(1) の左上に位置する DS3231 For PI の配線を、 パターン図(誤り) のように作製をしてしまい、何の疑いもなくデバッグ中には通電をしてしまいました。

 当然ですが、DS3231 For PI は動作をするわけもなく、クロックパルスが出力されることもなくダンマリ状態です。 POWER スイッチを何度も入れたり切ったりを繰り返しながら、その誤配線に気が付くまでの間、 電源の+−を逆接続の状態で少なくとも延べ数分間、という長時間を通電していたことになります。

 漸く誤配線だったことに気が付いて、思わず青ざめました。 DS3231 For PI が壊れてしまったことを半分覚悟しながら、仕方なく重い腰を上げて、プリント基板(1)( DS3231 For PI )の誤配線を正規に直した後、再度、POWER スイッチを入れてみました。 その結果、クロックパルスが出力されたことには、感動を覚えずにはいられませんでした。

 電源の+−逆接続 ― という IC にとっては最も過酷と思われる状態は、一体どれほどのダメージを与えるものなのでしょうか。 おかげさまで、その後、現在に至っても DS3231 For PI は、問題なくクロックパルスを出力し続けています。 今回は、私のうっかりミスで、誤配線による電源の+−逆接続を起こしてしまいました。 大いに反省です。

● TP4056 リチウムイオン電池充電モジュール

 本機を使用するための電源として、商用AC電源からスイッチングACアダプタ等を介した方法を採るか、それ以外の電池等の電源とするかを決めるにあたって、本機を据え置き型として使用する場合には当然前者の方が良いのですが、 本機では携帯性を持たすために後者としました。 そして本機では、18650 リチウムイオン電池を採用することにしました。

 18650 リチウムイオン電池を使用する場合に、私は生セルタイプを使用することが多くなるため、電池を充電することはもちろんのこと、使用時に過放電(2.4V)、過電流から保護するように、安全面からも "TP4056 リチウムイオン電池充電モジュール" なるものが必須となります。

 "TP4056 リチウムイオン電池充電モジュール" として、私は以前には、Micro USB タイプ のモジュールを使用していましたが、最近になって、タイプ C の USB コネクタを使用したモジュールを入手する機会を得たので、 本機では後者のモジュールを使用しました。 前者で使用している USB コネクタは使用時の外力には弱く、容易にモジュール基板から剥がれてしまうことも予測されますが、後者のモジュールでは、USB コネクタがスルーホールでがっちりと取り付けられているため、 使用時に破損させてしまう心配がありません。

Micro USB タイプ充電モジュール タイプ C 充電モジュール

 タイプ C の USB コネクタを使用したモジュールは、アマゾン等を覗いてみると、Micro USB タイプのモジュールに比べて、かなり高価で販売されているショップを多く見かけますが、私は Temu で安価なショップを見つけたので購入をしてみました。 ちなみに、2024 年 6 月現在において 15 個セットで 445 円でした。 1個当たり 30 円弱ですが、アマゾン等で販売している他のショップでは、これほどの安価な充電モジュールを見かけたことはありません。 願わくは、不良品が混在していないように!と祈るばかりです。

 なお、"TP4056 リチウムイオン電池充電モジュール" の機能等については、"197. 18650 リチウムイオン電池充電器" の TP4056 リチウムイオン電池充電モジュール で詳述しているので、そちらを参照してください。 また、上写真のように両者を見比べてみると、購入ショップが異なるためかメーカーも恐らく異なっているらしく、両者では微妙に使用部品の配置や回路構成なども、若干ですが異なっている様子が窺えます。

| ページトップ |

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

右側面側から見た様子 左側面側から見た様子
前側面側から見た様子 後側面側から見た様子

以下は外観6面写真です。

後側面
左側面 正面(上面) 右側面
前側面
背面(下面) 天地を逆にした写真

上蓋を開いてケース内部を見た様子 撮る角度を少し変えてもう1枚
カレンダー表示をしている様子 本機の電源の 18650 リチウムイオン電池を充電中の様子

| ページトップ |

■ 機能概要と使用法 ■

  • 本機では携帯使用をするために、電源には 18650 リチウムイオン電池を採用している。 そして、リアルタイムクロック(RTC)モジュールを搭載(バックアップ用のバッテリーも搭載)してあるため、リチウムイオン電池の消耗などで電源が切れたときはもちろん、 本機の不使用時の長時間の電源断にも、安定した時刻の継続が期待できる。

  • また、本機には 18650 リチウムイオン電池のための充電機能も内蔵しているので、USB コネクタから + 5 V 電源を供給すれば電池を充電することも可能である。 ただし、本機では充電中には本機の電源スイッチを切っておく必要があり、 充電しながらの連続使用はできない。

  • なお、本機では電源スイッチを一旦切ってから再び入れ直すときには、その間2〜3秒以上を置いてからにしないと、うまく起動をしない場合があるので注意が必要である。(現在、回避策を調査検討中)

◎ 本機の起動時の動作
  • さて、本機の電源スイッチを ON にすると、"ピポッ" と開始ブザー音を出力後、プログラムのタイトル、およびバージョン番号などの表示とともに、有機 EL ディスプレイ(OLED) のデモ表示が数 10 秒間行われる。 (前作をご覧になった方にはお馴染みの、縁枠のドット移動表示デモを今回作にも取り入れた。)
    			 Perpetual Calendar
    			   (OLED Edition)
    			    Version x.xx
    			    by m.yamamoto
    

  • ただし、このデモ表示だけで約 20 秒ほどを要するため、DOWN スイッチと UP スイッチを同時に押しながら電源を投入 すると、デモ表示だけを省略 することができる。

  • ディスプレイ(OLED) のデモ表示が終了すると、PIC のフラッシュメモリ (High-Endurance) に記憶されている、各種の引き継ぎ情報を RAM バッファ、および各種変数へ読み出す。

  • その後、リアルタイムクロック(RTC)モジュールの状態がチェックされ、初めて電源を入れたときや、バックアップ用バッテリーが異常なとき等に、次のエラーメッセージがディスプレイ(OLED) 画面に表示されるとともに、"ブッブー" ブザー音が出力される。
    			 DS3231 Error!
    			        Init?_
    

  • なお、このときディスプレイ(OLED) 画面では "Init?_" の後がブリンク表示されているが、これはリアルタイムクロック(RTC)モジュールの初期設定をするかどうかを、ユーザに応答を求めていることを表している。 ユーザはバックアップ用バッテリーの状態等を確認してその対処を行った後、この場合には 5個のスイッチの内のどれかを押して応答 をする。

  • すると、リアルタイムクロック(RTC)モジュールの初期設定を行った後、再度リアルタイムクロック(RTC)モジュールの状態がチェックされ、なおも NG であれば同様にエラーメッセージの表示が繰り返されるが、OK であれば時計機能が開始され、 ディスプレイ(OLED) 画面は、時間表示とともにカレンダー表示に切り替わる。 このとき表示される画面を NORMAL モード という。

        NORMAL モードで時計機能が開始

| 機能概要のトップに戻る |


◎ 基本機能とスイッチ操作
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │○│   │○│   │○│   │○│   │○│
    			 └─┘   └─┘   └─┘   └─┘   └─┘
    			 SIGNAL    ZERO     DOWN      UP      MODE
    			/CANCEL   /BACK   /MAINTE   /TMODE    /SET
    
    		MODE スイッチ        ..... NORMAL モード / LARGE モードの切り替え
    
    		MODE スイッチ 長押し ..... SET モードに移行(3秒以上の長押し)
    		(SET スイッチ)
    
    		  UP スイッチ        ..... カレンダーめくり機能(1か月前に進める)
    					 ( LARGE モード中は無視)
    
    		  UP スイッチ 長押し ..... 24時間表示 / 12時間表示の切り替え(3秒以上の長押し)
    	      (TMODE スイッチ)
    
    		DOWN スイッチ        ..... カレンダーめくり機能(1か月後に進める)
    					 ( LARGE モード中は無視)
    
    		DOWN スイッチ 長押し ..... メンテナンス機能に移行(3秒以上の長押し)
    	     (MAINTE スイッチ)		 (カレンダーめくり機能中はカレンダーめくり機能)
    
    		ZERO スイッチ        ..... 毎正時プラス・マイナス5分以内を 00分00秒に設定
    					 (5分以外では無視)
    
    	      SIGNAL スイッチ        ..... 毎時の時報音出力を ON/OFF 制御
    
    
  • 初めて本機に電源を投入すると、カレンダーおよび時間は "2025/01/01"、"00:00:00" と、本機をプログラミングしたときの設定値から始まって表示をするため、後述の「SET モード機能とスイッチ操作」手順で現在の年月日、 時分秒に設定をし直す必要がある。

  • なお、本機には上図のように操作をするための押しボタンスイッチが5個ありその機能概略を示すが、以降にその使用法の詳細を順に説明して行く。

    [ NORMAL / LARGE モードの切り替え機能 ]

  • その設定手順の説明をする前に、LARGE モードについてを先に触れると、上述のように、デモ表示の後 NORMAL モードに移行して、ディスプレイ(OLED) 画面は通常の7曜カレンダー表示をしているが、この状態のときに MODE / SET スイッチ を押すと、 画面には大きな文字が表示されるようになり、この状態を LARGE モード という。 当然ながら文字が大きくなったため、7曜カレンダー表示はできない。

        LARGE モードに切り替わった

  • NORMAL モードと LARGE モードは、MODE スイッチ を押すごとに交互にそのモードを切り替えることができる。 このように MODE スイッチをチョンと押して、NORMAL モードと LARGE モードを切り替えるのではなく、長押し をすることにより、 後述 のように年月日、時分秒を希望値に設定変更することができる SET モード となる。

    [ カレンダーめくり機能 ]

  • NORMAL モードにおいての UP スイッチ または DOWN スイッチ の振る舞いは、後述の SET モードのように項目の設定値を変更するのではなく、現在、ディスプレイ画面に表示されている 年月表示とカレンダー表示を、月ごとに前進、または後退 させて、紙のカレンダーをめくるように変更表示をする。 なお、このときの時分秒の時刻については、カレンダーめくりの機能とは関係なく現在時刻をきざみ続ける。

  • そして、ディスプレイ画面のメッセージエリアには、"←Down Up→" が表示され、かつ、"←Down" または "Up→" のどちらかが反転表示されて、本日の年月日(現在位置)からどちらの方向に偏っているかを表している。 本日の年月日にもどると、これらのメッセージは消えて7曜カレンダー内の該当日(本日)が反点表示される。

        1か月前を表示(後退) 本日の年月日(現在位置) 1か月後を表示(前進)

  • なお、この "←Down Up→" が表示されている [ カレンダーめくり機能 ] のときには、MODE / SET スイッチの操作をしても無視されて、LARGE モードへの切り替え、または SET モードへの移行はできない。

  • LARGE モードにおいては7曜カレンダー表示されることがないため、 UP スイッチまたは DOWN スイッチを押しても、画面表示の変化はなく無視される。

    [ 24時間表示 / 12時間表示の切り替え機能 ]

  • NORMAL モード、または LARGE モードのときに、UP / TMODE スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、24時間表示 / 12時間表示の切り替えが行われ、この操作を行うごとに表示形式が交互に切り替わる。

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

             ( LARGE 画面での表示画面例 )

  • そして、24時間表示 から 12時間表示になったときには、直ちに "am" または "pm" が、そのときの時 "xx" の設定値によって変更表示される。 逆に、12時間表示 から 24時間表示になったときには、"am"、"pm" 表示は消える。

    [ ZERO スイッチ機能 ]

  • ZERO / BACK スイッチ は、後述するように SET モードでは BACK スイッチとして機能するが、それ以外の NORMAL モード、および LARGE モードでは、毎正時プラス・マイナス5分以内に押されると 、00分 00秒に設定するための ZERO スイッチとして機能 し、ZERO スイッチを放した直後に、リアルタイムクロック(RTC)モジュールと PIC のフラッシュメモリ (High-Endurance) を更新後、"ピピッ" ブザー音を伴って更新したことを知らせる。

  • なお、毎正時プラス・マイナス5分以外に同スイッチが押されたときには、時間を更新することなく無視される。

    [ 毎時の時報音出力の ON / OFF 制御機能 ]

  • SIGNAL / CANCEL スイッチ は、押すごとにディスプレイ画面右下のメッセージエリアに、"Signal On" と "Signal Off" を交互に3秒間表示し、毎時の時報音のブザー音出力を、有効/無効に交互に設定をする。

        時報音が無効に設定 時報音が有効に設定

  • このとき、"Signal On" の有効のときには "ピピピッ" ブザー音を、"Signal Off" の無効のときには "ブー" ブザー音を伴って知らせる。 なお、電源を投入直後は "Signal On" の有効に設定がされている。

  • また、LARGE モードにおいては SET モードに切り替わったときと同様、メッセージエリアの確保のために2行目と3行目が上部位置に移動して、同メッセージが表示される。

        LARGE モード時の時報音 OFF の状態 LARGE モード時の時報音 ON の状態

  • なお、ここで設定するブザー音出力の有効/無効は、あくまでも毎時の時報音出力だけに関わる設定であって、その他のスイッチ操作等に伴なって出力される効果音には、当てはまらないので注意が必要である。

    [ スリープモード ]

  • NORMAL モード、または LARGE モードのとき( [ カレンダーめくり機能 ] 時も含めて)に、どのスイッチも操作しない状態が 10 分(デフォルト)以上続く と、省エネのため自動的にディスプレイ (OLED) をスリープさせるとともに、本機自体も スリープモード に移行する。( SET モード機能、 メンテナンス機能を実行中はスリープモードに移行しないので要注意。)

  • 本機がスリープモードに移行するときには、10 分(デフォルト)を経過する3秒前から、秒ごとに "ブッ" ブザー音を3回、また、10 分を経過直後に "ブッブー" ブザー音とともにスリープモードに移行する。

  • なお、この移行までの時間は後述の 「メンテナンス機能とスイッチ操作」 で、0 〜 60 分の範囲(ただし、0 設定時はスリープしない)で変更することができる。

  • また、本機自体およびディスプレイ (OLED) がスリープモードになっているときに、5つのスイッチの内のどれかが操作 されると本機は ウエイクアップ して、 "ピピッ" ブザー音とともに、再びディスプレイ (OLED) 画面の表示がされるようになる。

| 機能概要のトップに戻る |


◎ SET モード機能とスイッチ操作
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │○│   │○│   │○│   │○│   │○│
    			 └─┘   └─┘   └─┘   └─┘   └─┘
    			 SIGNAL    ZERO     DOWN      UP      MODE
    			/CANCEL   /BACK   /MAINTE   /TMODE    /SET
    
    		 SET スイッチ        ..... ブリンク位置のポインタを + 1
    
    		BACK スイッチ        ..... ブリンク位置のポインタを - 1
    
    		  UP スイッチ        ..... ブリンク位置の値を + 1
    		  UP スイッチ 長押し ..... ブリンク位置の値を + 1 早送り
    
    		DOWN スイッチ        ..... ブリンク位置の値を - 1
    		DOWN スイッチ 長押し ..... ブリンク位置の値を - 1 早送り
    
        (秒選択時に) SET スイッチ        ..... SET モードを終了し、NORMAL / LARGE モードに戻る
    
    	      CANCEL スイッチ        ..... SET モードを中断し、NORMAL / LARGE モードに戻る
    
    
  • さて、ここで話を戻して、年月日、時分秒の設定を変更する手順は、まず MODE / SET スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、ディスプレイ画面右下のメッセージエリアに "SET MODE" と反転表示されて、NORMAL モード、 または LARGE モードから SET モード に切り替わったことを示し、年月日および時分秒の表示は更新が停止する。

  • なお、このとき LARGE モードから SET モードに切り替わった場合には、メッセージエリアの確保のため、2行目(曜日、am/pm)の表示と3行目(時分秒)の表示が、以降 SET モードの間中は上部位置に移動して表示される。

        SET モードに切り替わった LARGE モードから SET モードに

  • そこで MODE / SET スイッチを放すと、メッセージは "Year Hi ?" に変わり、左上の年月 "xxxx/xx" 表示エリアの先頭2桁がブリンク表示されて、年の上位2桁の変更が可能となる。 (下の写真では反転表示になっているだけであるが、実際にはブリンク表示がされる。 以下、同様。)

        年の上位2桁の変更が可能 LARGE 画面で年の上位2桁の変更時

  • もし変更が必要であれば、UP スイッチ を押すごとに現在値より1ずつ増加し、また DOWN スイッチ を押すごとに1ずつ減少するので、適宜希望する値に変更する。

  • 年の上位2桁の変更が済んだら、再び MODE / SET スイッチ を押すとメッセージは "Year Lo ?" に変わり、左上の年月 "xxxx/xx" 表示エリアの 年の下位2桁がブリンク表示され、年の下位2桁の変更が可能となる。

        年の下位2桁の変更が可能 LARGE 画面で年の下位2桁の変更時

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

  • 以降、同様に SET スイッチ を押すごとに、月 → 日 → 24H/12H → 時 → 分 → 秒 と設定項目を変更することができるので、変更が必要であればその該当項目の選択時に、UP スイッチまたは DOWN スイッチを押すことによって、 適宜希望する値に変更する。

  • また、このときのメッセージエリアには、それぞれ "Month ?"、"Today ?"、"24H/12H ?"、"Hour ?"、"Minute ?"、"Second ?" と反転表示され、NORMAL 画面では1行目の該当項目の月、24H/12H、時、分、秒の、それぞれがブリンク表示されて選択項目を表す。 LARGE 画面においても位置は異なっているが、該当する項目が同様にブリンク表示される。

             ( 設定例 )
        年 "xxxx"、月 "xx" は変更なし 日 を "16" に設定 デフォルトは "24H" になっている
        "12H" に変更後、時を "pm 8" に設定 分 を "35" に設定 秒 を "30" に設定

             ( LARGE 画面での設定画面例 )

  • 選択項目の日 "xx" については、NORMAL 画面では7曜カレンダー内で該当日(本日)がブリンク表示されるので、同様に UP スイッチまたは DOWN スイッチによって、その位置を移動変更することにより選択をする。 また、LARGE 画面においては1行目の右端2桁がブリンク表示され、他の項目と同様に UP スイッチまたは DOWN スイッチを押すことによって、適宜希望する値に変更する。

  • この SET スイッチによって項目を選択中に、誤って希望する項目を通り過ぎてしまったような場合には、BACK スイッチ を押すごとにひとつずつ前の項目に戻ることができる。

  • 最後の秒の項目選択時に更に SET スイッチを押すと、今まで変更されてきた各項目の設定値が、新たな情報として リアルタイムクロック(RTC)モジュール と PIC の フラッシュメモリ (High-Endurance) に書き込み更新 され、 その後、SET モードからNORMAL モード、または LARGE モードの、SET モードに移行する前のディスプレイ(OLED) 画面に再び戻って、その設定値から年月日、時分秒の表示が再開される。

      • 設定再開後、"47 秒" が経過した SET モードから再び LARGE モードに

  • SET モードでの選択項目の推移をまとめると次図のようになる。
    	                               BACK            BACK  BACK  BACK       BACK  BACK  BACK
    	             MODE               ←              ←    ←    ←         ←    ←    ←
    	             /SET              SET             SET   SET   SET        SET   SET   SET   SET
    	 NORMALモード ─→ 年(上位2桁) → 年(下位2桁) → 月 → 日 → 24H/12H → 時 → 分 → 秒 ─→ NORMALモード
    	 (LARGEモード)          │                                                            ↑     (LARGEモード)
    	                    BACK└──────────────────────────────┘
    
    
  • ここで項目 24H/12H について補足をしておくと、これは時表示を 24時間表示にするか 12時間表示にするか、どちらかを選択することで、UP スイッチまたは DOWN スイッチのどちらかを押すことによって、交互に切り替えることができる。

        デフォルトは "24H" になっている "12H" に切り替えた

  • 24H を選択した場合は、次の項目に移った時に "24H/12H" 表示エリアには何も表示されないが、12H を選択した場合は、次の項目に移った時に "am" または "pm" が、そのときの時 "xx" の設定値によって変更表示される。

        次項目に移ると "pm" が表示される

  • 次に、12時間表示と 24時間表示の対応を示す。 なお、12時間表示の場合だけ 時 "xx" の先頭の1桁目は、ゼロサプレスを行なって表示をする。
    		(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
    
    
  • 上述のように、最後の秒の項目選択時に更に SET スイッチ を押した場合には、リアルタイムクロック(RTC)モジュール等を更新 後、"ピピッ" ブザー音を伴って正常に終了したことを知らせる。

  • また、各項目の変更中に何らかの理由があって途中で変更作業を中断したい場合には、SIGNAL / CANCEL スイッチ を押すことによって、直ちに SET モードから NORMAL モード、または LARGE モードの、SET モードに移行する前に戻ることができる。 この場合には、リアルタイムクロック(RTC)モジュール等を更新することはなく、"ブー" ブザー音を伴って中断終了したことを知らせる。

| 機能概要のトップに戻る |


◎ メンテナンス機能とスイッチ操作
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │○│   │○│   │○│   │○│   │○│
    			 └─┘   └─┘   └─┘   └─┘   └─┘
    			 SIGNAL    ZERO     DOWN      UP      MODE
    			/CANCEL   /BACK   /MAINTE   /TMODE    /SET
    
    		 SET スイッチ        ..... OLED コントラスト / スリープまでの移行時間 の選択
    
    		  UP スイッチ        ..... ブリンク位置の値を + 1
    		  UP スイッチ 長押し ..... ブリンク位置の値を + 1 早送り
    
    		  UP スイッチ +
    		DOWN スイッチ        ..... ブリンク位置の値をデフォルト値に設定
    
    		DOWN スイッチ        ..... ブリンク位置の値を - 1
    		DOWN スイッチ 長押し ..... ブリンク位置の値を - 1 早送り
    
    		DOWN スイッチ +
    		  UP スイッチ        ..... ブリンク位置の値をデフォルト値に設定
    
    		BACK スイッチ        ..... メンテナンス機能を終了し、NORMAL / LARGE モードに戻る
    
    	      CANCEL スイッチ        ..... メンテナンス機能を中断し、NORMAL / LARGE モードに戻る
    
    
  • NORMAL モードのときに、DOWN / MAINTE スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、ディスプレイ画面右下のメッセージエリアに "Maintenance" と反転表示されて、メンテナンス機能への移行準備が行われるので、 DOWN / MAINTE スイッチを放すと、ディスプレイ画面が メンテナンス機能 画面に切り替わる。


  • また、LARGE モードのときに、DOWN / MAINTE スイッチ を3秒間以上押し続けると、SET モードに切り替わったときと同様、メッセージエリアの確保のために2行目と3行目が上部位置に移動して表示され、以降は NORMAL モードのときと同様である。
    			=== Maintenance ===
    			 > OLED Contrast
    			  (001-255) ? _ xxx
    			 > Sleep Time
    			  (00-60) ? _ xx
    

  • 本機におけるメンテナンス機能には、OLED コントラストを設定変更スリープまでの移行時間(分)を設定変更、の2つの機能があり、本メンテナンス機能画面に切り替わった直後は、前者の設定変更が選択されて "(001-255) ? _ xxx" メッセージ の "xxx" 部分がブリンク表示される。

  • そこで、前者設定値を変更したい場合には、UP スイッチ を押すごとに現在値より1ずつ増加し、また DOWN スイッチ を押すごとに1ずつ減少するので、適宜希望する値に変更する。

  • また、後者の設定変更を選択したい場合には、MODE / SET スイッチ を押すことによって "(00-60) ? _ xx" メッセージ の "xx" 部分がブリンク表示されるので、同様に UP スイッチまたは DOWN スイッチを押すことによって、 希望する値に変更する。


  • このときの MODE / SET スイッチは、押すごとに両者の設定変更の選択を交互に切り替えることができ、それぞれで変更できる 設定範囲は 、前者では 001 〜 255 まで、後者では 00 〜 60 までとなっている。 ただし、後者で 00 を設定した場合には、スリープモードには移行しなくなるので注意が必要である。

    (余談) 前者の設定値として、SSD1306 では 000 も可能ではあるが、その場合には画面が完全に消えてしまうので、本機では設定値から外すことにした。

  • また、UP スイッチまたは DOWN スイッチによる増減幅を大きくしたい場合には、UP スイッチまたは DOWN スイッチを押したまま にしていると、増減値が早送りされる ようになる。

  • なお、OLED コントラストを設定変更、スリープまでの移行時間(分)を設定変更、の2つの設定値のデフォルト値は、それぞれ 127 と 10 に規定されており、それぞれの設定変更が選択されているときに、UP スイッチと DOWN スイッチを同時に押す ことによって、それぞれの デフォルト値に簡単に設定する ことができる。

  • 両者の設定変更が済んで、元の NORMAL モードまたは LARGE モードに戻りたい場合は、ZERO / BACK スイッチ を押すことによって行われ、変更された設定値で PIC の フラッシュメモリ (High-Endurance) を更新 後、 "ピピッ" ブザー音を伴って正常に終了したことを知らせる。

  • また、何らかの理由があって途中で設定変更を中断したい場合には、SIGNAL / CANCEL スイッチ を押すことによって、メンテナンス機能に移行する前の NORMAL モードまたは LARGE モードに戻ることができる。 この場合には、それまでに 変更された設定値は破棄 され、"ブー" ブザー音を伴って中断終了したことを知らせる。

| 機能概要のトップに戻る | ページトップ |

■ プログラム ■

 本ページの冒頭でも述べたように、本機では PIC16F1705 を採用してプログラム開発を行いました。 プログラムメモリやスタックメモリのサイズも十分にあって、まず、スタックメモリをオーバーフローさせるような心配も少なく、 PIC16F ファミリとは異なるアーキテクチャのもとに追加された便利な命令等を多用して、私にとっては快適にプログラミングを楽しむことができました。

 とはいうものの、本機のプログラムが完成するまでには2か月以上が掛かってしまいました。 後述する OLED モジュール ( SSD1306 ) 制御サブルーチンの開発や、メインのプログラムの細部にも多くの機能を追加をしたことで、 全体として多くの時間も要することになりました。  このプログラムの項では、有機 EL ディスプレイ(OLED)( SSD1306 )モジュールのプログラミングについてを重点的に、本機でのプログラミングにおける実例を示しながら解説をしたいと思います。 なお、本機でも使用した、リアルタイムクロックモジュールのプログラミングについては、既に、"190. I2C IF モジュール + LCD(1602A) 表示時計" の リアルタイムクロックモジュールのプログラミング で詳述をしているので、そちらをご覧になってください。

 現在、プログラムメモリは、Page 0、Page 1、Page 2、Page 3 の全4ページの内、Page 2 の部分がまるまる空いており、今後も本機に取り入れたい機能の拡張を計るつもりではいますが、少々疲れたのでここでひとまず休憩を入れたいと思います。 身体を休めてから機能の追加を行って、改めてその部分を公開し直したいと思います。

● 本機で使用した PIC16F1705 のメモリの使用状況

 本機のプログラム全体を理解する上で、データメモリの内の特殊機能レジスタ (SFR) には、どのレジスタにアクセスをしているかとか、プログラムメモリの使用状況がどのようになっているか、などの情報が事前に分かっていると、 他の人はもちろんのこと、作者の自分自身でも数か月以上が経ってしまったときには、非常に役に立つと思います。

 プログラム規模が大きくなればなるほどそれらの情報が役立つものとして、最近の私作の規模が大きいプログラムでは記録に残しておくようにしています。

◎ 本機におけるデータメモリの使用状況

 次の TABLE 3-2、TABLE 3-3 は、Microchip Technology Inc. 社の PIC16F1705 データシートから、データメモリの内の一部分を抜粋したもので、私がプログラムで一度でもアクセスをしたレジスタについて、それらがよく分かるように彩色を施しました。

 黄色や青色に塗ったレジスタが 特殊機能レジスタ (SFR) で、これらの内で青色のものは、High-Endurance フラッシュメモリにアクセスをするときに、必要になるレジスタ群です。 また、薄緑色のレジスタ群は特殊機能レジスタ (SFR) ではなく、 一般の変数など、ユーザが自由に使用できる 汎用レジスタ(GPR) を表しています。

| プログラムのトップに戻る |

◎ 本機におけるプログラムメモリの使用状況

 次表は、本機(プログラムバージョン: Ver. 1.05 現在)における PIC のプログラムメモリの使用状況を、各処理別に分けたメモリ分布(割り付け)をページごとに表したもので、 今後にプログラム更新があれば、使用メモリの割り付けアドレス等には多少の変動は起こると思いますが、各ページ内における各処理の順番等の構成については、今のところ変更するつもりはないので、プログラム全体を把握する上では参考になるものと思います。

 今後の予定としては、現在、Page 2 の部分がまるまる空いているので、そこに追加機能のプログラムを収容するつもりですが、そのプログラムへの導入部分がメインプログラムの処理に必要となるため、 Page 0 の若いアドレスに位置しているメインプログラムのサイズが増大して、以降の各処理のアドレスにも変動が起こり得ます。

        ページ 使用メモリ範囲 サイズ プログラム処理
        0 h'0000' 〜 h'004B' 76 words   割り込み処理 
        h'004C' 〜 h'01F0' 421 words   外部サブルーチン include エリア *1 
        h'01F1' 〜 h'02CF' 223 words   初期化処理等、他 
        h'02D0' 〜 h'0309' 58 words   メインプログラムの処理
        h'030A' 〜 h'033B' 50 words   UP スイッチの処理
        h'033C' 〜 h'037A' 63 words   DOWN スイッチの処理
        h'037B' 〜 h'041E' 164 words   UP、DOWN スイッチ、その他の共通処理
        h'041F' 〜 h'0454' 54 words   ZERO スイッチの処理
        h'0455' 〜 h'04AF' 91 words   SIGNAL スイッチの処理
        h'04B0' 〜 h'0539' 138 words   MODE / SET スイッチの処理
        h'053A' 〜 h'0599' 96 words   SET モード内での各種スイッチの処理
        h'059A' 〜 h'05E6' 77 words   メンテナンス機能の処理
        h'05E7' 〜 h'062A' 68 words   メンテナンス機能内での各種スイッチの処理
        h'062B' 〜 h'065F' 53 words   時間の監視とスリープモード処理
        h'0660' 〜 h'06CA' 107 words   High-Endurance フラッシュメモリ関連アクセス
        h'06CB' 〜 h'075F' 149 words   アラーム関連、ウェイトルーチン
        h'0760' 〜 h'07A0' 65 words   ページ変換サブルーチン (Page 0 用)
        h'07A1' 〜 h'07FF' 95 words   空き
        1 h'0800' 〜 h'097C' 381 words   各_BCD カウンタのインクリメント / デクリメント計算
        h'097D' 〜 h'09AB' 47 words   ページ変換サブルーチン (Page 1 用)
        h'09AC' 〜 h'0BF8' 589 words   NORMAL / LARGE モード時の各種スクリーン表示
        h'0BF9' 〜 h'0D16' 286 words   SETモード時のブリンク表示
        h'0D17' 〜 h'0EFB' 485 words   タイトルの表示と縁枠のドット移動デモ表示
        h'0EFC' 〜 h'0FB1' 182 words   メンテナンスメッセージの表示
        h'0FB2' 〜 h'0FFF' 78 words   空き
        2 h'1000' 〜 h'17FF' 2,048 words   空き
        3 h'1800' 〜 h'1BBF' 960 words   文字フォント (5 x 7) データ 外部テーブル include エリア *2 
        h'1BC0' 〜 h'1E50' 657 words   文字フォント (10 x 14) データテーブル、他
        h'1E51' 〜 h'1F7F' 303 words   空き
        h'1F80' 〜 h'1FFF' 128 words   (High-Endurance フラッシュメモリ) 数バイトのみ使用
        *1: I2C (SCLクロック周波数 = 100/400 KHz) サブルーチン(ソフトウエア I2C 版)(I2C_XS.sub)
        I2C RTC(DS3231/1307)モジュール 制御サブルーチン (I2C_RTCII.sub)
        OLED モジュール ( SSD1306 ) 制御サブルーチン (OLED_SSD1306.sub)
        *2: 文字フォント(5 x 7)データテーブル (Font5x7.tbl)

| プログラムのトップに戻る |

● 有機 EL ディスプレイ(OLED)( SSD1306 )モジュールのプログラミング

 現在、"SSD1306" をキーワードとしてネット検索をしてみると、随分とたくさんの候補がヒットしますが、その殆どが Arduino や Raspberry Pi 関連のもので、私のような PIC 人間にはとても残念であり、また、肩身の狭いような思いもします。 上述の 本機で使用した各モジュール有機 EL ディスプレイ(OLED)( SSD1306 )モジュール の項でも触れましたが、私のように本モジュールを使用するのが初めての者が、 利用できるような PIC 用の既成のライブラリの存在は、まず期待することができません。

 しかも、私のように特にアセンブラ言語を使用したプログラミングを行う者にとっては尚更で、最近ではネット検索をしてみても初めからあきらめムードですが、結果は、やはり自分が求めているような情報を得ることはなかなか難しいようです。 それでも、唯一、私が参考にさせて頂いたサイトを見つけたので、ここにお礼も兼ねてご紹介をさせて頂きます。 "JR3TGS' Homebrewing Place" さんの "有機EL (OLED)をPICマイコンで制御" というページです。 お世話になり、ありがとうございました。

 ◎ グラフィック ディスプレイ データ RAM (GDDRAM) の構成

 GDDRAM は、表示されるビット パターンを保持するビット マップ スタティック RAM で、下図の赤枠で囲まれた部分がスクリーン全体のメモリ配置図です。 そのサイズは 128 x 64 ビットで、RAM は PAGE0 から PAGE7 までの 8 つのページに分割され、各ページは SEG0 から SEG127 までの 128 のセグメントで構成されています。

 そして、赤枠内の小さな各1マスずつが各1ビットを表し、例えば、薄緑色に塗りつぶした縦列の 8 ビット部分が、各ページ内の各セグメントの1バイトを表しています。 また、その1バイト内の、データ ビット D0 は最上行で、データ ビット D7 は最下行に配置されます。


 なお、次項のディスプレイ(OLED) の画面レイアウト以降の説明や、後述する OLED モジュール ( SSD1306 ) 制御サブルーチン 等のプログラムでは、これらのページ、セグメントという構成する単位を、 ページは同様に ページ Page ですが、セグメントは カラム Column という単位で扱っています。

| プログラムのトップに戻る |

 ◎ ディスプレイ(OLED) の画面レイアウト

 本機の画面レイアウトについては、前作の "174. グラフィック液晶表示 万年カレンダー" とほとんど同様としました。 しかし、横 128 x 縦 64 ドットという構成は、前作で使用したグラフィック液晶(SG12864A)と同様ですが、今回使用する OLED (SSD1306) とではその制御方法がまったく異なっています。

 ・ NORMAL モード画面

 1行目(Page 0)には、年月 "xxxx/xx" 、"  "/"am"/"pm" の種別、および時分秒 "xx:xx:xx" を表示するエリアです。 2行目(Page 1)は、 曜日の表示エリアです。 3行目(Page 2)から8行目(Page 7)までが、カレンダーの各日にちが表示されるエリアです。

 また、最下行の8行目(Page 7)は、行頭から6文字目以降はカレンダーの日にち表示がされることはないので、画面右下の赤細線枠で囲んだ部分を、 いろいろなメッセージをユーザに伝えるための、メッセージエリアとして使用しています。

 なお、1行目(Page 0)と、その他の2行目(Page 1)から8行目(Page 7)までとの、文字フォントを表示しているビット位置に注目をして見比べてください。 Page 0 では bit 0 〜 bit 6 の位置に表示をしていますが、 その他の Page 1 〜 Page 7 では bit 1 〜 bit 7 の位置に表示をしています。

 ・ LARGE モード画面

 文字サイズを NORMAL モード画面に比べて、縦横2倍(面積4倍)のサイズで表示します。 したがって、次図に示すように文字表示には1行に 2 Page 分を必要とし、行間には 1 Page 分を割り付けました。 当然ながら日にちの表示は、 NORMAL モード画面のように7曜カレンダーで表示することはできません。

 この LARGE モード画面で表示しているときに SET モード機能に移行したときなどには、下図中の Page 2 と Page 5 の行間の空白行をなくして、Page 3, 4 と Page 6, 7 を上方に移動させて表示をし、最下行(Page 7)にメッセージエリアを確保します。

| Excel ファイル (PerpetualCalendarII_parts.xls) |

| プログラムのトップに戻る |

 ◎ ドライバ IC SSD1306 の I2C インタフェース制御方法

 下図 Figure 8-7 は、SSD1306 データシートから抜粋した I2C-bus data format ですが、同図は分かりづらい書き方がしてあって、少々理解するのに苦しみます。

 まず、S - Start Condition に続いて Slave Address を送り、その次には Control byte を送るのですが、これから送るデータ群が Command byte なのか Data byte なのかを、D/C# (Data / Command Selection) bit で決めます。 Command byte を送りたい場合には "0" を指定 し、Data byte を送りたい場合には "1" を指定 します。

 そして、一度に複数の Command byte または Data byte を送りたい場合には、Co (Continuation) bit"0" を指定 することによって、以降、何バイトでも連続して送ることができますが、 "1" を指定 した場合には、1バイトの Command byte または Data byte を送ることしかできません。 そして、最後に P - Stop Condition を送って終了させます。

 Figure 8-7 では、S - Start Condition から P - Stop Condition までの間に2個の Control byte が現れていますが、1個目に Co=1 指定をした場合は良いのですが Co=0 指定をした場合には、2個目が Control byte なのか Command byte(または Data byte)なのかを、判別する術はないはずですから同図のような送り方には注意が必要だと思います。

 図中の1個目の Control byte で m ≧ 0 words という意味 は、Co=1 指定をした場合に 成り立つことで、Co=1 指定 の Control byte1バイトの Command byte または Data byte をペア(1 word)として、複数のワードを送ることが可能 ― という意味で、また、図中の2個目の Control byte 後の Data byte で n ≧ 0 bytes という意味 は、2個目の Control byte に Co=0 指定をした場合には複数バイトの Command byte または Data byte を送ることが可能 ― という意味である、と解釈をしました。

 実際には、これらの複数の Control byte を使用した動作確認を私はしていません。 後述する OLED モジュール ( SSD1306 ) 制御サブルーチン では、どのサブルーチンも S - Start Condition から P - Stop Condition までの間には、単純に1つの Control byte だけを使用して I2C インタフェースを制御しています。


 例えば、次のリスト例のように、ディスプレイの ON/OFF 制御を行う SSD1306_DispOnOff サブルーチン では、Control byte に Co=1, D/C#=0 を指定して、その後に1バイトの Command byte (h'af' または h'ae') を送っています。
      ;==========================================================================
      ;		OLED ( SSD1306 ) の Display ON/OFF 制御
      ;==========================================================================
      
      ;入力レジスタ:	W reg:	コマンドデータ h'af':ON / h'ae':OFF
      
      ;使用レジスタ:	pattern: ワーク
      
      SSD1306_DispOnOff
      		movwf	pattern			;ワークに一時退避
      
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'80'			;Control byte Co=1, D/C#=0
      		call	i2c_byte_send		;1 バイト送信
      
      		movf	pattern,W		;コマンドデータを復帰
      		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      		return
      
 また、次のコントラスト制御を行う SSD1306_Contrast サブルーチン では、Control byte に Co=0, D/C#=0 を指定して、その後に2バイトの Command byte (h'81' と h'00' 〜 h'ff' のどれか) を送っています。 (この例では2バイトだけを送っていますが、Co=0 指定では 何バイトでも送ることが可能)
      ;==========================================================================
      ;		OLED ( SSD1306 ) の コントラスト制御
      ;==========================================================================
      
      ;入力レジスタ:	W reg:	コマンドデータ h'00'- h'ff'
      
      ;使用レジスタ:	pattern: ワーク
      
      SSD1306_Contrast
      		movwf	pattern			;ワークに一時退避
      
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'00'			;Control byte Co=0, D/C#=0
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	h'81'			;Set Contrast Control
      		call	i2c_byte_send		;1 バイト送信
      
      		movf	pattern,W		;コマンドデータを復帰
      		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      		return
      
 上に挙げた2つの例では、どちらも D/C#=0 指定で Command byte を送っていますが、D/C#=1 を指定すれば、同様に Data byte を送ることができます。

 そして、Command byte を送った場合には、SSD1306 を制御するためのコマンドとして解釈されますが、Data byte を送った場合には、ディスプレイの表示データとして GDDRAM へ書き込まれます。 なお、コマンドには多くの種類が用意されていて、詳細は SSD1306 データシートの 9 COMMAND TABLE (P 28/59) をご覧ください。

| プログラムのトップに戻る |

 ◎ ディスプレイ RAM (GDDRAM) のアドレス指定モード

 GDDRAM のアドレス指定モードには、下図に示す Figure 10-1 ページ アドレス指定モード、Figure 10-3 水平アドレス指定モード、Figure 10-4 垂直アドレス指定モード の3種類があります。(これらの図は SSD1306 データシート から抜粋)


 上図 ページ アドレス指定モード では、ディスプレイ RAM へ1バイトデータを書き込んだ後、カラム アドレス ポインタが自動的に1増加します。 カラム アドレス ポインタがカラム終了アドレスに達すると、カラム アドレス ポインタはカラム開始アドレスにリセットされますが、ページ アドレス ポインタは変更されません。 次のページのディスプレイ RAM にアクセスするには、新しいページ アドレスとカラム アドレスを設定する必要があります。

 実際に ページ アドレス指定モード を使用した例として、次項の緑色リストの SSD1306_FontPos サブルーチン を参照してみてください。


 上図 水平 アドレス指定モード では、ディスプレイ RAM へ1バイトデータを書き込んだ後、カラム アドレス ポインタが自動的に1増加します。 カラム アドレス ポインタがカラム終了アドレスに達すると、カラム アドレス ポインタはカラム開始アドレスにリセットされ、ページ アドレス ポインタが 1 増加します。 カラム アドレス ポインタとページ アドレス ポインタの両方が終了アドレスに達すると、それぞれのポインタは、カラム開始アドレスとページ開始アドレスにリセットされます。

 実際に 水平 アドレス指定モード を使用した例として、次項の緑色リストの SSD1306_Clear サブルーチン を参照してみてください。


 上図 垂直 アドレス指定モード では、ディスプレイ RAM へ1バイトデータを書き込んだ後、ページ アドレス ポインタが自動的に1増加します。 ページ アドレス ポインタがページ終了アドレスに達すると、ページ アドレス ポインタはページ開始アドレスにリセットされ、カラム アドレス ポインタが 1 増加します。 カラム アドレス ポインタとページ アドレス ポインタの両方が終了アドレスに達すると、それぞれのポインタは、カラム開始アドレスとページ開始アドレスにリセットされます。

 実際に 垂直 アドレス指定モード を使用した例として、次項の緑色リストの SSD1306_Line_V サブルーチン を参照してみてください。

 なお、上に挙げた3つのサブルーチン例では、それぞれ複数の Command byte を送っていますが、それらの Command byte の意味を理解するには、SSD1306 データシートの 9 COMMAND TABLE (P 28/59)、および 10 COMMAND DESCRIPTIONS (P 34/59) を、 熟読してください(当然ながら英文ですが・・・)。

| プログラムのトップに戻る |

 ◎ OLED モジュール ( SSD1306 ) 制御サブルーチン

 次に示す緑色リストのサブルーチン群は、SSD1306 データシートの 9 COMMAND TABLE (P 28/59) の中から、本機 "201. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー II" の、 プログラムを作成するために必要となるコマンドに限ってを、いくつか選択してサブルーチン集として私がまとめ上げたものです。

 このサブルーチン集を動作させるためには、他にも、次リストの冒頭部分のコメントで述べているように、I2C インタフェース用の外部ルーチン (I2C_XS.sub) や、外部テーブル (Font5x7.tbl) 等が必要になりますが、 それらは 現在の最新プログラムバージョン に収録をしてありますので、そちらを参照してみてください。
      ;<使用外部ルーチン>
      
      ;(i2c_start, i2c_stop, i2c_byte_send, i2c_ack, i2c_nack)
      
      		:
      		:
      
      ;<使用テーブル>
      
      ;font5x7_data_tbl(外部テーブル: Font5x7.tbl)
      ;font10x14_data_tbl
      
 なお、I2C インタフェース用の外部ルーチン (I2C_XS.sub) については、"189. ドットマトリクス 8 x 8 LED 表示時計 II ( MAX7219 版)" の リアルタイムクロックモジュールのプログラミング でもリストを示して触れているので、そちらも参照してみてください。

 また、文字フォント(10 x 14)データテーブル(font10x14_data_tbl)については、そのサイズが大きくなるために、本機で必要となるフォントデータだけを作成して、本機のソースプログラム (PerpetualCalendarII.asm) 中の、プログラムメモリ (Page 3) 部分に収録がしてあるので、"font10x14_data_tbl" または "(Page 3)" で検索をしてください。
      ;==========================================================================
      ;	OLED モジュール ( SSD1306 ) 制御サブルーチン
      ;==========================================================================
      
      ;<使用外部ルーチン>
      
      ;(i2c_start, i2c_stop, i2c_byte_send, i2c_ack, i2c_nack)
      
      ;<使用レジスタ>
      
      ;pagex						;表示開始ページ
      ;end_pagex					;表示終了ページ
      ;column						;表示開始カラム
      ;end_column					;表示終了カラム
      ;pattern					;水平ビット位置,垂直パターン,ワーク
      ;echr_flg					;表示文字の機能拡張フラグ
      ;
      ;oled_lpcnt					;ループカウンタ
      
      ;<使用テーブル>
      
      ;font5x7_data_tbl(外部テーブル: Font5x7.tbl)
      ;font10x14_data_tbl
      
      ;==========================================================================
      ;		定数の定義
      ;==========================================================================
      
      SSD1306_Addr	equ	h'3c'			;OLED モジュール ( SSD1306 ) のスレーブアドレス
      
      ;==========================================================================
      ;		マクロ命令定義
      ;==========================================================================
      
      ;		OLED_FontPos_M マクロ		;フォントの表示開始位置指定
      
      OLED_FontPos_M	macro	@col,@row
      		movlw	@col			;
      		movwf	column			;表示カラム
      		movlw	@row			;
      		movwf	pagex			;表示ページ
      		call	SSD1306_FontPos		;表示開始位置指定
      		endm
      
      ;		OLED_DispStr_M マクロ		;キャラクタ (横:6 x 縦:8) 文字列の表示
      
      OLED_DispStr_M	macro	@str_adr,@x
      	#if 	@x != 0
      		movlw	high @str_adr		;文字列の先頭 high アドレス
      		movwf	FSR0H			;
      		movlw	low @str_adr		;文字列の先頭 low アドレス
      		movwf	FSR0L			;
      	#endif
      		call	SSD1306_DispStr		;文字列データ1行表示
      		endm
      
      ;		OLED_DispStr2_M マクロ		;キャラクタ (横:12 x 縦:16) 文字列の表示
      
      OLED_DispStr2_M	macro	@str_adr,@x
      	#if 	@x != 0
      		movlw	high @str_adr		;文字列の先頭 high アドレス
      		movwf	FSR0H			;
      		movlw	low @str_adr		;文字列の先頭 low アドレス
      		movwf	FSR0L			;
      	#endif
      		call	SSD1306_DispStr2	;文字列データ1行表示
      		endm
      
      ;		OLED_Line_H_M マクロ		;水平線表示
      
      OLED_Line_H_M	macro	@col_st,@col_sp,@row,@ptn
      		movlw	@col_st			;
      		movwf	column			;表示開始カラム
      		movlw	@col_sp			;
      		movwf	end_column		;表示終了カラム
      		movlw	@row			;
      		movwf	pagex			;表示ページ
      		movlw	@ptn			;
      		movwf	pattern			;ビット位置
      		call	SSD1306_Line_H		;モジュールの水平線表示
      		endm
      
      ;		OLED_Line_V_M マクロ		;垂直線表示
      
      OLED_Line_V_M	macro	@col,@row_st,@row_sp,@ptn
      		movlw	@col			;
      		movwf	column			;表示カラム
      		movlw	@row_st			;
      		movwf	pagex			;表示開始ページ
      		movlw	@row_sp			;
      		movwf	end_pagex		;表示終了ページ
      		movlw	@ptn			;
      		movwf	pattern			;垂直パターン
      		call	SSD1306_Line_V		;モジュールの垂直線表示
      		endm
      
      ;==========================================================================
      ;		フォントの表示開始位置指定
      ;==========================================================================
      
      ;入力レジスタ:	pagex:		表示ページ
      ;		column:		表示カラム
      
      SSD1306_FontPos
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'00'			;Control byte Co=0, D/C#=0
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'20'			;Set Memory Addressing Mode
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'02'			;Page Addressing Mode
      		call	i2c_byte_send		;1 バイト送信
      
      		movf	pagex,W
      		addlw	h'b0'			;Set Page Start Addrss for Page Addressing Mode
      		call	i2c_byte_send		;1 バイト送信(ページ開始アドレスの設定)
      		movf	column,W
      		andlw	h'0f'			;Set Lower Column Start Address for Page Addressing Mode
      		call	i2c_byte_send		;1 バイト送信(カラム開始アドレスの下位ニブル)
      		swapf	column,W
      		andlw	h'0f'
      		addlw	h'10'			;Set Higher Column Start Address for Page Addressing Mode
      		call	i2c_byte_send		;1 バイト送信(カラム開始アドレスの上位ニブル)
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;==========================================================================
      ;		キャラクタ (横:6 x 縦:8) 文字の表示
      ;==========================================================================
      
      ;入力レジスタ:	W reg:		表示する文字コード (h'20'〜h'df')
      
      ;		echr_flg:	表示文字の機能拡張フラグ	;(Ver.1.01にて追加)
      ;				bit7: ビット反転表示指示
      ;				bit6: 1 bit 左(下)ずらし指示
      
      ;使用レジスタ:	oled_lpcnt, pattern, FSR1H:FSR1L
      
      ;使用テーブル:	font5x7_data_tbl(外部テーブル: Font5x7.tbl)
      
      SSD1306_DispChr
      		movwf	FSR1L			;表示する文字コード
      		clrf	FSR1H
      
      		movlw	h'20'			;h'20'がテーブルの先頭位置
      		subwf	FSR1L,F
      		movf	FSR1L,W			;W に一時退避
      
      		lslf	FSR1L,F			;x2
      		rlf	FSR1H,F
      		lslf	FSR1L,F			;x4
      		rlf	FSR1H,F
      		addwf	FSR1L,F			;x5 ... 退避した W を足す
      		clrw
      		addwfc	FSR1H,F			;C フラグを足す
      
      		movlw	low font5x7_data_tbl	;フォントテーブルデータの先頭 low アドレス
      		addwf	FSR1L,F			;
      		movlw	high font5x7_data_tbl	;フォントテーブルデータの先頭 high アドレス
      		addwfc	FSR1H,F			;
      ;
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'40'			;Control byte Co=0, D/C#=1
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	5			;
      		movwf	oled_lpcnt		;ループカウンタ
      
      dspchr1		call	oledtbl_read		;テーブルデータの読み出し
      		movwf	pattern			;ワークに一時退避
      		movlp	high $			;この場所の high アドレス
      
      		btfss	echr_flg,7		;ビット反転表示指示 か?
      		goto	dspchr2			;No
      
      		movlw	h'7f'
      		xorwf	pattern,F		;ビット反転
      
      dspchr2		btfsc	echr_flg,6		;1 bit 左(下)ずらし指示 か?
      		lslf	pattern,F		;Yes
      
      		movf	pattern,W		;ワーク
      		call	i2c_byte_send		;1 バイト送信
      
      		addfsr	FSR1,1			;間接アドレス FSR1H:FSR1L + 1
      		decfsz	oled_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	dspchr1			;No
      
      		clrw				;文字間 h'00' 1 バイト追加
      		btfsc	echr_flg,7		;ビット反転表示指示 か?
      		movlw	h'7f'			;Yes. ビット反転
      
      		btfss	echr_flg,6		;1 bit 左(下)ずらし指示 か?
      		goto	dspchr3			;No
      
      		movwf	pattern			;ワーク
      		lslf	pattern,W		;
      
      dspchr3		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;==========================================================================
      ;		キャラクタ (横:6 x 縦:8) 文字列の表示
      ;==========================================================================
      
      ;入力レジスタ:	FSR0H:FSR0L:	文字列の先頭アドレス
      
      ;<使用例>	movlw	high title_msg		;文字列の先頭 high アドレス
      ;		movwf	FSR0H			;
      ;		movlw	low title_msg		;文字列の先頭 low アドレス
      ;		movwf	FSR0L			;
      ;		call	SSD1306_DispStr		;文字列データ1行表示
      ;		  :
      ;title_msg	dt	"Perpetual Calendar",0
      
      SSD1306_DispStr
      dspstr1		call	str_read		;文字列データの読み出し
      		movlp	high $			;この場所の high アドレス
      		addfsr	FSR0,1			;間接アドレス FSR0H:FSR0L + 1
      
      		addlw	0
      		btfsc	STATUS,Z		;文字列の終了(h'00') か?
      		goto	dspstr2			;Yes
      
      		call	SSD1306_DispChr		;OLED へデータを1文字出力
      		goto	dspstr1
      
      dspstr2		return
      
      		; テーブルデータの1文字読み出し
      str_read
      		movf	FSR0H,W			;読み出すデータの high アドレス
      		movwf	PCLATH
      		movf	FSR0L,W			;読み出すデータの low アドレス
      		movwf	PCL
      
      ;==========================================================================
      ;		キャラクタ (横:12 x 縦:16) 文字の表示
      ;==========================================================================
      
      ;入力レジスタ:	W: 表示する文字コード (h'2f'(/), h'30'(0) 〜 h'39'(9), h'3a'(:))
      
      ;		echr_flg:	表示文字の機能拡張フラグ	;(Ver.1.01にて追加)
      ;				bit7: ビット反転表示指示
      
      ;使用レジスタ:	oled_lpcnt, pattern, FSR1H:FSR1L
      
      ;使用テーブル:	font10x14_data_tbl
      
      SSD1306_DispChr2
      		movwf	FSR1L			;表示する文字コード
      		clrf	FSR1H
      
      		movlw	h'2f'			;h'2f'がテーブルの先頭位置
      		subwf	FSR1L,F
      
      		lslf	FSR1L,F			;x2
      		rlf	FSR1H,F
      		lslf	FSR1L,F			;x4
      		rlf	FSR1H,F
      		movf	FSR1L,W			;W に一時退避
      		lslf	FSR1L,F			;x8
      		rlf	FSR1H,F
      		lslf	FSR1L,F			;x16
      		rlf	FSR1H,F
      
      		addwf	FSR1L,F			;x20 ... 退避した W を足す
      		clrw
      		addwfc	FSR1H,F			;C フラグを足す
      
      		movlw	low font10x14_data_tbl	;フォントテーブルデータの先頭 low アドレス
      		addwf	FSR1L,F			;
      		movlw	high font10x14_data_tbl	;フォントテーブルデータの先頭 high アドレス
      		addwfc	FSR1H,F			;
      
      SSD1306_DispChr2s
      		call	dsp2chr0		;文字の上位半分の表示
      ;
      		incf	pagex,F			;文字の下位半分の表示位置
      		call	SSD1306_FontPos		;フォントの表示開始位置指定
      
      dsp2chr0	call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'40'			;Control byte Co=0, D/C#=1
      		call	i2c_byte_send		;1 バイト送信
      
      		clrw				;文字間 h'00' 1 バイト追加
      		btfsc	echr_flg,7		;ビット反転表示指示 か?
      		movlw	h'ff'			;Yes. ビット反転
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	10			;
      		movwf	oled_lpcnt		;ループカウンタ
      
      dsp2chr1	call	oledtbl_read		;テーブルデータの読み出し
      		movwf	pattern			;ワークに一時退避
      		movlp	high $			;この場所の high アドレス
      
      		btfss	echr_flg,7		;ビット反転表示指示 か?
      		goto	dsp2chr2		;No
      
      		movlw	h'ff'
      		xorwf	pattern,F		;ビット反転
      
      dsp2chr2	movf	pattern,W		;ワーク
      		call	i2c_byte_send		;1 バイト送信
      
      		addfsr	FSR1,1			;間接アドレス FSR1H:FSR1L + 1
      		decfsz	oled_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	dsp2chr1		;No
      
      		clrw				;文字間 h'00' 1 バイト追加
      		btfsc	echr_flg,7		;ビット反転表示指示 か?
      		movlw	h'ff'			;Yes. ビット反転
      		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;==========================================================================
      ;		キャラクタ (横:12 x 縦:16) 文字列の表示
      ;==========================================================================
      
      ;入力レジスタ:	FSR0H:FSR0L:	文字列の先頭アドレス
      
      ;<使用例>	movlw	high date_msg		;文字列の先頭 high アドレス
      ;		movwf	FSR0H			;
      ;		movlw	low date_msg		;文字列の先頭 low アドレス
      ;		movwf	FSR0L			;
      ;		call	SSD1306_DispStr2	;文字列データ1行表示
      ;		  :
      ;date_msg	dt	"2024/12/02",0
      
      SSD1306_DispStr2
      dsp2str1	call	str_read		;文字列データの読み出し
      		movlp	high $			;この場所の high アドレス
      		addfsr	FSR0,1			;間接アドレス FSR0H:FSR0L + 1
      
      		addlw	0
      		btfsc	STATUS,Z		;文字列の終了(h'00') か?
      		goto	dsp2str2		;Yes
      
      		call	SSD1306_DispChr2	;OLED へデータを1文字出力
      
      		decf	pagex,F			;文字の上位半分の表示位置に戻す
      		movlw	12
      		addwf	column,F		;カラム位置の更新
      		call	SSD1306_FontPos		;次文字の表示位置
      		goto	dsp2str1
      
      dsp2str2	return
      
      ;==========================================================================
      ;		OLED ( SSD1306 ) モジュールの水平線表示
      ;==========================================================================
      
      ;入力レジスタ:	pagex:		表示ページ
      ;		column:		表示開始カラム
      ;		end_column:	表示終了カラム
      ;		pattern:	ビット位置: h'01', h'02', h'04', h'08', h'10', h'20', h'40', h'80'
      
      ;使用レジスタ:	oled_lpcnt:	ループカウンタ
      
      SSD1306_Line_H
      		call	SSD1306_FontPos		;表示開始位置の指定
      
      		movf	column,W		;表示開始カラム
      		subwf	end_column,W		;表示終了カラム
      		addlw	1
      		movwf	oled_lpcnt		;ループカウンタ
      ;
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'40'			;Control byte Co=0, D/C#=1
      		call	i2c_byte_send		;1 バイト送信
      
      oled_lh1	movf	pattern,W		;
      		call	i2c_byte_send		;1 バイト送信
      
      		decfsz	oled_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	oled_lh1		;No
      
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;==========================================================================
      ;		OLED ( SSD1306 ) モジュールの垂直線表示
      ;==========================================================================
      
      ;入力レジスタ:	pagex:		表示開始ページ
      ;		end_pagex:	表示終了ページ
      ;		column:		表示カラム
      ;		pattern:	垂直パターン: h'00' 〜 h'ff'
      
      ;使用レジスタ:	oled_lpcnt:	ループカウンタ
      
      SSD1306_Line_V
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'00'			;Control byte Co=0, D/C#=0
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'20'			;Set Memory Addressing Mode
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'01'			;Vertical Addressing Mode
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	h'21'			;Set Column Address カラムアドレスの設定
      		call	i2c_byte_send		;1 バイト送信
      		movf	column,W		;Column start address, range: 0-127
      		call	i2c_byte_send		;1 バイト送信
      		movf	column,W		;Column end address, range: 0-127
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	h'22'			;Set Page Address ページアドレスの設定
      		call	i2c_byte_send		;1 バイト送信
      		movf	pagex,W			;Page start Address, range: 0-7
      		call	i2c_byte_send		;1 バイト送信
      		movf	end_pagex,W		;Page end Address, range: 0-7
      		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      ;
      		movf	pagex,W			;表示開始ページ
      		subwf	end_pagex,W		;表示終了ページ
      		addlw	1
      		movwf	oled_lpcnt		;ループカウンタ
      
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'40'			;Control byte Co=0, D/C#=1
      		call	i2c_byte_send		;1 バイト送信
      
      oled_lv1	movf	pattern,W		;
      		call	i2c_byte_send		;1 バイト送信
      
      		decfsz	oled_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	oled_lv1		;No
      
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;==========================================================================
      ;		OLED ( SSD1306 ) モジュールの画面消去
      ;==========================================================================
      
      ;使用レジスタ:	oled_lpcnt, FSR1H:FSR1L
      
      SSD1306_Clear
      		movlw	high ssd1306_clear_table ;テーブルデータの先頭 high アドレス
      		movwf	FSR1H			;
      		movlw	low ssd1306_clear_table	;テーブルデータの先頭 low アドレス
      		movwf	FSR1L			;
      		movlw	ssd1306_clear_table_end - ssd1306_clear_table
      		movwf	oled_lpcnt		;ループカウンタ
      		call	oledini00		;(SSD1306_Init 内)
      ;
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'40'			;Control byte Co=0, D/C#=1
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	high (128 * 8)		;128culomn * 8page
      		movwf	FSR1H
      		movlw	low (128 * 8)
      		movwf	FSR1L			;ループカウンタ
      
      oledclr01	clrw				;h'00'
      		call	i2c_byte_send		;1 バイト送信
      		addfsr	FSR1,-1			;ループカウンタ - 1
      
      		movf	FSR1H,W			;
      		iorwf	FSR1L,W			;
      		btfss	STATUS,Z		;FSR1H = FSR1L = h'00' か?	
      		goto	oledclr01		;No
      
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;--------------------------------------------------------------------------
      
      ;		OLED ( SSD1306 ) の画面消去用コマンドデータ・テーブル
      
      ssd1306_clear_table
      		dt	SSD1306_Addr << 1	;スレーブアドレス
      		dt	h'00'			;Control byte Co=0, D/C#=0
      
      		dt	h'20'			;Set Memory Addressing Mode
      		dt	h'00'			;Horizontal Addressing Mode
      
      		dt	h'21'			;Set Column Address カラムアドレスの設定
      		dt	0			;Column start address, range: 0-127
      		dt	127			;Column end address,   range: 0-127
      
      		dt	h'22'			;Set Page Address ページアドレスの設定
      		dt	0			;Page start Address, range: 0-7
      		dt	7			;Page end Address,   range: 0-7
      ssd1306_clear_table_end
      
      ;==========================================================================
      ;		OLED ( SSD1306 ) モジュールの初期設定
      ;==========================================================================
      
      ;使用レジスタ:	oled_lpcnt, FSR1H:FSR1L
      
      SSD1306_Init
      		movlw	high ssd1306_init_table	;テーブルデータの先頭 high アドレス
      		movwf	FSR1H			;
      		movlw	low ssd1306_init_table	;テーブルデータの先頭 low アドレス
      		movwf	FSR1L			;
      		movlw	ssd1306_init_table_end - ssd1306_init_table
      		movwf	oled_lpcnt		;ループカウンタ
      
      oledini00	call	i2c_start		;スタートコンディション
      
      oledini01	call	oledtbl_read		;テーブルデータの読み出し
      		call	i2c_byte_send		;1 バイト送信
      
      		addfsr	FSR1,1			;間接アドレス FSR1H:FSR1L + 1
      		decfsz	oled_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	oledini01		;No
      
      		call	i2c_stop		;ストップコンディション
      		return
      
      		; テーブルデータの1文字読み出し
      oledtbl_read
      		movf	FSR1H,W			;読み出すデータの high アドレス
      		movwf	PCLATH
      		movf	FSR1L,W			;読み出すデータの low アドレス
      		movwf	PCL
      
      ;--------------------------------------------------------------------------
      
      ;		OLED ( SSD1306 ) の初期設定用コマンドデータ・テーブル
      
      ssd1306_init_table
      		dt	SSD1306_Addr << 1	;スレーブアドレス
      		dt	h'00'			;Control byte Co=0, D/C#=0
      
      		dt	h'a8'			;Set Multiplex Ratio
      		dt	h'3f'	;h'00'- h'3f'	;
      
      		dt	h'd3'			;Set Display Offset
      		dt	h'00'	;h'00'- h'3f'	;
      
      		dt	h'40'	;h'40'- h'7f'	;Set Display Start Line
      
      		dt	h'a1'	;h'a0'/ h'a1'	;Set Segment Re-map, 左右反転
      
      		dt	h'c8'	;h'c0'/ h'c8'	;Set COM Output Scan Direction, 上下反転
      
      		dt	h'da'			;Set COM Pins Hardware Configuration
      		dt	h'12'	;h'02'- h'32'	;
      
      		dt	h'81'			;Set Contrast Control
      		dt	h'7f'	;h'00'- h'ff'	;コントラスト
      
      		dt	h'a4'	;h'a4'/ h'a5'	;Disable Entire Display On
      
      		dt	h'a6'	;h'a6'/ h'a7'	;Set Normal Display, 白黒反転
      
      		dt	h'd5'			;Set Osc Frequency
      		dt	h'80'	;h'00'- h'ff'	;
      
      		dt	h'8d'			;Enable Charge Pump Regulator
      		dt	h'14'	;h'04'/ h'14'	;
      
      		dt	h'af'	;h'ae'/ h'af'	;Display On, h'ae':OFF / h'af':ON
      ssd1306_init_table_end
      
      ;==========================================================================
      ;		OLED ( SSD1306 ) の Display ON/OFF 制御
      ;==========================================================================
      
      ;入力レジスタ:	W reg:	コマンドデータ h'af':ON / h'ae':OFF
      
      ;使用レジスタ:	pattern: ワーク
      
      SSD1306_DispOnOff
      		movwf	pattern			;ワークに一時退避
      
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'80'			;Control byte Co=1, D/C#=0
      		call	i2c_byte_send		;1 バイト送信
      
      		movf	pattern,W		;コマンドデータを復帰
      		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;==========================================================================
      ;		OLED ( SSD1306 ) の コントラスト制御
      ;==========================================================================
      
      ;入力レジスタ:	W reg:	コマンドデータ h'00'- h'ff'
      
      ;使用レジスタ:	pattern: ワーク
      
      SSD1306_Contrast
      		movwf	pattern			;ワークに一時退避
      
      		call	i2c_start		;スタートコンディション
      		movlw	SSD1306_Addr << 1	;スレーブアドレス
      		call	i2c_byte_send		;1 バイト送信
      		movlw	h'00'			;Control byte Co=0, D/C#=0
      		call	i2c_byte_send		;1 バイト送信
      
      		movlw	h'81'			;Set Contrast Control
      		call	i2c_byte_send		;1 バイト送信
      
      		movf	pattern,W		;コマンドデータを復帰
      		call	i2c_byte_send		;1 バイト送信
      		call	i2c_stop		;ストップコンディション
      		return
      
      ;=============================================================== end ======
      
 なお、余談ですが、上リストの OLED モジュール ( SSD1306 ) 制御サブルーチンの中で、変数の表示ページが pagex と定義されているのは、本来 page としたいのですが page がアセンブラ命令で予約語となっていて使用できないため、 仕方なく x を付して pagex と定義しました。

| プログラムのトップに戻る |

 ◎ OLED モジュール ( SSD1306 ) 制御サブルーチンの使用例

 前項の OLED モジュール ( SSD1306 ) 制御サブルーチンを、実際に使用した例を次に示します。 本機が NORMAL モード、または LARGE モードのときに、MODE / SET スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、 ディスプレイ画面右下のメッセージエリアに、" SET MODE " と文字列のビット反転表示がされますが、そのときに使用される SET モードメッセージの表示 (setmode_display) サブルーチン の例を取り上げてみました。
      ;		SET モードメッセージの表示
      
      setmode_display
      		OLED_FontPos_M	4+6*10,7	;表示開始位置の指定
      		movlw	h'c0'			;h'c0': ビット反転表示とビットずらし指示
      		movwf	echr_flg		;
      		OLED_DispStr_M	setmode_msg,1	;メッセージ文字列の表示
      		bcf	echr_flg,7		;ビット反転表示指示解除
      		return
      
      setmode_msg	dt	" SET MODE ",0
      
 このように、数行の命令群でサブルーチンを書くことができます。 この例では OLED_FontPos_M と OLED_DispStr_M の、2つのマクロ命令を使用しているためで、これらのマクロ命令は、MPLAB X IDE v5.35 を実行するとアセンブラ MPASM によって、次リストのようにマクロ展開(LINE 欄が M 表記の行)が行われます。
      LOC  OBJECT CODE     LINE SOURCE TEXT
        VALUE
                            02276 
                            02277 ;               SET モードメッセージの表示
                            02278 
      0521                  02279 setmode_display
                            02280                 OLED_FontPos_M  4+6*10,7        ;表示開始位置の指定
      0521   3040               M                 movlw   4+6*10                  ;
      0522   00E3               M                 movwf   column                  ;表示カラム
      0523   3007               M                 movlw   7                       ;
      0524   00E1               M                 movwf   pagex                   ;表示ページ
      0525   2???               M                 call    SSD1306_FontPos         ;表示開始位置指定
      0526   30C0           02281                 movlw   h'c0'                   ;h'c0': ビット反転表示とビットずらし指示
      0527   00E6           02282                 movwf   echr_flg                ;
                            02283                 OLED_DispStr_M  setmode_msg,1   ;メッセージ文字列の表示
                                M         #if     1  != 0
      0528   30??               M                 movlw   high setmode_msg        ;文字列の先頭 high アドレス
      0529   0085               M                 movwf   FSR0H                   ;
      052A   30??               M                 movlw   low setmode_msg         ;文字列の先頭 low アドレス
      052B   0084               M                 movwf   FSR0L                   ;
                                M         #endif
      052C   2???               M                 call    SSD1306_DispStr         ;文字列データ1行表示
      052D   13E6           02284                 bcf     echr_flg,7              ;ビット反転表示指示解除
      052E   0008           02285                 return
                            02286 
      052F   3420 3453 3445 02287 setmode_msg     dt      " SET MODE ",0
             3454 3420 344D 
             344F 3444 3445 
             3420 3400 
                            02288 
      
 1つ目の OLED_FontPos_M マクロ命令 で、メッセージ文字列の表示開始位置を指定した後、ビット反転表示指示とビットずらし指示をしながら、2つ目の OLED_DispStr_M マクロ命令 で、メッセージ文字列の1行分を表示しています。

 これらのマクロ命令では、実際には、それぞれに決められている引数を各変数に引き渡した後、フォントの表示開始位置指定 (SSD1306_FontPos) サブルーチン や、キャラクタ (横:6 x 縦:8) 文字列の表示 (SSD1306_DispStr) サブルーチン が実行されます。 なお、SSD1306_DispStr サブルーチン内では、キャラクタ (横:6 x 縦:8) 文字の表示 (SSD1306_DispChr) サブルーチン が、文字列の文字数だけ繰り返し CALL されています。

 ここに示した SET モードメッセージの表示 (setmode_display) サブルーチン の使用例を理解するためには、前項で示した緑色リストの OLED モジュール ( SSD1306 ) 制御サブルーチン 内に書かれてある、OLED_FontPos_M マクロ、OLED_DispStr_M マクロ、SSD1306_FontPos サブルーチン、SSD1306_DispChr サブルーチン、SSD1306_DispStr サブルーチンを理解する必要があります。

| プログラムのトップに戻る |

● アセンブルリスト ( PerpetualCalendarII.lst ) について

 下に示したリストは、本機のソースプログラムファイル (PerpetualCalendarII.asm) を入力として、MPLAB X IDE v5.35 を実行したときに、アセンブラ MPASM によって、実際に吐き出されたアセンブルリスト (PerpetualCalendarII.lst) の、 ほんの一部分だけを抜粋したリストですが、随所に文字化けを起こしているのが確認できます。

 本機のソースプログラム内では、3本のサブルーチンファイルを include していますが、その内の OLED モジュール制御サブルーチンファイル (OLED_SSD1306.sub) 部分 だけと、そのファイル内で定義されているマクロ命令を、ソースプログラム内で使用して アセンブラ MPASM によって展開された部分 だけが、文字化けを起こしています。

 下のリストでは、OLED_SSD1306.sub ファイルを include して、その中の冒頭部分、OLED_FontPos_M マクロ、SSD1306_FontPos サブルーチンと、そして、実際に OLED_FontPos_M マクロを使用している部分の一例だけを抜粋してあります。 (現在の最新プログラムバージョン には、参考として全リストを収録してあります)

 私は以前から、各種のプログラムファイルやサブルーチンファイルを作成するのに、メモ帳を愛用していますが、それらを 単体ファイルとして見た場合には、メモ帳はもちろん Microsoft Edge などのブラウザで閲覧した場合にも、何ら文字化けを起こすことはなく ごく普通に見えています。

 ところが、MPASM によってソースプログラム内に include され、アセンブルリストになると文字化けを起こしてしまいます。 これは MPASM 自体に問題があるのでしょうか? それとも、OLED モジュール制御サブルーチンファイル (OLED_SSD1306.sub) 内に、化けるような異常なコードが含まれているのでしょうか?

 下のリスト内で実際に文字化けを起こしているのは、コメント部分に書かれている漢字部分(2バイト文字)だけなので、生成されるオブジェクトファイルには実害はないと思いますが、アセンブルリストを見たときには気持ちが良いものではありません。
      				:
      				:
      				:
                            00856                 include         C:\Data\Project\PIC\_sub\OLED_SSD1306.sub
                            00001 ;***** OLED_SSD1306.sub ***************************************************
                            00002 ;
                            00003 ;       OLED 繝「繧ク繝・繝シ繝ォ ( SSD1306 ) 蛻カ蠕。繧オ繝悶Ν繝シ繝√Φ
                            00004 ;
                            00005 ;       (SSD1306_FontPos, SSD1306_DispChr,  SSD1306_DispStr, )
                            00006 ;       (                 SSD1306_DispChr2, SSD1306_DispStr2,)
                            00007 ;       (SSD1306_Line_H, SSD1306_Line_V, SSD1306_Clear, SSD1306_Init,)
                            00008 ;       (SSD1306_DispOnOff, SSD1306_Contrast)
                            00009 ;
                            00010 ;       Copyright (C) 2024   by M.Yamamoto. All rights reserved.
                            00011 ;
                            00012 ;       Homepage URL: https://xyama.sakura.ne.jp/hp/PerpetualCalendarII.html
                            00013 ;
                            00014 ;     ( coding:  Ver. 0.00   2024/11/20  by M.Yamamoto )
                            00015 ;       coding:  Ver. 1.00   2024/12/02  蝓コ譛ャ繧オ繝悶Ν繝シ繝√Φ縺ョ菴懈・
                            00016 ;       update:  Ver. 1.01   2024/12/05  SSD1306_DispChr,SSD1306_DispChr2縺ョ讖溯・諡。蠑オ
                            00017 ;       update:  Ver. 1.02   2024/12/18  SSD1306_FontPos繧貞、画峩
                            00018 ;       update:  Ver. 1.03   2024/12/21  SSD1306_DispChr2繧貞、画峩
                            00019 ;       update:  Ver. 1.04   2024/12/28  SSD1306_DispOnOff,SSD1306_Contrast繧定ソス蜉
                            00020 ;       bugfix:  
                            00021 ;
                            00022 ;******************************************************* PicAsm 0269 ******
                            00023 
                            00024 ;<菴ソ逕ィ螟夜Κ繝ォ繝シ繝√Φ>
                            00025 
                            00026 ;(i2c_start, i2c_stop, i2c_byte_send, i2c_ack, i2c_nack)
                            00027 
                            00028 ;<菴ソ逕ィ繝ャ繧ク繧ケ繧ソ>
                            00029 
                            00030 ;pagex                                          ;陦ィ遉コ髢句ァ九・繝シ繧ク
                            00031 ;end_pagex                                      ;陦ィ遉コ邨ゆコ・・繝シ繧ク
                            00032 ;column                                         ;陦ィ遉コ髢句ァ九き繝ゥ繝
                            00033 ;end_column                                     ;陦ィ遉コ邨ゆコ・き繝ゥ繝
                            00034 ;pattern                                        ;豌エ蟷ウ繝薙ャ繝井ス咲スョ,蝙ら峩繝代ち繝シ繝ウ,繝ッ繝シ繧ッ
                            00035 ;echr_flg                                       ;陦ィ遉コ譁・ュ励・讖溯・諡。蠑オ繝輔Λ繧ー
                            00036 ;
                            00037 ;oled_lpcnt                                     ;繝ォ繝シ繝励き繧ヲ繝ウ繧ソ
                            00038 
                            00039 ;<菴ソ逕ィ繝・・繝悶Ν>
                            00040 
                            00041 ;font5x7_data_tbl・亥、夜Κ繝・・繝悶Ν: Font5x7.tbl・・
                            00042 ;font10x14_data_tbl
                            00043 
                            00044 ;==========================================================================
                            00045 ;               螳壽焚縺ョ螳夂セゥ
                            00046 ;==========================================================================
                            00047 
        0000003C            00048 SSD1306_Addr    equ     h'3c'                   ;OLED 繝「繧ク繝・繝シ繝ォ ( SSD1306 ) 縺ョ繧ケ繝ャ繝シ繝悶い繝峨
                                  Ξ繧ケ
                            00049 
                            00050 ;==========================================================================
                            00051 ;               繝槭け繝ュ蜻ス莉、螳夂セゥ
                            00052 ;==========================================================================
                            00053 
                            00054 ;               OLED_FontPos_M 繝槭け繝ュ                ;繝輔か繝ウ繝医・陦ィ遉コ髢句ァ倶ス咲スョ謖・ョ・
                            00055 
                            00056 OLED_FontPos_M  macro   @col,@row
                            00057                 movlw   @col                    ;
                            00058                 movwf   column                  ;陦ィ遉コ繧ォ繝ゥ繝
                            00059                 movlw   @row                    ;
                            00060                 movwf   pagex                   ;陦ィ遉コ繝壹・繧ク
                            00061                 call    SSD1306_FontPos         ;陦ィ遉コ髢句ァ倶ス咲スョ謖・ョ・
                            00062                 endm
                            00063 
      				:
      				:
      				:
                            00115 
                            00116 ;==========================================================================
                            00117 ;               繝輔か繝ウ繝医・陦ィ遉コ髢句ァ倶ス咲スョ謖・ョ・
                            00118 ;==========================================================================
                            00119 
                            00120 ;蜈・蜉帙Ξ繧ク繧ケ繧ソ:    pagex:          陦ィ遉コ繝壹・繧ク
                            00121 ;               column:         陦ィ遉コ繧ォ繝ゥ繝
                            00122 
      00CB                  00123 SSD1306_FontPos
      00CB   2???           00124                 call    i2c_start               ;繧ケ繧ソ繝シ繝医さ繝ウ繝・ぅ繧キ繝ァ繝ウ
      00CC   3078           00125                 movlw   SSD1306_Addr << 1       ;繧ケ繝ャ繝シ繝悶い繝峨Ξ繧ケ
      00CD   2???           00126                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。
      00CE   3000           00127                 movlw   h'00'                   ;Control byte Co=0, D/C#=0
      00CF   2???           00128                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。
      00D0   3020           00129                 movlw   h'20'                   ;Set Memory Addressing Mode
      00D1   2???           00130                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。
      00D2   3002           00131                 movlw   h'02'                   ;Page Addressing Mode
      00D3   2???           00132                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。
                            00133 
      00D4   0861           00134                 movf    pagex,W
      00D5   3EB0           00135                 addlw   h'b0'                   ;Set Page Start Addrss for Page Addressing Mode
      00D6   2???           00136                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。・医・繝シ繧ク髢句ァ九い繝峨Ξ繧ケ縺ョ險ュ螳
                                  夲シ・
      00D7   0863           00137                 movf    column,W
      00D8   390F           00138                 andlw   h'0f'                   ;Set Lower Column Start Address for Page Addressing Mode
      00D9   2???           00139                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。・医き繝ゥ繝髢句ァ九い繝峨Ξ繧ケ縺ョ荳倶ス
                                  阪ル繝悶Ν・・
      00DA   0E63           00140                 swapf   column,W
      00DB   390F           00141                 andlw   h'0f'
      00DC   3E10           00142                 addlw   h'10'                   ;Set Higher Column Start Address for Page Addressing Mod
                                  e
      00DD   2???           00143                 call    i2c_byte_send           ;1 繝舌う繝磯∽ソ。・医き繝ゥ繝髢句ァ九い繝峨Ξ繧ケ縺ョ荳贋ス
                                  阪ル繝悶Ν・・
      00DE   2???           00144                 call    i2c_stop                ;繧ケ繝医ャ繝励さ繝ウ繝・ぅ繧キ繝ァ繝ウ
      00DF   0008           00145                 return
                            00146 
      				:
      				:
      				:
                            02276 
                            02277 ;               SET モードメッセージの表示
                            02278 
      0521                  02279 setmode_display
                            02280                 OLED_FontPos_M  4+6*10,7        ;表示開始位置の指定
      0521   3040               M                 movlw   4+6*10                  ;
      0522   00E3               M                 movwf   column                  ;陦ィ遉コ繧ォ繝ゥ繝
      0523   3007               M                 movlw   7                       ;
      0524   00E1               M                 movwf   pagex                   ;陦ィ遉コ繝壹・繧ク
      0525   2???               M                 call    SSD1306_FontPos         ;陦ィ遉コ髢句ァ倶ス咲スョ謖・ョ・
      0526   30C0           02281                 movlw   h'c0'                   ;h'c0': ビット反転表示とビットずらし指示
      0527   00E6           02282                 movwf   echr_flg                ;
                            02283                 OLED_DispStr_M  setmode_msg,1   ;メッセージ文字列の表示
                                M         #if     1  != 0
      0528   30??               M                 movlw   high setmode_msg        ;譁・ュ怜・縺ョ蜈磯ュ high 繧「繝峨Ξ繧ケ
      0529   0085               M                 movwf   FSR0H                   ;
      052A   30??               M                 movlw   low setmode_msg         ;譁・ュ怜・縺ョ蜈磯ュ low 繧「繝峨Ξ繧ケ
      052B   0084               M                 movwf   FSR0L                   ;
                                M         #endif
      052C   2???               M                 call    SSD1306_DispStr         ;譁・ュ怜・繝・・繧ソ・題。瑚。ィ遉コ
      052D   13E6           02284                 bcf     echr_flg,7              ;ビット反転表示指示解除
      052E   0008           02285                 return
                            02286 
      052F   3420 3453 3445 02287 setmode_msg     dt      " SET MODE ",0
             3454 3420 344D 
             344F 3444 3445 
             3420 3400 
                            02288 
      				:
      				:
      				:
      
 このように、OLED モジュール制御サブルーチンファイル (OLED_SSD1306.sub) を include した場合だけに起こる現象で、他の2ファイルを include した場合には至って正常で、まったく文字化けなどは起きていません。 やはり、同ファイル内に異常なコードが含まれている ― としか思えないのですが ・・・

 * (その後、サーバ上にアップロードした (OLED_SSD1306.sub) を、Microsoft Edge で閲覧した場合にも文字化けを起こすことが分かりました。)

 そこで、この項をお読みになった方々にお願いがあります。 ファイル内に異常なコードが含まれているような場合に、どの文字が異常なのか、それを発見するにはどのようにすれば判るのか ― もしも、ご存じでしたらぜひともご教授ください。

(メールアドレスは、当サイトの トップページ(ホーム) の左上に表示の【 ご挨拶とお願い 】をクリックしていただけると、開いたページの最下行に表示がされています。)

| プログラムのトップに戻る |

現在の最新プログラムバージョン: Ver. 1.05

ソースファイル (PerpetualCalendarII.asm)
 I2C (SCLクロック周波数 = 100/400 KHz) サブルーチン(ソフトウエア I2C 版)(I2C_XS.sub) Ver. 1.04
 I2C RTC(DS3231/1307)モジュール 制御サブルーチン (I2C_RTCII.sub) Ver. 1.04
 OLED モジュール ( SSD1306 ) 制御サブルーチン (OLED_SSD1306.sub) Ver. 1.04 (文字化け有り)
 文字フォント(5 x 7)データテーブル (Font5x7.tbl)
HEX ファイル (PerpetualCalendarII.hex)
アセンブルリストファイル (PerpetualCalendarII.lst) (参考)

| ページトップ |

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

 使用したメインとなる下図 左側のプリント基板 は、"秋月電子" の "片面ガラスコンポジット・ユニバーサル基板 Bタイプ めっき仕上げ(95 x 72 mm)日本製 型番: AE-B2-CEM3(販売コード 103230)" ですが、後述の ケース加工図 で示したケース内に収めるためには、プリント基板の切断等の加工が必要です。 左図に示すように、まず基板下部の ----- X 線の位置で切断をします。

 そして、この切断によって失われた基板下部の取り付け用穴の代理となる、新たなΦ3.2 の穴を図のように2か所開けます。 次に、基板右端に位置するスイッチ用基板の取り付けのために用いる、 ジュラコンスペーサ用のΦ3.2 の穴を2か所開けます。


 次に 右側のプリント基板 は、"秋月電子" の "片面ガラス・ユニバーサル基板 Cタイプ(72 x 47.5 mm)めっき仕上げ(販売コード 100517)" で、左側メイン基板の右端に取り付けるスイッチ用基板になるもので、 他にコネクタ用の小基板2枚も切り出します。

 図の ----- 線に従って、Y1, Y2, X1, X2, X3, X4 の順に切断をします。 Y2 線よりも左側の大きな部分と、X3 線よりも下部分は余りで今回は使用しません。 図中の (A) 基板がスイッチ用基板で、2か所のΦ3.2 の穴を開けることも忘れないでください。 (B), (C) の小さな基板は、メイン基板との接続のためのコネクタ用に使用します。

| プリント基板部品配置図 (PerpetualCalendarIIPC0.CE3) | (PerpetualCalendarII2PC0.CE3) | ページトップ |

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

 メイン基板に多くのパーツを搭載するにあたっては、それぞれに対して以降に述べるような注意事項があるので、基板を組み立てる上での参考にしてください。 なお、図の中で、細長い長方形の中に ○で表したものはピンヘッダ(オス)を、同様に◎で表したものはピンソケット(メス)を使用することを表しているので、注意をしてください。


上図から黒文字を除去して表示

・RTC モジュール( DS3231 For PI )
 プリント基板の左上角に位置する小さな四角状のものが RTC モジュール( DS3231 For PI )で、本機では リアルタイムクロックモジュール( DS3231 For PI ) の項で説明をした改造が必要になります。 具体的には、"200. 6桁ニキシー管時計 III(IN-17)" の リアルタイムクロックモジュール( DS3231 For PI ) の項で詳述しているので、それに従って改造を行ってください。

 改造後の RTC モジュール( DS3231 For PI )の取り付けは、付け替えた 5P のピンヘッダとメイン基板とを、直接ハンダ付けをします。 また、上写真に写っている赤色線のように、RTC モジュール基板のコイン電池を取り外した跡の+側に接続してあるジャンパー線も、 メイン基板のコイン電池ホルダの+端子との接続を、忘れないように必ず行います。

・TP4056 充電モジュール
 プリント基板の左下に位置する "TP4056 充電モジュール" の取り付けについては、まず、縦横4か所の各青色線で示す位置の、メイン基板のハンダ面側から 0.4 〜 0.5 mm の錫メッキ線等を通し、モジュール基板上面側で各青色線の対となるもう片方の穴へグルっとUターンをして、 再び、メイン基板のハンダ面側に通した後はんだ付けをします。 このとき、モジュール基板側は 2.54 mm ピッチではないため注意が必要ですが、メイン基板側の穴位置は、前項 プリント基板の加工と部品配置 で示した縦横4か所の各青色線で示したランド穴位置を選択すれば問題はないでしょう。

 次に、モジュール基板左側の斜2か所の青色線で示すモジュール基板側の穴に対応するメイン基板側の位置には、ランド穴が開いていないのでこの位置にΦ1 程度の穴を開ける必要があり * ます。 穴を開けた後、前の縦横4か所のときと同要領で斜2か所についても、錫メッキ線等でモジュール基板の固定をします。 ただし、前の縦横4か所についてはその後、メイン基板のハンダ面側で回路の配線が必要になりますが、この斜2か所については回路の配線はありません。
      * モジュール基板のメーカーや、TP4056 リチウムイオン電池充電モジュール で述べた、Micro USB /タイプ C の USB コネクタの種類によっては、モジュール基板の穴位置が多少異なるため、 穴開けが不要な場合もあります。 私の場合にはメイン基板の左端を超えたため、穴を開けなくても錫メッキ線を通すことができました。
 また、この充電モジュールでバッテリに充電中には、充電制御 IC TP4056 がかなり発熱をするので、手持ちにあったヒートシンクを熱伝導シール(両面粘着)で貼り付けました。

・OLED モジュール
 プリント基板の上部中央には、本機の目玉である OLED モジュールが位置します。 メイン基板側にはあらかじめ 4P のピンソケットを取り付けておき、OLED モジュール側のピンヘッダと嵌合させます。 このとき、ピンソケットには分割ピンソケットを使用するとその加工が楽になります。

・トグルスイッチ
 プリント基板下部中央に位置する POWER スイッチには、3P(1回路)のトグルスイッチで良いのですが、3P でレバーが短いタイプが私の持ち合わせになく、6P(2回路)のものがあったので私は代わりにそれを使用しました。 したがって、3P でレバーが短いタイプを入手した場合には、基板パターン図を 3P(1回路)用に変更をしてください。

 本機では ケース加工図 で示したケース(内寸高さ 24 mm)を使用したため、レバーが通常のタイプは不可で、短いタイプでないとケース内に収めることができません。

 通常、本機のように時計関連の製作物には POWER スイッチ等は設けない場合が多いのですが、本機の場合には、18650 リチウムイオン電池を充電する場合には、TP4056 充電モジュールの負荷接続端子を開放しておく必要があるために、その目的でスイッチを設置しました。

・タクトスイッチ用基板との接続コネクタ
 プリント基板の右端縦長の位置に、タクトスイッチ用基板を取り付けますが、この基板の取り付けには、後述の ケースへのプリント基板の取り付け で説明しているように、私の場合には手持ちの関係で、 13 mm 長のオネジ+メネジの六角ジュラコンスペーサ(廣杉計器 BS-313W)を使用しました。

 そして、電気的な接続には、下の プリント基板(2)パターン図 (部品面) (ハンダ面) の項で示した、タクトスイッチ用基板のケーブルコネクタ( 6P ピンソケット(メス))と、メイン基板上に設けた 6P L型ピンヘッダとを、常時接続をさせておきます。 なお、メイン基板側のピンヘッダは、パターン図や写真のように L型でないと接続ができません。

・その他
 プリント基板左下の 3P のピンヘッダ B+ と B- 端子には、本機の電源である 18650 リチウムイオン電池を、電池ホルダからの配線( 3P ピンソケット(メス))を介して接続させます。 電気的には 2P で良いのですが、 2P 状態よりも 3P の方が、しっかりとコネクタ接続ができるために 3P としました。 そのため、真ん中のピンには配線はしていません。

| プリント基板パターン図 (部品面) (PerpetualCalendarIIPC.CE3) | 左図から黒色文字を除いた図 (PerpetualCalendarIIPC2.CE3) | ページトップ |

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

 前項 プリント基板パターン図 (部品面) でも述べたように、下パターン図や写真は、トグルスイッチに 3P(1回路)ではなく 6P(2回路)を使用したものなので、3P(1回路)トグルスイッチを使用した場合には、 スイッチ周りのパターンを適宜変更をしてください。


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

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

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

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

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

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

■ ケース加工図 ■

 本機のケースは、"秋月電子" の "ABS樹脂ケース(蝶番式・中)112−TS ニシムラ (販売コード: 100277)" を使用しました。 外側(内側)寸法が 117 (112) x 84 (80) x 28 (24) mm で、可動式のフタが付いています。


 上図の(上面図)及び(左側面図)において、各丸穴の位置寸法を記入* はしてありますが、参考程度に見ておいてください。 実際に穴開けを行う場合には、プリント基板を仮に取り付けた後、ケースが透明で中が透けて見えているので、 現物合わせで丸穴の中心位置を千枚通し等で印を付けて位置決めを行った方が、穴開けがうまくいくと思います。 ただし、(下面図)におけるプリント基板の取り付け用の穴位置は、極力、正確な位置に穴開けを行うように心掛けてください。
      * ユニバーサルプリント基板は 1/10 inch = 2.54 mm というサイズ単位で穴開けがされているため、5個のタクトスイッチのキートップ用の穴間隔は 10 mm ではなく、実際には 10.16 mm となる。
 また、圧電スピーカの音抜き用の穴間隔を、実際には 5 mm のところを間違えて、私は 10 mm 間隔で開けてしまいました。 まあ、あまり大きな問題ではありませんが(見栄えが悪くなる)、上の図寸法と実際の本機の 外観写真 とでは異なっているので注意をしてください。

・メイン基板の取り付け
 上図の(下面図)はケースの裏面側から見た図で、上部の大きな点線の四角部分(72 x 89 mm)がメイン基板の取り付け位置です。 私がプリント基板をケース等に取り付ける場合、通常、両者の間には 5 mm 長のスペーサを挟んで 取り付けることが多いのですが、本機のメイン基板には 5 mm 長のスペーサを使用することができません。

 上の プリント基板パターン図 (部品面) の項で、使用した トグルスイッチ について述べたように、本機ではレバーが短いタイプを使用していますが、メイン基板を上図のケース内に納めるためには 5 mm 長のスペーサでは長過ぎて、 上蓋が閉まらなくなってしまいます。 そこで本機では M3 のナットをスペーサ代わり、としました。 ウィルコ で購入したナットで、 "鉄(ニッケルめっき) 六角ナット・1種 FNT-03N" の厚さ 2.4 mm のものです。

 ケースの裏面側(外側)の4か所から、それぞれ M3 x 10 サイズのビス(+なべ小ねじ)を通し、ケース内側でスペーサ代わりの M3 ナット → メイン基板 → ポリカーボネート平ワッシャー → M3 ナット、の順に取り付けます。 ポリカーボネート平ワッシャーは、プリント基板表面の傷つき防止とねじ緩み防止を兼ねて挿入をしてあります。(ねじ類の型番等については、使用部品表 を参照のこと)

・電池ホルダーの取り付け
 同様に上図の(下面図)で、下部の横に細長い点線の四角部分に、18650 リチウムイオン電池用の電池ホルダーを取り付けます。 私が使用した電池ホルダー、およびその取り付けるときの注意点、方法などについては、 別ページ "198. MP3プレーヤー I" の 電池ホルダーをケースに取り付け を参考にしてください。

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

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

 下図は本機ケースの右側面側から上部半分ほどを見た図で、2枚のプリント基板やタクトスイッチの取り付けの様子がよく分かるように、右側面を切り取った断面図で表しています。

 ケースへのメイン基板の取り付けに当たって、最も重要なのはその上下(高さ)位置で、重複しますが上述した メイン基板の取り付け のように、本機ではトグルスイッチ搭載のために M3 のナットをスペーサ代わりとして使用しています。 そして、前項で述べたケースを使用する限り、この状態が最もベストな上下(高さ)位置で変更することはできません。

 また、同図に示すように本機では、スイッチ用プリント基板に取り付けたタクトスイッチのトップが、ケース上面から適度な長さ(X)を飛び出すようにしなければなりません。 そのために、タクトスイッチには手持ちにあった通常のものより少々長い、 スイッチ底面からトップまでの長さが 9.5mm のものを使用し、スイッチ用基板をメイン基板に取り付けるのに、これも手持ちの関係で右写真のような、M3 x 13 mm 長のオネジ+メネジの六角ジュラコンスペーサ(廣杉計器 BS-313W)を使用しました。

 余談ですが、タクトスイッチをプリント基板に取り付ける場合に、私は通常、スイッチを基板穴に軽く押し込んだときに、足ピンがくの字に曲がったあたりで進入が止まった位置、すなわち、スイッチ底面が少し基板上面から浮いた位置でハンダ付けをすることが多いのですが、 今回は上図のように、スイッチ底面が基板上面に付くまでスイッチを押し込んで使用しました。 これは使用したタクトスイッチとスペーサの各長さによって X 値を調節するためで、ちなみに図の組み合わせでは X ≒ 2 mm ほどになりました。

| 基板の取り付け図 (pcb_attach.CE3) | ページトップ |

■ 使用部品表 ■

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

(データシート)
PICマイコン .................... PIC16F1705
三端子レギュレータ .................... S-812C33AY-B-G
トランジスタ .................... 2SA1015
有機 EL ディスプレイ(OLED) .................... SSD1306
圧電ブザー .................... PKM17EPP-4001

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

■ 参考資料・参考サイト ■

PIC16F1705 データシート .......... https://ww1.microchip.com/downloads/en/DeviceDoc/40001729C.pdf
SSD1306 データシート .......... https://akizukidenshi.com/goodsaffix/ssd1306.pdf
174. グラフィック液晶表示 万年カレンダー .......... https://xyama.sakura.ne.jp/hp/PerpetualCalendar.html
有機EL (OLED)をPICマイコンで制御 .......... https://jr3tgs-homebrew.net/contents/oled_test/oled_test.html

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


Copyright (C) 2024-2025 やまもとみのる
初版:2024年12月10日、初公開:2025年2月16日、最終更新:2025年3月18日