USART, PPI, PIC

NECのセカンドソースでパッケージの統一感があったので、つい1枚の写真にとってしまいました。すべてA無しの旧バージョンです。8086はおろか8085でも使えず、8080A専用です(8255AなどのAバージョンならOK)。と、良くみたらPICはuPD8259でなくてuPD8259-5になっているから、これだけは8085でも使用できるものでした。いかんいかん。
8251, 8255, 8259
Aが付いているかどうかはバスタイミングとPICの8086対応だけでプログラマから見たモデルは同一です。すでに単体のLSIとしては使われなくなっても、大きなLSIの一部に組み込まれた形で使われ続けていたりしますから、あいかわらずこれらのチップのレジスタ操作を行うプログラマはいるんじゃないでしょうか。

写真右上のuPD8251はIntelの8251相当品で、シリアル通信用のインターフェースLSIです。Universal Synchronous/Asynchronous Receiver Transmitter(汎用同期/非同期送受信回路とでもなるのかな)の略でUSARTと呼称されています。バイト指向の同期通信が可能になっている他、非同期通信でも文字のビット長に5 bitの設定やストップビットに1.5 bitの設定があるなど無線通信に使われているシリアル通信のフォーマットもサポートしています。
ただ、モード設定用のレジスタとコマンドレジスタと、さらに同期通信用の同期キャラクタ設定用レジスタが、同じアドレスに割り当てられていて、それまでの設定履歴によって何がアクセスされるか決まるようになっているため、正しく初期化するためには一見変わった手順でレジスタに書き込まなくてはなりません。ダミーの初期化データを最初に3回書き込まなくてはならないのですが、これを忘れるとたいていの場合は正しく動いても初期化ルーチンが呼び出されたときに偶然同期キャラクタ設定用レジスタにアクセスする状態になっていた場合なんかに初期化が正常に行なえないという、再現性の低いやっかいな問題を抱え込むことになります。
さらに8080Aクラスで使用する場合には問題なくても、高速の8086とか80286なんかに接続してレジスタに連続アクセスしたような場合にはレジスタ書き込み後のリカバリタイムが満足されずに誤動作することもありました。

写真下のuPD8255はIntelの8255相当品で、パラレルI/Oインターフェースです。Programmable Peripheral Interfaceの略でPPIと呼ばれています。8 bit単位で入出力できるポートをA, B, Cの3ポート備えていて、1個で24本の入出力が可能です。ただし、ビット単位で入出力方向を決めることはできず、A, Bポートはポート単位で入出力方向を指定します。さらにハンドシェークの有無などにより、3モードにポートを設定することができ、Cポートはモード設定により異なる使われ方をします。モード0が単純な入出力ポートで、モード1がハンドシェーク付きの入力や出力が行なえるモード、モード2が制御信号付きの双方向パラレル入出力になっています。モード1はプリンタや紙テープリーダ・パンチャなんかとのインターフェースを、モード2はSCSIインターフェースを低レベルにしたような感じのI/Oインターフェースなんかを想定しているといえるでしょうか。PPIのモード2インターフェースを利用したものにはNECのPC8801用フロッピーディスクドライブインターフェースがありましたね。
8255の問題点は初期設定時の出力レベルが挙げられます。8255はリセット直後に全ポートが入力状態になります。このこと自体は正しい処理です。仮に入力ポートに使うつもりで外部回路から駆動されている端子がリセットで出力状態になったら外部回路の出力と8255の出力がぶつかって破損する可能性があるのに、出力ポートに使う予定のところが入力状態になってもコンフリクトは起きずにせいぜい出力される状態が不定になるだけです。出力が不定になるのは、ポートを外付けの抵抗でプルアップかプルダウンしておけば回避できますから。ところが、出力ポートに設定した瞬間に、8255は必ずLレベルを出力してしまいます。そのため、8255のリセット時の出力を固定するためにプルアップ抵抗を使用することはできず、プルダウン抵抗しか許されなくなります。たとえばモータを駆動するような場合、CPUが関与しないリセット時の状態や8255の初期設定時の状態でいきなりモータに電源が入ってしまっては困ります。そのためLレベルでオフになるような回路にしておかなくてはならないからです。最近ならCMOSロジックが普通に使えるので、プルダウンでもOKですが、1970年代は8255の外付け回路にTTLロジックファミリを使用することも多く、TTLの入力をプルダウンするのは入力流れ出し電流の都合で困難でしたから、8255の出力で外部論理回路を駆動するのは面倒でした。いきなり8255の出力でNPN型のダーリントントランジスタ回路を駆動する場合には問題にならないんですけどね。

写真左上のuPD8259-5はIntelの8259-5相当品で、割り込みコントローラです。Programmable Interrupt Controllerの略でPICと呼ばれています。8080Aや8085Aに対して単体で8レベルまでの優先制御付き割り込み制御回路を実現できます。複数使用してカスケード接続することによって最大64レベルまでの優先度まで拡張可能です。
もともと8080A用にはバイポーラプロセスで作成された8214という割り込みコントローラが用意されていました。8レベルまでの優先順位決定回路とカスケード拡張回路、さらにRST命令をプルアップされたデータバスに出力する回路が組み込まれている、比較的シンプルな24ピンの割り込み制御回路です。ただし、優先順位は割り込み要求信号端子の番号によって固定されていたり、割り込み時に送出できる命令がRST命令だけで自由度が少なかったりしました。その欠点を改良していったのが8259です。AMD社からはAm9519という少し仕様の異なるバージョンが発表されています。
割り込みモードをプログラマブルにしたり、8レベルの割り込み要求それぞれに個別にマスクをかけられるようになったり、RST命令ばかりかCALL命令も割り込み時に出力できるようにしたり、8 bitマイクロプロセッサの割り込み制御回路としては相当にぜいたくなものになっています。

そういえば、写真のLSIは金属のふたの部分からセラミックパッケージ上を金メッキされた金属配線が特定のピンに配線されているのが見えると思います。n-MOSやCMOSのICでは、この金属部分は一番電圧の低いところに接続するかどこにも接続していないオープン状態のどちらかにすることが原則となっています。これらのLSIは5 V単一電源ですから、接続された先はすべてGND端子ということになります。もちろん-5 V端子のあるような8080Aの場合には、-5 Vに接続されているか、オープンのどちらかです。不用意にどこかの配線とショートさせないように気をつけるべきでしょう。

さて、上の写真はすべてAなしですが、8251と8255にはそれぞれ8251Aと8255Aというバージョンがあり、多数流通していたのはこちらのA付きの方です。Aが付いているのは8085対応ということですね。どこが違うのかというと、レジスタがトランスペアレントラッチになっているかフリップフロップ構造になっているかという点にあります。
8080では書き込み時にデータバスに出力されたデータが確定してからWR*ストローブパルスが出力されました。したがって、WR*ストローブが有効となる時間には書き込みたいデータが確実に入力されています。ところが、8085になると、Z80-CPUなど他の多くのプロセッサと同様にWR*ストローブが出力された後に少し遅れて有効なデータがプロセッサから出力されます。WR*ストローブの終端時には十分なセットアップ時間を確保したうえで確実なデータが周辺LSIやメモリに与えられます。後者のほうがアクセスタイミングに余裕を持たせやすいため、広く使われる傾向があります。
書き込み対象がスタティックメモリ素子の場合には、書き込みタイミングの途中で不確定なデータから正しいデータへ遷移しても最終的には正しいデータが書き込まれるため、どちらでも問題はありません。ダイナミックメモリの場合でも書き込みサイクルを初めてから少したってから確定したデータが必要となるため、問題はありません。それどころかCPUがデータを用意する前から早めにWR*ストローブが出力されて書き込みサイクルを起動できるため、アクセス時間に余裕ができます。
しかし、I/Oポートの場合は問題が生じます。出力ポートのレジスタがトランスペアレントラッチ構造の場合、WR*ストローブが有効な間はデータバスの状態がそのまま出力されてしまいます。たとえば、現在00Hが出力されているポートに0FFHを出力しようとしても、00Hからすなおに0FFHに出力が遷移するのではなく、00Hから一瞬デタラメなデータが出力されて、その後で0FFHに変化するというようなことが発生します。まぁ、せいぜいほんの200 nsくらいのことでしょうから出力ポートの先に接続されたものが遅い素子なら無視できるわけなんでしょうけど。ところが8255の場合を考えてみると、Cポートのビット単位のセットリセットコマンドがあるため、危険なことが生じます。8255には、コントロールレジスタに特別なコマンドを書きこむことでCポートの特定の1 bitをセットしたりリセットしたりする機能があります。さて、Cポートのビット0をセットするコマンドは01Hというコマンドになりますが、これを書き込むときに偶然に不定データとして先に05Hというデータが出力されていたとすれば、Cポートのビット2をセットしろというコマンドになります。そうすると、8255は05Hという書き込みと01Hという書き込みが連続して発生したと誤って解釈する可能性があります。プログラマの意図した命令列以外の不定データが書き込まれたことによって、関係ないはずのビットが影響を受ける場合があるのですね。ということで、8085やZ80-CPUに8255を接続すると誤動作する可能性があります。8255Aになると、いったんWR*パルスの立ち上がり時にフリップフロップ構造のレジスタにコマンドを記憶して、それからビット操作などの動作を始めますから、WR*パルスの後端でデータが確定さえしていれば、出力ポートにヒゲ状のノイズを出力することもなければビット操作時に誤動作することもありません。
同じことは8251にもいえます。8251でシリアル通信を行っている最中、ブレーク送出やエラーリセットの都合上、コマンドレジスタに書き込みすることがあります。同じコマンドレジスタのビット6に1というデータを書き込むと8251をリセットするというコマンドになってしまいます。コマンドレジスタ書き込み時にWR*パルスが有効な間の不定データのビット6が偶然1になっていると、8251を意図せずリセットする可能性があります。
というわけで、8080(A)以外のプロセッサで8251や8255を使用する場合、必ずA付きのバージョンのものが必要となります。トランスペアレントラッチの方がフリップフロップよりも回路が簡単で少ないトランジスタ数で実装できますから、そうしていたのでしょうけれど。

Return to IC Collection.