シフトレジスタ 74HC595の考察
電子工作で、8ビットシフトレジスタ74HC595をよく使います。
しかし、仕様を完全に理解していないで、他ブログや自分の過去の利用を流用し、
その場しのぎで利用していました。
「これじゃぁ、アカン、ちゃんと仕様と機能をちゃんと理解しよう」と思い、
調査しまとめることにしました。
まずは仕様の再確認
ピンレイアウト
メーカー毎に微妙にピン名称が異なります。
MC74HC595Aが分かり易い名称なので、データシートからピンレイアウトを
拝借し、修正しました。
ブロック図
内部的には、シフトレジスタとストレージレジスタの構成になっています。
変化するシフトレジスタの8ビットパラレル出力を、ストレージレレジスタが
LATCH CLOCKのラッチのタイミングで取り込んで、パラレル出力の状態を保持&出力します。
ストレージレジスタのQA~QHは3ステート(HIGH、LOW、ハイインピーダンス)です。
(SQHは2ステート(HIGH、LOW)であるに注意)
Arduino Unoを使った実験
ブレッドボード上の8個のLEDを74HC595を使って制御します。
接続は、74HC595のパラレル出力QA~QH、SQHにLEDを接続します。
各LEDには電流調整用に330Ωの抵抗を入れてGNDに接続しています。
各LEDはQA~QH、SQHの出力がHIGHの場合点灯し、LOWの場合に消灯します。
OUTPUT ENABLE、SERIAL DATA INPUT、RESET、SHIFT CLOCK, LATCH CLOCKの
制御用の入力端子は、ArduinoのD10、D11、D2、D13、D3に接続します。
LEDの簡単な点灯制御
つぎの動画のように、8つLEDをチカチカさせる制御です。
スケッチ
// 利用ピンの定義 #define OUT_ENABLE 10 #define SERIAL_OUT 11 #define HC595_RESET 2 #define SHIFT_CLK 13 #define LATCH_CLK 3 // シフトレジスタへの8ビットデータのセット void shift_dataOut(uint8_t data) { for (uint8_t i=0; i < 8; i++) { digitalWrite(SHIFT_CLK,LOW); digitalWrite(SERIAL_OUT, (data & (0x80>>i))); digitalWrite(SHIFT_CLK,HIGH); } } // シフトレジスタのデータリセット void shift_reset() { digitalWrite(HC595_RESET,LOW); digitalWrite(HC595_RESET,HIGH); } // シフトレジスタからストレージレジスタへのデータセット void strage_update() { digitalWrite(LATCH_CLK,LOW); digitalWrite(LATCH_CLK,HIGH); } // ストレージレジスタの出力有効 void strage_enable() { digitalWrite(OUT_ENABLE, LOW); } // ストレージレジスタの出力無効 void strage_disable() { digitalWrite(OUT_ENABLE, HIGH); } void setup() { // 利用ピンの初期化 pinMode(OUT_ENABLE, OUTPUT); pinMode(SERIAL_OUT, OUTPUT); pinMode(HC595_RESET,OUTPUT); pinMode(SHIFT_CLK, OUTPUT); pinMode(LATCH_CLK, OUTPUT); // SHIFT CLOCK、LATCH CLOCKの設定 digitalWrite(SHIFT_CLK,LOW); digitalWrite(LATCH_CLK,LOW); shift_reset(); // シフトレジスタの値リセット strage_update(); // シフトレジスタからストレージレジスタへの値セット strage_enable(); // ストレージレジスタの出力有効 delay(2000); } void loop() { shift_dataOut(0b10101010); strage_update(); delay(500); shift_dataOut(0b01010101); strage_update(); delay(500); }
スケッチの説明
①初期化 setup()
(1)利用ピンの初期化
74HC595の制御を行う5つのピンの出力設定を行っています。
(2)SHIFT CLOCK、LATCH CLOCKの設定
初期値としてLOWの設定を行います。
(3)シフトレジスタの値リセット
shift_reset()関数を呼び出してシフトレジスタの値のリセットを行います。
shift_reset()関数は次のように定義しています。
// シフトレジスタのデータリセット void shift_reset() { digitalWrite(HC595_RESET,LOW); digitalWrite(HC595_RESET,HIGH); }
74HC595のリセットピンのLOWを設定してリセットを行った後、HIGHに戻しています。
(4)ストレージレジスタへの値設定
strage_update()関数を呼び出して、シフトレジスタの値をストレージレジスタに設定
しています。
strage_update()関数は次のように定義しています。
// シフトレジスタからストレージレジスタへのデータセット void strage_update() { digitalWrite(LATCH_CLK,LOW); digitalWrite(LATCH_CLK,HIGH); }
74HC595のLATCH CLOCKに対して、LOW→HIGHを行うことで、
シフトレジスタの値をラッチしてストレージレジスタに取り込みます。
(5)ストレージレジスタの出力有効
strage_enable()関数を呼び出して、ストレージレジスタのパラレル出力QA~QH、SQH
を有効にします。
strage_enable()関数は次のように定義しています。
// ストレージレジスタの出力有効 void strage_enable() { digitalWrite(OUT_ENABLE, LOW); }
74HC595のOUTPUT ENABLEをLOWに設定することにより、
出力を有効にしています。
delay(2000)は、LEDの出力がリセットされていることを確認するために入れています。
Arduinoのリセットボタンを押した直後、2秒間8個のLEDが消灯していることが確認できます。
②LEDの点灯ループ loop()
8個のLEDに対して、2つのパターンの出力を0.5秒間隔で繰り返しています。
shift_dataOut()関数は8個のLEDの点灯パターンを設定しています。
shift_dataOut()関数は、シフトレジスタへの値の設定のみを行います。
この関数を実行しても、LEDの表示には影響しません。
shift_dataOut()関数は次のように定義しています。
// シフトレジスタへの8ビットデータのセット void shift_dataOut(uint8_t data) { for (uint8_t i=0; i < 8; i++) { digitalWrite(SHIFT_CLK,LOW); digitalWrite(SERIAL_OUT, (data & (0x80>>i))); digitalWrite(SHIFT_CLK,HIGH); } }
8ビットの値をシフトレジスタにセットするために8回繰り返し処理を行っています。
1回毎の処理で1ビットの値をシフトレジスタにセットしています。
(1)74HC595のSHIFT CLOCKをLOWにした状態にする
(2)74HC595のSERIAL OUTにセットしたい値をセットする
(3)74HC595のSHIFT CLOCKをHIGHにして、SERIAL OUTの状態をラッチして
1ビットをシフトレジスタにシフトインして取り込む。
次にstrage_update()関数にてシフトレジスタの値をストレージレジスタにセットします。
このタイミングでLEDの表示が更新されます。
LEDのPWMを使った明るさの制御
74HC595のOUTPUT ENABLEをPWMで制御することでLEDの明るさを制御することが出来ます。
スケッチのloop()のdeley(500)を次のように修正して、PWMにて徐々に暗くなるように
修正してみます。
実行すると、「ぽわー、ぽわー」と暗くなってからパターンが切り替わります。
void loop() { shift_dataOut(0b10101010); strage_update(); for (int16_t i=0; i<256; i++) { analogWrite(OUT_ENABLE,i); delay(5); } shift_dataOut(0b01010101); strage_update(); for (int16_t i=0; i<256; i++) { analogWrite(OUT_ENABLE,i); delay(5); } }
ちょっとした疑問
74HC595は連結(SQHを連結先の74HC595のSERIAL DATA INPUTに接続)して
8ビット、16ビット、24ビットと桁数を増やすことが出来る仕様なのですが、
QHとSQHが同じ値なので、
「1個目の8ビット目と2個目の1ビット目が同じ値になってしまうのでは?」
と非常に疑問を感じます。
シフトレジスタ部の内部ロジック構造を見てみることにします。
シフトレジスタ部はDフリップ・フロップの連結構造です。
(ロジック図はMC74HC595Aからの引用です)
74HC595内部の個々のDフリップ・フロップの連結と
1個目の最後のDフリップ・フロップと2個目の74HC595のDフリップ・フロップへの
連結(SRH ⇒ SRA)は、差異が無いはずです。
下記の図は1個目の74HC595のシフトレジスタ部内のSRHと、2個目の74HC595の
シフトレジスタ部内のSRAを接続したイメージです。
下図のタイミングチャートにおいて、
SERIAL CLOCKの立上り(太い線)でSERIAL DATA INPUTから読み込むデータを
D0、D1、D2...とすると、SQHとSQAの状態は次のような感じにまります。
(時間軸は左が過去)
SQHがD5をラッチするタイミングでSQAのDにはD4が入力されているため、取り込むデータの
値は当然D4になります。
うぁ、良く考えたら当たり前で、こんな図を描いて考える必要もなかった。
「Dフリップ・フロップ の連結で受け取るデータは前段のDフリップ・フロップの
1クロック遅れたデータを受け取る」
ってことです。
まあ、これで疑問が解けたので良しとします。
« ATtiny13AでI2C接続キャラクタLCDを利用する(4) | トップページ | Aliexpressで USBTinyISPの小型版を購入 »
「arduino」カテゴリの記事
- 豊四季Tiny Basic for micro:bit のマニュアルを更新しました(2020.11.21)
- 豊四季タイニーBASIC for Arduino 機能拡張版 V0.08の更新(2020.07.27)
- Arduino IDE 1.8.13が公開されています(2020.07.24)
- SPI接続フラッシュメモリモジュールを入手しました(2020.05.13)
- 豊四季タイニーBASIC for Arduino 機能拡張版 フルスクリーンエディタ対応(2020.02.20)
« ATtiny13AでI2C接続キャラクタLCDを利用する(4) | トップページ | Aliexpressで USBTinyISPの小型版を購入 »
コメント