본문 바로가기
MCU/아두이노

아두이노에서 74HC165 (병렬 → 직렬 변환기) 사용하기

by linuxgo 2025. 9. 3.

1. 74HC165란?

74HC165는 8비트 병렬 입력을 직렬 데이터로 변환하는 PISO (Parallel-In Serial-Out) 시프트 레지스터입니다.
즉, 버튼, 스위치, 센서 등 여러 개의 입력을 동시에 받아서 아두이노 같은 MCU에 시리얼 데이터 한 줄로 보내주는 역할을 합니다.

74HC165

🔹 주요 특징 (사양 요약)

  • 입력 개수: 8비트 (D0~D7)
  • 출력 방식: 직렬 출력 (Q7 핀)
  • 클럭: 외부 클럭 입력(CP 핀)으로 데이터가 시프트됨
  • 래치 기능: PL (Parallel Load) 핀을 사용하여 병렬 데이터를 한번에 읽어와 래치 가능
  • 확장: 여러 개 칩을 직렬 연결하여 16비트, 24비트, 32비트… 무제한 확장 가능
  • 동작 전압: 2V ~ 6V (일반적으로 5V 아두이노와 호환)
  • 최대 클럭 속도: 약 25 MHz (Vcc=5V 기준)

2. 74HC165 핀 설명

핀 번호 이름 설명

  이름 이름 설명
1 (Q7) Q7 직렬 데이터 출력 (아두이노가 읽는 핀)
2 (CP) CLK 시프트 클럭 입력 (클럭마다 1비트 이동)
3~6,11~14 D0~D7 병렬 입력 (스위치, 버튼 등)
7 (Q7’) 시리얼 체인 출력 다음 74HC165로 연결 시 사용
8 GND 그라운드
9 (/PL) Parallel Load LOW 입력값을 래치
10 (/CE) Chip Enable LOW 활성화
15 (DS) 직렬 데이터 입력 체인 연결 시 사용
16 VCC 전원 (2~6V, 보통 5V)

3. 아두이노와 연결하기

  • PL → 아두이노 4번
  • CE → 아두이노 5번
  • CLK (CP) → 아두이노 6번
  • Q7 → 아두이노 7번
  • 버튼 → D0~D7 (풀업 저항 또는 내부 풀업 사용 가능)

여러 개의 74HC165를 확장할 경우, Q7’ → 다음 칩의 DS 로 연결합니다.

4. 아두이노용 74HC165 라이브러리

여기서는 확장 지원 버전 라이브러리를 작성했습니다.
최대 64비트(74HC165 8개 직렬 연결)까지 읽을 수 있도록 했습니다.

📄 74HC165.h

#ifndef SHIFT74HC165_H
#define SHIFT74HC165_H

#include <Arduino.h>

/**
 * @brief 74HC165 병렬-직렬 변환기(PISO) 제어 클래스
 * 
 * 기능:
 * - 병렬 입력을 래치하여 직렬 데이터로 변환
 * - 여러 개의 74HC165를 직렬 연결해 확장 가능
 */
class Shift74HC165 {
  public:
    /**
     * @brief 생성자
     * 
     * @param plPin   PL (Parallel Load) 핀 번호
     * @param cePin   CE (Chip Enable) 핀 번호
     * @param clkPin  CP (Clock) 핀 번호
     * @param dataPin Q7 (Serial Data Out) 핀 번호
     * @param chips   직렬로 연결된 칩 개수 (기본값 1)
     */
    Shift74HC165(uint8_t plPin, uint8_t cePin, uint8_t clkPin, uint8_t dataPin, uint8_t chips = 1);

    /**
     * @brief 초기화 (핀 모드 설정)
     */
    void begin();

    /**
     * @brief 입력 값 읽기 (최대 32비트)
     * 
     * @return 32비트 정수 값 (chips * 8 비트까지만 유효)
     */
    uint32_t read();

    /**
     * @brief 입력 값 읽기 (최대 64비트)
     * 
     * @return 64비트 정수 값 (chips * 8 비트까지만 유효)
     */
    uint64_t read64();

  private:
    uint8_t _plPin;
    uint8_t _cePin;
    uint8_t _clkPin;
    uint8_t _dataPin;
    uint8_t _chips;
};

#endif

📄 74HC165.cpp

#include "74HC165.h"

Shift74HC165::Shift74HC165(uint8_t plPin, uint8_t cePin, uint8_t clkPin, uint8_t dataPin, uint8_t chips) {
  _plPin = plPin;
  _cePin = cePin;
  _clkPin = clkPin;
  _dataPin = dataPin;
  _chips = chips;
}

void Shift74HC165::begin() {
  pinMode(_plPin, OUTPUT);
  pinMode(_cePin, OUTPUT);
  pinMode(_clkPin, OUTPUT);
  pinMode(_dataPin, INPUT);

  // 기본 상태
  digitalWrite(_plPin, HIGH);  // PL은 HIGH일 때 시프트 가능
  digitalWrite(_cePin, LOW);   // CE는 LOW일 때 활성화
  digitalWrite(_clkPin, LOW);  // CLK 초기화
}

uint32_t Shift74HC165::read() {
  uint32_t value = 0;

  // 병렬 입력을 래치
  digitalWrite(_plPin, LOW);
  delayMicroseconds(5);
  digitalWrite(_plPin, HIGH);

  // 직렬 데이터 읽기 (chips * 8 비트)
  for (int i = 0; i < _chips * 8 && i < 32; i++) {
    value <<= 1;
    value |= digitalRead(_dataPin);  // 현재 비트 읽기
    digitalWrite(_clkPin, HIGH);     // 클럭 펄스
    delayMicroseconds(2);
    digitalWrite(_clkPin, LOW);
  }

  return value;
}

uint64_t Shift74HC165::read64() {
  uint64_t value = 0;

  // 병렬 입력을 래치
  digitalWrite(_plPin, LOW);
  delayMicroseconds(5);
  digitalWrite(_plPin, HIGH);

  // 직렬 데이터 읽기 (chips * 8 비트, 최대 64비트)
  for (int i = 0; i < _chips * 8 && i < 64; i++) {
    value <<= 1;
    value |= digitalRead(_dataPin);
    digitalWrite(_clkPin, HIGH);
    delayMicroseconds(2);
    digitalWrite(_clkPin, LOW);
  }

  return value;
}

5. 예제 코드 (16비트 입력 읽기)

#include <74HC165.h>

// 핀 연결 설정
const int PL_PIN = 4;   // Parallel Load (PL)
const int CE_PIN = 5;   // Chip Enable (CE)
const int CLK_PIN = 6;  // Clock (CP)
const int DATA_PIN = 7; // Serial Data Out (Q7)

// 74HC165 두 개 직렬 연결 → 16비트 입력
Shift74HC165 shift(PL_PIN, CE_PIN, CLK_PIN, DATA_PIN, 2);

void setup() {
  Serial.begin(9600);
  shift.begin();
}

void loop() {
  // 16비트 입력값 읽기
  uint32_t inputs = shift.read();

  // 이진수 출력 (16자리로 맞춤)
  Serial.print("Inputs: ");
  for (int i = 15; i >= 0; i--) {
    Serial.print((inputs >> i) & 1);
  }
  Serial.println();

  delay(500);
}

출력 예시:

Inputs: 1011001101010011

 

6. 활용 아이디어

  • 버튼 입력 확장 (게임 패드, 키보드, 컨트롤러 등)
  • 센서 배열 데이터 수집
  • 로봇 제어용 스위치 패널
  • 최대 64비트까지 확장 가능 (74HC165 8개 연결)