PICでRTC62421Aを制御してみる
投稿日 2026年06月23日

PIC 16F887(40ピンDIP)とRTC62421A(18ピンDIP)
背景はEPSON社 RTC62421Aのアプリケーション・マニュアル
何をつくるのか
RTC62421Aはとっくの昔に製造中止で、今では入手しにくくなっているパラレルタイプのRTC(リアルタイム・クロック)です。今回はこれをPICマイコンで制御し、最終的にはデジタル時計に仕上げてみることにしました。また、これまでC言語を使うのが普通でしたが、今回はあえてアセンブラで作ってみることにしました。
使用するPICは16F887です、これまた古いPIC。開発環境はMicrochip MPLAB X IDE V6.20 XC8 pic-asアセンブラです。16F887を選んだ理由は、GPIOのピン数が36本と多く余裕があること。クロック発振器内蔵で使いやすいこと。アセンブラでプログラミングするので、すこし古いアーキテクチャのPICがふさわしいと思ったからでもあります。そして何より手持ちがあったことが理由です。MPLAB IDEを最新バージョンではなくV6.20を選んだ理由は、書き込み器のpickit3がサポートされている最終バージョンだからです。当局にはpickit3より新しい書き込み器はありません。このV6.20はすでに以前のアセンブラPICASMは使えず、pic-asとなっています。PICASMはほとんど使ったことが無いので、これからアセンブラをいじってみるにはpic-asの方がよいかと思います。
RTC62421Aを選んだ理由
RTC62421Aを選んだ理由は、これもたまたま手持ちがあったからですが、このRTCはパラレル・インターフェースなので昔ながらの8ビットマイコンとは相性がよいものです。アセンブラでSPIやI2Cをプログラミングするのは、できなくはないですがハードルが高いので、まずは比較的容易なパラレル接続がアセンブラ初心者にとっては助かります。そもそもRTC62421AはZ80や8085のようなマイコンに接続することを意識して設計されているので、PICとも相性がいいわけです。4ビットのアドレスバスと4ビットのデータバスの計8本のGPIOが必要です。ただし、今回も採用しましたがアドレスとデータバスを共通にして4本で済ませることもできます。
まとめると
〇RTC6241Aを採用:パラレル・インターフェイスで8ビットマイコンと相性が良い
〇PIC 16F887を採用:GPIO数が多くクロック発振器内蔵で使いやすい アセンブラで使うので機能/性能面でバランスがよい。
〇MPLAB X IDE V6.20を使用:puckit3サポートの最終バージョン
〇pic-asアセンブラを使用:MPLAB X IDEではPICASMは廃止されpic-asアセンブラがサポートされている
使用したパソコン環境はWindows 11です。電源電圧がPIC 16F887、RTC62421Aともに5Vです。

PIC 16F887とRTC62421Aで製作したデジタル時計
7SEG LEDやボタン類はMicrotechnikaのEasyPICを使用
書きこみ器はpickit3
ボタンで年月日、時刻の設定を行える
RTC62421AはどんなRTC?
まず、RTC62421Aはエプソンの製品ですが、OKIのMSM6242Bがベースになっているようです。今回使用したのは18ピンのDIPですが、ピン配置はMSM6242Bと互換性があります。スペックもざっくりみたところほとんど同じようです。セカンドソースと言ってよいでしょうか。前述のようにパラレル・インターフェイスのRTCです。32.768KHzの発振部を内蔵しているので外付けのXTALは不要です。年2桁、月、日、曜日、時、分、秒のレジスタと設定用を含め0x00から0x0Fまで4ビットのレジスタが計16個あります。データはBCDコードです。4ビットのアドレスバスで0からFまでのレジスタを選択し、4ビットのデータを書き込む、または読み込む形です。24時間/12時間設定が可能です。ピン(STD.P)に1/64秒(64Hz)、1秒(1Hz)、1分(1/60Hz)、1時間(1/3600Hz)間隔でパルスを出力することができます。電源電圧は2から5.5Vに対応しており、スタンバイは2Vで1.8uAと小さいのでCR2032のようなボタン電池でバッテリ・バックアップできます。アラーム機能はありませんので、必要な場合はマイコン側での対応となります。
PIC 16F887を使用した理由
今回使用したマイコンはPIC 16F887です。16F877Aの改良版といってもよいかと思います。877Aでもよいのですが、887は内部発振器を持っているので外付けのXTALが不要で便利です。GPIOは36本ありRTCをつなぐには十分ですが、時計としてくみ上げる場合は、時刻設定のボタンや、7セグメントLEDなどで多くのGPIOが必要となるので、余裕をみて40ピンDIPの887にしています。なぜ、887のような古いアーキテクチャのPICを選んだのかは、前述のようにRTCがパラレル・インターフェイスの古い仕様であること、それをアセンブラで制御したいので、マイコンも"ちょい古"を選びました。
プログラムのフローはこんな感じ
RTC52421Aを制御するプログラムのフローはだいたいこんな感じです。
①PICを初期化する:RTC62421A、ボタン、7SEG LEDなどの信号ラインのGPIO、変数定義など
②RTC62421Aを初期化する:レジスタD,E,FでRESET, HOLD, 24/12設定など
④年月日、曜日、時刻の初期値を設定しHOLD解除:レジスタ0 - C
⑥現在時刻を表示:レジスタ0 - Cを読み込み、7SEG LEDに表示する STD.Pで秒LED点滅
⑦設定ボタンが押されたか調べる
⑧⑥へ戻って繰り返す
〇ボタン処理:年、月日、時分、分秒の表示切り替え、各項目の変更(UP/DOWN)、アラーム時分の設定

RTC62421A DIP18Pのピン配置
アドレス、データバス それぞれ4ピン
制御ピン /CS0,CS1,ALE,/RD,/WR
STD.Pはパルス出力
RTC62421Aのレジスタと信号線

レジスタ0からFを設定する レジスタDEFはいつでも設定でき、0からCはHOLDにしてから設定する
データーはBCDコード
RTC62421Aを動かす手順
一気には時計にできないので、まず基本的な機能から確認していきます。初めにレジスタへの書き込み、読み込みルーチンを用意しなければなりません。アプリケーション・アニュアルのREAD/WRITEのタイミングチャートを見ながら、必要な信号ラインのレベルを変化させます。(後述) 書込み、読み込みルーチンが機能していることを確認するため、まずはSTD.Pにパルスを出してみます。RTCを初期化(レジスタFのRESETをON/OFFなど)し、STOP(レジスタFのHOLD ON)状態でレジスタEを設定して、1Hzのパルス(STD.P)を出力させてLEDを点滅させます。STD.Pピンはオープンドレインなのでプルアップ抵抗が必要です。このあたりの手順やレジスタの設定はアプリケーション。マニュアルに記載されています。
STD.PパルスによってLEDが1秒間隔で点滅すればRAED/WRITEルーチンは正常と判断できます。STD.Pは時計機能とは無関係なので、このまま発振させておくか、使用しなければ停めておくこともできます。これで各レジスタにREAD/WRIEできるようになったので、次は年、月、日、曜日、時、分、秒の各レジスタに年月日、時刻を適当に設定します。データはBCDです。これらの書き込みのときは、まずレジスタDでHOLD状態にしてから行い、書き込みが完了したらHOLDを解除します。読み込みはHOLDにする必要はありません。書き込みがうまくいっているかは、たとえば秒(レジスタ0)を読んで、そのビット0が1秒周期で0/1を繰り返しているかを判定し、LEDを点灯するなどして確認します。
次に7SEG LEDを4桁(もしくは6桁)分用意し、GPIOにつなぎます。4桁の場合はダイナミック点灯でも最低12本のGPIOが必要です。7SEG LEDが用意できたら、年、月日、時分、分秒をボタンで切り替えられるようにして、表示してみます。4桁の場合、時分秒の表示はできないので、先のSTD.PでLEDを点滅させます。このあたりは配線が面倒なので今回はEasyPICを使いました。
あとは時刻設定ボタンを用意し、動作させながら数値をUP/DOWNできるようにしておきます。やりかたはいろいろあるかと思います。一般的にはADJボタンを押して、Up/DOWNボタンで調整し、SETボタンで設定する感じが多いかと思います。
RTC62421Aはアラーム機能が無いので、必要な場合はマイコン側で処理しなければなりません。時分だけのアラームか、曜日も加えるかなど、自由に組み込めるかと思います。

RTC62421AのREAD/WRITEタイミング
ALE信号を用いてアドレスとデータバスを共有する場合のタイミングチャート
CS1でチップセレクトし、/CS0を出しながらアドレスを載せ、ALEの立下りでセット
データーをのせながら/RDまたは/WRを立ち上げると読み込/書き込まれる
アドレスとデータを別々のバスにしている場合はALEをHIGHのままとする
CS1はHIGHのままでもよい
RTC62421AのREAD/WRITEタイミングと手順
アドレスバスとデータバスを別々にしている場合と、共通にしている場合で異なります。別々にしている場合は、アドレスバスに4本、データバスに4本の計8本のGPIOが必要ですが、共通の場合は4本ですみます。ただし共通の場合はALE信号のために別に1本必要です。
CS1はチップセレクトでRTC62421Aがひとつしかない場合は常にHIGHでかまいません。タイミングはREAD/WRITEともにまずレジスタ・アドレスを読み込ませ、その後、/RDの立ち上がりエッジで読み込むか、/WRの立ち上がりエッジで書き込むかの違いです。
バスを共通にしている場合は、ALEでアドレスを読むタイミングを得ていますので、まずバスにアドレスを出力しておき、/CS0をLOWにし、その後ALEをHIGHにします。これでアドレスが読み込まれます。その後、READの場合は/RDをLOWにするとデータがバスに乗るので、立ち上がりエッジで取り込みます。WRITEの場合はデータを載せておいて、/WRをLOWにし、HIGHへ立ち上げると取り込まれます。バスを別々にしている場合は、ALEは常にHIGHにしておき、アドレスバスにアドレスを乗せっぱなしにできます。
レジスタD、E、F以外はHOLDにしてから設定し、設定し終わったらHOLDを解除します。解除するとカウントアップが始まり、順次秒から更新されます。STD.Pピンのパルスと同時に秒がカウントアップされます。
製作で感じたところ
PIC16Fをアセンブラでプログラミングするのは骨が折れます。それはPICのメモリ事情が品祖だからです。PIC16F887のプログラム用フラッシュ・メモリは8KW。データ用RAMが368Bあるので、たっぷりだなと感じますが、実はストレス無くプログラミングできるのは、プログラムが2KWに収まる場合と、データRAMが16B以下で済む場合です。それを超えればわずらわしいページ切替とバンク切替に悩まされることになります。887の場合は2KWのページが4ページで8KWです。ページ0を使いつくしたら、ページ1,2,3を使うことになりますが、ページ0にあるCALL命令でページ1のサブルーチンを呼ぶ場合は、まずPAGSELでページ1に切り替えなければなりません。プログラムが大きくなると、これが頻発します。そのうち同じページにあるか、他のページか分からなくなり、不安の結果不要なページ切り替えが頻発することになります。また、各ページからバンク切替なしでアクセスできるRAMはたったの16Bです。頻繁に使う変数を置くのですが、これを使い果たすと、今度はバンク切替の嵐となります。
このページ切替とバンク切替は、行わなければそのままプログラムは進行し、バグの温床となります。ページの切替を忘れたまま、デバッグでステップ実行をしていると、突然全く関係ない部分を実行し始めるので分かりますがエラーもなにも出ません。バンク切替も忘れると、他の変数を参照して知らぬ顔。手順は合っているのになぜか動かないプログラムが出来上がります。まことに殺生な世界にハマります。C言語のありがたさをしみじみ感じます。
こういうストレスの無い世界でのプログラミングはPIC24で可能です。PIC24のメモリは完全にフラットですから。しかしその命令は数が多く、しかもMOVLWなど、レジスタと結果の行先がわかりやすい命令ではなく、MOVが引数で何種類もあるって感じで、見た目にわかりにくい命令体系になっています。PIC24くらいになるとアセンブラは人間のためではなくCコンパイラのためにあるという感じです。まぁ、PIC24をアセンブラでプログラミングすること自体邪道なのかもしれませんが。しかしPIC24にもPIC24F04KA200のような、たった14ピンで2KWの小さなものもありますので、こういうものはアセンブラで作りたくなります。
(JF1VRR)


