アフィリエイト広告
アフィリエイト広告

シフトレジスタ 74HC597から Arduinoへ SPIでデータを受ける

今回は、シフトレジスタ 74HC597 (PISO) から Arduino へ、SPI でデータを受けとる実験をしてみました。

前回やってみたのは、Arduino からシフトレジスタ 74HC595 (SIPO) へ SPI でデータを送る実験でした。今回とは受け渡すデータの伝送方向が逆になっています。

SPI とは

シリアル通信の一種である SPI のしくみは、前回勉強しました。おさらいです。

SPI とは、シフトレジスタ同士のデータの交換です

SPI はコントローラ (Controller) とペリフェラル (Peripheral) の間のデータ交換のしくみです。

図1 に示すように、コントローラとペリフェラルにはそれぞれシフトレジスタがあり、それがループのようにつながっています。それぞれのシフトレジスタは交互にデータを送り合って、最終的にコントローラ側のデータとペリフェラル側のデータが入れ換わります。

SPIのしくみのダイヤグラム
図1. SPI のしくみ

前回は送信だけを行ないました。今回は受信だけをやりたいのですが、このときもコントローラからデータを送信することで、ペリフェラルとデータの交換を行ないます。その結果、ペリフェラルのデータが受信されることになります。

74HC597 から Arduinoへデータを受ける方法

では、じっさいにコントローラの Arduino で、ペリフェラルの 74HC597 からデータを受ける方法を考えてみましょう。

74HC597からArduinoへデータを受ける接続のダイヤグラム
図2. 74HC597から Arduinoへデータを受ける接続図

データを受信する場合も、Arduino からデータを送ります。このとき送信するデータはダミーデータ、要するになんでもいいんです。SPI.transfer(dummyData) でダミーデータが COPI に送信され、同時に受信した CIPO のデータは戻り値として出力されます。
ダミーデータは 74HC597 では利用しませんから、COPI はどこへも接続しません。利用するのは送信時に出力されるシリアルクロック SCK で、74HC597 のシフトクロック SHCP に接続します。

74HC597 側では、チップセレクト CS を受けてパラレルロード PL を生成し、ストレージレジスタからシフトレジスタへデータを渡します。そして SCK に同期してデータを CIPO へ送出します。
送信が完了すると CS が HIGH になりますので、これをストレージクロック STCP として、外部からのパラレルデータをストレージレジスタへ読み込みます。つまり、74HC597 から送られてくるデータは、一回前の通信が完了したときのデータということになります。
もちろん、通信開始時に STCP を生成してデータを取り込んでもよいです。まぁ、そこまでリアルタイムであることが必要なのかってところでしょうか。

74HC597からArduinoへデータを受けるタイミングダイヤグラム
図3. 74HC595から Arduinoへデータを受けるタイミングダイヤグラム

図3 は、データ受信時のタイミングダイヤグラムです。ここでは SPISetting() を、MSBFIRST、SPI_MODE0 としています。

コントローラ (Arduino) 側では、チップセレクト CS を LOW にすることで通信を開始し、終了したら HIGH にもどす。SPI.transfer() を実行するとシリアルクロック SCK が送出される。COPI に出力されるデータは、ペリフェラル側では利用しない。

ペリフェラル (74HC597) 側。CS は STCP につながっているが、LOW になっても何も起こらない。
CS の立ち下がりエッジで、一定時間のパラレルロード PL パルスを生成する。これにより、シリアルデータ Q7 に データ D7 が出力される。
SHCP (SCK) の立ち上がりエッジでデータをシフトし、8ビットのデータが CIPO へ送られる。コントローラも、データを SCK の立ち上がりエッジ (Rising) で読み込み (Data Capture)、SPI.transfer() の戻り値として出力する。
受信が終了し CS が HIGH になると、それがストレージクロック STCP となり、新たなデータがストレージレジスタへ読み込まれる。

回路図

図2 にしたがって、Arduino へ 74HC597 からデータを受ける回路を作ります。

データを受信する回路

8ビットのパラレルデータを 74HC597 でシリアルデータにして、Arduino で受信する回路です。

74HC597からArduinoへデータを受ける回路図
図4. 74HC597から Arduinoへデータを受ける回路図

Arduino は Nano Every です。使用するピンは、SCK が D13、CIPO が D12、CS は D8 です。UNO や NANO では CS は D10 ですので、間違えないように。COPI (D11) は使用しません。
電源は USB から供給します。IC の駆動電源として 5V 出力を利用します。電源にかなりノイズがのりますので、10μF の電解コンデンサをつけてあります。もちろん、IC のパスコンなどはお忘れなく。

左の Dip スイッチで 8ビットのデータを生成、それをシフトレジスタ 74HC597 に読み込み、Arduino へ送ります。
下部の NOR ゲート 74HC02 を使った回路はワンショットパルス回路。 図3 に示したように、チップセレクト CS が LOW になったときに、パラレルデータをロードするための PL を生成します。パルス幅は 90nsほどになっています。データシートによると必要なパルス幅は 14ns なので、十分でしょう。

ワンショットパルス回路

ワンショットパルス回路図
図5. ワンショットパルス回路

図5 上は、入力信号 CS が HIGH になったときに、一定幅の正のパルス PL を出力するワンショットパルス回路です。
CS が RC回路をとおって遅延した時間だけ、HIGH が出力されます。

今回使う信号は CS、PL ともに負理論 (LOW で有効) ですので、図5 下のように AND の入力に負理論を示す○をつけ、出力を NOT で反転させます。これで CS が LOW になったときに負のパルス PL が出力されるようになります。
遅延回路は立ち上がりでも立ち下がりでも遅延しますから、論理の変換には影響しません。

負理論入力の AND は正理論入力の NOR です。NOT も NOR に換えることで、図4 のように 74HC02 だけで組むことができました。

スケッチ

74HC597 から Arduino へ、SPI で 8ビットデータを受信するテスト用のスケッチです。

  1. // Sketch for 74HC597 to Arduino SPI-Test 2023.9.10 meyon
  2. #include <SPI.h>
  3. SPISettings mySettings(8000000, MSBFIRST, SPI_MODE0);
  4. void setup() {
  5.   // In Nano Every,SS is pin-D8, Mode setting required
  6.   pinMode(SS, OUTPUT);
  7.   Serial.begin(9600);
  8.   SPI.begin();
  9. }
  10. void loop() {
  11.   static byte receivedValue = 0;
  12.   SPI.beginTransaction(mySettings);
  13.     digitalWrite(SS, LOW);
  14.     receivedValue = SPI.transfer(0xff);
  15.     digitalWrite(SS, HIGH);
  16.   SPI.endTransaction();
  17.   Serial.println(receivedValue, BIN);
  18.   delay(50);
  19. }

9行目。Arduino Nano Every では CS のピンモードを設定してやらないとうまく動きません。UNO や NANO では必要ないです。あっても不都合はないようですが、念のため SPI.begin() の前に置いておきましょう。

20行目で CS を LOW にし、21行目でダミーデータ (0xff) を送信します。同時に戻り値を受信データとして receivedValue に代入し、22行目で CS を HIGH にもどします。そしてシリアルモニタへ受信データを表示させています。このトランザクションを 50ms 間隔で繰り返しています。

動作状況

動作時の各部の波形
図6. 動作時の各部波形

図6 は、動作中の各部の波形です。CS を基準に合成しました。

一番上 (黄) が CS です。通信開始時に LOWとし、終了時 HIGH にもどします。
0.8μs 後にシリアルクロック SCK (青上) が出力されます。
CS と同時にパラレルロード PL (青中央) が出力されて、CIPO にデータ Q7 (青下) がセットされます。ここではパラレルデータを「11010110」としていますので、D7 の「1」となっています。SCK に同期して、CIPO へ出力されています。

全体で 5.9μs になりましたが、ときどきばらついて 3倍ほどの時間になることがあります。

クロックと CIPOのデータの波形
図7. クロックと CIPO データの波形

図7 に、クロック SCK (黄) と出力 CIPO (青) を拡大して示します。

コントローラでは、SCK の立ちあがりエッジで CIPO のデータが読み込まれることに着目しておきましょう。

Arduinoシリアルモニタの出力
図8. Arduino シリアルモニタ出力

図8 は、Arduino のシリアルモニタの出力です。

図7 でみたように、たしかに「11010110」が読み込まれています。

ModeOutput EdgeData Capture
SPI_MODE0FallingRising
出典:Arduino & Serial Peripheral Interface (SPI)

コントローラでは、Output Edge で COPI がシフトし、Data Capture で CIPO を読み取ります。ペリフェラル側のシフトレジスタは、Data Capture でシフトします。そのタイミングの違いがわかれば、データのやりとりはむずかしくないように思います。

ブレッドボード

実験中のブレッドボードのようす
図9. ブレッドボードのようす

毎度の、じっさいに組んで実験してみたよ、のブレッドボードです。

Dipスイッチでデータを生成、左側の IC が 74HC597、右が 74HC02 です。Arduino から 3本のラインでつながっているのがわかると思います。

回路図には描いてないですが、IC の電源端子にはパスコン 0.1μF をつけています。また、NOR の未使用入力端子は GND につないでおきます。そのあたりは、あたりまえのこととして実施しておきましょう。

後記

今回は、ペリフェラルのシフトレジスタ 74HC597 から、コントローラの Arduino へ SPI でデータを受信する実験をしました。

前回のデータ送信の実験と合わせて、五里霧中だった SPI 通信もかなり理解できたように思います。
もちろん、本格的に SPI 通信を行なうとしたら、そのためのモジュールとかあるのですから利用するほうがよいでしょう。ただ、ちょっとシフトレジスタを使ってデータ伝送しよう、ってときに、それなりに扱えそうです。

さてと、送受信することはこれでよさそうですが、もう少し SPI で遊んでみようかと思ってます。

タイトルとURLをコピーしました