2019年09月13日 | 公開。 |
Arduino Unoなどの小型のArduinoを使っている時に、I/Oピンが足りなくなって困った事はありませんか?Arduino Mega 2560等の大型のArduinoに置き換えれば問題は解決するものの、大型のArduinoは価格が高いですし、何よりArduino Unoなら、最終的に自作の回路にArduino互換マイコンを組み込んでしまう事を想定する場合、DIPパッケージのマイコン(ATmega328P)が手に入るので、便利です。(Arduinoで作った回路の小型化(Arduino互換機の製作)(1)参照)
そんな場合、74HC595というシフトレジスタを使えば、Arduinoの出力ピンを拡張できますし、74HC165というシフトレジスタを使えば、入力ピンを拡張できます。
この記事では、74HC595を用いて出力ピンを拡張する方法について説明します。
なお、この記事では、マイコンにArduinoを使う事を前提に、回路図やサンプルスケッチを紹介していますが、同様の技術が、他のマイコン(PICマイコンやMbedなど)の出力ピンの増設にも使えます。
この記事では、74HC595の動作原理や制御の方法の説明をまず行いますが、理屈の説明を飛ばして、手っ取り早く74HC595とArduinoの配線方法とサンプルスケッチをご覧になりたい方は、4ページから読み始めてください。
初心者がArduinoに触れる場合、まずArduino Uno(写真1)から使い始める場合が多いと思うのですが、Arduino Unoの場合、I/Oピンが合計で20本しかありません。だんだん複雑な物を作る様になると、I/Oピンが足らなくなってきます。Arduino LeonardoやArduino Zeroなどの、Arduino Unoと同じ形状のArduinoを使う場合や、Arduino MicroやArduino Nano(写真2)などの、ブレッドボードに挿して使う小型Arduinoの場合も、同様の問題が発生します。
こういう場合、Arduino Mega 2560やArduino Due(写真3)などの大型のArduinoを使う場合うと、I/Oピンの数が大幅に増え(Arduino Mega 2560の場合70本)、問題が解決するのですが、大型のArduinoは高価ですし、Arduino互換機を自作基板に組み込むにも、QFPなどの表面実装部品を使う必要があり、個人には敷居が高いという問題があります。
こういう場合、74HC595(写真4)というICを使うと、手軽にArduinoの出力ピンを拡張できます。
この写真に写っているTC74HC595AP(東芝デバイス&ストレージ製)はマルツで買った物で、130円(税別)しましたが、秋月電子なら、U74HC595AG-D16-T(UTC製)が1個35円(税込み)で買えます(2019年10月現在)ので、安く出力ピンを拡張できます。
この章では、74HC595を使うと、どうしてArduinoに出力ピンを増設できるのか、原理的な説明をします。
74HC595を使うと、ArduinoのI/Oピン3つを使って、出力ピン8つを増設できます。差し引き8−3=5つだけI/Oピンが増える計算になります。(図1参照)
この図では、電源線(VCCとGND)は省略しています。74HC595の電源をArduinoから供給する場合は、VCCとGNDの配線が必要になるため、Arduinoと74HC595の間の配線は、信号線3本、電源線2本の計5本になります。
さらに、2個の74HC595を使うと、ArduinoのI/Oピン3つを使って、出力ピンを16個増設できます。この場合は、差し引き16−3=13個だけI/Oピンが増える計算になります。(図2参照)
さらに、3個、4個…と74HC595の個数を増やすと、増設されるI/Oピンの数が24個、32個…と74HC595が1個につきI/Oピン8つずつ増えます。
ただし、良い事ばかりではなく、動作速度は、74HC595経由で出力する場合より、Arduinoの出力ピンで直接出力する方が速いです。
また、74HC595をたくさん使ってたくさんの出力ピンを増設するほど、動作速度が遅くなります。
動作速度が落ちるというデメリットはあるものの、どうして、たった3本の信号線で多くの出力ピンを増設するという、魔法みたいな事ができるのでしょう?それは、74HC595にシフトレジスタという回路が内蔵されており、シフトレジスタを使うとシリアル-パラレル変換できるからです。
シフトレジスタの詳しい説明は、用語集のシフトレジスタの項目に載っているので、そちらを読んでいただくとして、この節ではシフトレジスタの回路構成と動作の概略だけを説明します。
シフトレジスタといってもいくつかバリエーションがあるのですが、ここでは典型的な図3の回路について説明します。
注:74HC595には、Dフリップフロップを8個使った8段のシフトレジスタが内蔵されているのですが、Dフリップフロップの数が多いと説明図が複雑になるため、ここでは4段のシフトレジスタを使って原理的な説明をします。また、74HC595に内蔵されているシフトレジスタには非同期クリアの端子があるのですが、今回の説明には非同期クリアの話は出てこないため、非同期クリア機能のないシフトレジスタについて説明します。
図3の回路の中に、Dフリップフロップという部品が4つ使われています。Dフリップフロップの詳しい説明は用語集のDフリップフロップの項目に載っていますので、ここでは、シフトレジスタの動作を理解するのに最低限必要な説明のみをします。
Dフリップフロップというのは、図4に示す様に、CLK信号の立ち上がりのタイミングで(L→Hに電圧が変化する瞬間に)D信号の電圧を読み取り、Q信号に出力する部品です。CLK信号の立ち上がりのタイミング以外では、D信号は無視して、Q信号には変化がありません。
CLK信号の立ち上がりのタイミングが分かりやすい様に、上矢印を付けて強調してあります。また、電源投入後、最初にCLK信号が立ち上がるまでの間は、Q信号の電圧が予測不能なので、不定を表す記号「U」で表示しています。
言い方を変えれば、DフリップフロップはCLK信号の立ち上がりのタイミングのD信号を記憶する、1ビットの記憶装置だとも言えます。
参考:事実、RAMと呼ばれる記憶装置の内、SRAM(スタティックRAM)と呼ばれる物は、Dフリップフロップを多数、集積して作られています。
この様な性質を持つDフリップフロップを4つ、図3の様につなぐと、図5に示す様に、SRCLK信号の立ち上がりのタイミングで、直前のSER端子の電圧がQ0端子に出力され、直前のQ0端子の電圧がQ1端子に出力され、直前のQ1端子の電圧がQ2端子に出力され、直前のQ2端子の電圧がQ3に出力されるという具合に、電圧の情報が1段右側に移動する現象が起こります。この動作をシフト動作といいます。
SRCLK信号に正のパルス(L→H→Lの順番に電圧が変化するパルス)を4つ入力して、シフト動作を4回起こせば、SRCLK信号の立ち上がりのタイミングでSER端子に入力されていた電圧が、入力された時間の逆順でQ0端子~Q3端子に出力されるという現象が起こります。その事を示したタイミングチャートが図6です。
図6を見ると、合計8つの正のパルス(合計8クロック)がSRCLK端子に入力されている事が分かります。それぞれのパルスの立ち上がりの部分に、1~8の連番を付けています。
また、この図から分かる様に、1~4番のパルスと、5~8番のパルス間には、しばらく信号の変化がない部分があります。
まず、前半の1~4番のパルスの部分について考えます。
1~4番のパルスの立ち上がりのタイミングでは、SER端子にH、L、H、Hの順に電圧が入力されています。SRCLK信号の立ち上がりのタイミングではシフトレジスタがシフト動作しますから、電圧が1つ右の段(図6のタイミングチャートでは1つ下の行)に伝わります。これを4回繰り返すと、4番目のパルスの立ち上がり以降の波形を見て分かる様に、SER端子に入力した電圧が、逆順(H、H、L、Hの順)でQ0~Q3端子に出力されます。
後半の5~8番のパルスの部分においても、前半と同様の現象が起きています。
5~8番のパルスの立ち上がりのタイミングでは、SER端子にL、H、L、Hの順に電圧が入力されています。5~8番のパルスの立ち上がりでシフト動作を4回繰り返すと、8番目のパルスの立ち上がり以降の波形を見て分かる様に、SER端子に入力した電圧が、逆順(H、L、H、Lの順)でQ0~Q3端子に出力さます。
この様に、1つの入力端子(この場合はSER端子)に、シフトレジスタの段数と同じ数(この場合は4つ)の信号を、クロック信号(この場合はSRCLK信号)に同期して順に入力すると、シフトレジスタの出力端子(この場合はQ0端子~Q3端子)に、入力した信号が出力される事を、シリアル-パラレル変換といいます。
複数ビットの情報を伝える際に、1つの信号線を使って複数のビットの情報を順に伝える方式をシリアル方式といいます。一方で、伝えたい情報のビット数と同じ数の信号線を使って、全ビットの情報を同時に伝える方式をパラレル方式といいます。シリアル-パラレル変換とは、シリアル形式で入力した信号をパラレル方式に変換する操作の事なのです。
この様に、伝えたい情報を送るためのSER信号とクロック信号であるSRCLK信号の2つの信号線を使うと、シフトレジスタのQ0~Q3の4つの端子に好きな電圧を出力できます。この事により、ArduinoのI/Oピンを2つ使う事で、シフトレジスタ上の4つの出力ピンを操れるようになります。
また図3では4段の(Dフリップフロップを4つ使った)シフトレジスタを例示しましたが、8段のシフトレジスタを使うと操れる出力端子が8個になり、16段のシフトレジスタを使うと操れる出力端子が16個になります。
シフトレジスタの段数を増やして出力ピンを増やした場合でも、Arduinoで使用するI/Oピンは、SER信号用とSRCLK信号用の計2つのままです。
ただし、シフトレジスタの段数を増やすと、シリアル-パラレル変換に必要なクロックパルスの数が増えるため、動作速度が低下します。
図3のシフトレジスタでシリアル-パラレル変換が行える事は説明しましたが、この回路のままでは具合の悪い所があります。というのは、この回路では、図6のタイミングチャートを見て分かる様に、シリアル-パラレル変換の最中(1クロック目の立ち上がりから4クロック目の立ち上がりまでと、5クロック目の立ち上がりから8クロック目の立ち上がりまで)に、Q0~Q4の端子に変換途中の一時的な信号が出力されてしまうからです。
シフトレジスタの応用の仕方によっては、変換途中の一時的な信号が出力されても良い場合もあるのですが、今回の様にArduinoの出力端子の拡張の目的でシフトレジスタを使う場合は、一瞬でも意図しない電圧のパターンが出力端子に出力されてしまう事は避けなければなりません。
この問題の対策に使うのがストレージレジスタです。
ストレージレジスタは図7の様な回路です。
回路図を見れば分かる様に、4つのDフリップフロップがクロック信号(RCLK信号)を共有しています。この回路は、RCLK信号の立ち上がりのタイミングで、各DフリップフロップがそれぞれQ1~Q3の端子から電圧を読み込み、それぞれQA~QDの端子に出力します。この回路のタイミングチャートの例を図8に示します。
図7のストレージレジスタは、クロック信号の立ち上がりのタイミングで入力信号を読み込み、出力端子に出力します。クロック信号の立ち上がりのタイミング以外で入力信号が変化しても、出力信号に影響を及ぼしません。
ストレージレジスタのこの性質を使うと、図3のシフトレジスタが持っている、シリアル-パラレル変換の最中に途中結果が出力に出てしまう欠点をカバーできます。そのためには、図3のシフトレジスタの出力端子を図7のストレージレジスタのデータ入力端子に接続して、図9に示す回路にします。
図9の回路でシリアル-パラレル変換をする場合のタイミングチャートの例を図10に示します。
図9では、説明図が大きくなりすぎない様に4ビットのシリアル-パラレル変換回路の回路図を紹介しましたが、シフトレジスタを4段から8段に変更し、ストレージレジスタも4ビットから8ビットに変更すれば、ほぼ74HC595と同様の回路になります。
注:厳密な話をすると、74HC595は、図9の回路を8ビット化しただけでなく、シフトレジスタに非同期クリア機能がありますし、また、ストレージレジスタのパラレル出力端子に3ステートバッファが付いています。しかし、これらの機能はArduinoの出力ピンの増設には必ずしも必要ない物なので、ここでは説明しません。74HC595の機能についてさらに詳しく知りたい場合は、用語集の74HC595の項目をご覧ください。
図9を見ればこのシリアル-パラレル変換回路を動作させるために、Arduinoから供給する必要のある信号線は、SER、SRCLK、RCLKの3つである事が分かります。これらの3つの信号の制御を、ArduinoのI/Oピン3本で行うと、シリアル-パラレル変換により、出力ピンの増設ができます。
図9の回路は4ビットのシリアル-パラレル変換回路であるため、図10のタイミングチャートではSRCLK端子に4クロック入力した後にRCLK端子に1クロック入力する事でシリアル-パラレル変換を行っていますが、実際の74HC595は8ビットのシリアル-パラレル変換回路であるため、SRCLK端子に8クロック入力した後にRCLK端子に1クロック入力します。
さらに74HC595を2つ接続して16ビットのシリアル-パラレル変換回路を形成する場合は、SRCLK端子に16クロック入力した後にRCLK端子に1クロック入力するという具合に、シリアル-パラレル変換回路のビット数が増えると、SRCLK端子に入力しなければならないクロック数が増え、動作時間が遅くなります。
次のページでは、Arduinoと74HC595の具体的な接続法について説明します。