74HC595と74HC165をCH552Eで使用してみた.

電子工作

先日からいくつか記事にしているCH552E.しかし,いかんせんGPIOが少ない!!.確かに,GPIOの多いモデルもありますが,キーボードなどを作ろうとすると,8×8の16ピン使用しても64個しかつけられません.16ピン稼ぐのは他のマイコンでもそこそこ大変です.そこで,今回は74HC595と74HC165を使用して,お手軽にGPIOを増やそうと思います.

はじめに

そもそも,74HC595と74HC165とは何なのかというと,どちらも只の8bitのシフトレジスターです.どちらもシリアルパラレル変換に主に使用されます.
それぞれ,秋月のリンクを張っておきます.

8ビットシフトレジスター U74HC595AG-D16-T: 半導体 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作8ビットシフトレジスター U74HC595AG-D16-T秋月電子通商 電子部品通信販売
8ビットシフトレジスター TC74HC165AP: 半導体 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作8ビットシフトレジスター TC74HC165AP秋月電子通商 電子部品通信販売

秋月価格で595は40円,165は80円(少し高い)です.

74HC595

シリアル入力-パラレル出力をしてくれるICです.OUTPUTピンを増やしたいときに使えます.以下のサイトがわかりやすく書いていてくれています.

「74HC595」の解説
用語「74HC595」の意味を解説しています。

データシートからピン配置とロジック回路図を見てみます.

中身を見ると,D-FFをつなげただけなのが分かります.
主要なピンを軽く説明すると以下のようになります.

  • SRCLR…ピンのクリアに使われる.負論理なので普段はHIGHにしておきます
  • SRCLK…データをシフトするのに使われる.このクロックの立ち上がったタイミングでD-FFのDへの入力がQの出力になる.
  • SER…出力したいシリアルのデータを入力するピン.SER->CLK->SER->CLK…の様にデータ入力とクロックを繰り返してデータをセットしていく.
  • RCLK…これをLOW->HIGHにしたタイミングで,下の出力保存用のD-FFの出力Qが確定する.なので,全データがセットし終わって,出力を始めるときにHIGHにする.
  • OE…出力有効無効のピン.負論理なので常にLOWにしておく.

よって,最低限制御しないといけないのはSRCLK,SER,RCLKの3本です.また,QH’を使用すればどんどん595を増やしていけます.

74HC165

パラレル入力-シリアル出力をしてくれるICです.INPUTピンを増やしたいときに使えます.以下のサイトがわかりやすく書いていてくれています.こちらも,先程のサイトが参考になります.

「74HC165」の解説
用語「74HC165」の意味を解説しています。

こちらもデータシートからピン配置とロジック回路図を見てみます.

中身を見るとこちらも,D-FFをつなげただけなのが分かります.
主要なピンを軽く説明すると以下のようになります.

  • SH/LD…ピンの入力を確定します.A-Hの入力を読み込みたいタイミングでLOWにし,読み込み終わったらHIGHにします.負論理なので注意
  • CLK…データをシフトするのに使われる.このクロックの立ち上がったタイミングのDの入力がQになる.
  • QH…最後のD-FFの出力Qが出てくる.QH->CLK->QH->CLK…の様にデータ出力とクロックを繰り返してデータを読み取る.
  • CLK INH…クロックの入力を受け付けるか選ぶ.HIGHだとFFに入るパルスが立ち上がったままになるので常にLOWにしておく
  • OE…出力有効無効のピン.負論理なので常にLOWにしておく

よって,最低限制御しないといけSH/LD,CLK,QHになります.こちらもSERとQHを使えば,どんどんつなげることができます.

回路図

今回の回路は以下のようになります.

小さくて申し訳ないです.
CH552Eのピンが少ないのでCLKと{RCLK,SH/LD}を共有することで4ピンで両方のICを制御します.他のマイコンでも,ピン節約したいときはこれらを共有することで節約できます.試してはいませんが,入力と出力を切り替えれば,SERとQHも1ピンに節約できそうです.
165への入力にはプルアップをしています.
やってはいませんが,LEDを一気に全点灯すると電流的にやばいかも.

コード

以下の動作をするコードです.

  • ボタンの入力(負論理)を読み取ってシリアルモニターに出力する
  • 100[ms]おきに,順番にLEDを点灯していきます.
#include <Serial.h>
#define CLK 14
#define LATCH 15
#define SERIAL_OUTPUT 16
#define SERIAL_INPUT 17

uint8_t readData() {
  uint8_t result = 0;
  digitalWrite(CLK, LOW);
  digitalWrite(LATCH, LOW);
  digitalWrite(LATCH, HIGH);
  for (int i = 0; i < 8; i++) {
    result |= ((digitalRead(SERIAL_INPUT) & 0x01) << i);
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
  }
  return result;
}
void sendData(uint8_t send_data) {
  digitalWrite(CLK, LOW);
  uint8_t mask = 0x01;
  digitalWrite(LATCH, LOW);
  for (int i = 0; i < 8; i++) {
    digitalWrite(SERIAL_OUTPUT, send_data & mask);
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
    mask = mask << 1;
  }
  digitalWrite(LATCH, HIGH);
}
void setup() {
  pinMode(CLK, OUTPUT);
  pinMode(LATCH, OUTPUT);
  pinMode(SERIAL_OUTPUT, OUTPUT);
  pinMode(SERIAL_INPUT, INPUT);
  digitalWrite(LATCH, LOW);
  digitalWrite(CLK, LOW);
}

void loop() {
  uint8_t result = readData();
  USBSerial_println_ib(result, BIN);  
  for (int i = 0; i < 8; i++) {
    sendData(1 << i);
    delay(100);
  }
}

Serial Printの部分がArduinoとは少し違うので注意です.書き込み時は,USB SettingsをDefaul CDCにしておきます.書き込みに関しては以下で説明しています.

参考までにArduino nanoでのコードは以下になります.

#define CLK A1
#define LATCH A2
#define SERIAL_OUTPUT A3
#define SERIAL_INPUT A4
void setup() {
  pinMode(CLK, OUTPUT);
  pinMode(LATCH, OUTPUT);
  pinMode(SERIAL_OUTPUT, OUTPUT);
  pinMode(SERIAL_INPUT, INPUT);
  digitalWrite(LATCH, LOW);
  digitalWrite(CLK, LOW);
  Serial.begin(9600);
}
void loop() {
  uint8_t result = readData();
  Serial.println(result, BIN);
  for (int i = 0; i < 8; i++) {
    sendData(1 << i);
    delay(100);
  }
}

uint8_t readData() {
  uint8_t result = 0;
  digitalWrite(CLK, LOW);
  digitalWrite(LATCH, LOW);
  digitalWrite(LATCH, HIGH);
  for (int i = 0; i < 8; i++) {
    result |= ((digitalRead(SERIAL_INPUT) & 0x01) << i);
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
  }
  return result;
}
void sendData(uint8_t send_data) {
  uint8_t mask = 0x01;
  digitalWrite(CLK, LOW);
  digitalWrite(LATCH, LOW);
  for (int i = 0; i < 8; i++) {
    digitalWrite(SERIAL_OUTPUT, send_data & mask);
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
    mask = mask << 1;
  }
  digitalWrite(LATCH, HIGH);
}

動作結果

以下の動画のように動きます.

終わりに

今回はCH552Eで74HC595及び74HC165を使用してGPIOを増やしてみました.マイコンのピンをお手軽に増やしたい場合は結構使えます.
よかったら参考にしてみてください.

コメント

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