2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

74HC595×2個で駆動する8桁7セグメントLEDモジュールのドライバ作成

Last updated at Posted at 2021-01-09

74HC595(シフトレジスタ)×2個でダイナミック駆動する8桁の7セグメントLED用のドライバを作成しました。
開発環境:VSCode + PlatformIO, ESP32-WROOM-32D
対象モジュール:下記画像のものです。
8digit_led.JPG

・数字、アルファベット、一部の記号の表示に対応しています。
・数字の直後のドットは数字のdpになります。
・今後、文字単位でのブリンク機能、表示全体のスクロール機能を追加するつもりです。

hc595led.h
//////////////////////////////////////////////////////////////////////////////
// a driver for 8-digit 7-segment LED driven dynamically by two 74HC595's.
// optimized for arduino ESP32-WROOM-32D (PlatformIO).
//////////////////////////////////////////////////////////////////////////////

#ifndef __H_HC595LED_H__
#define __H_HC595LED_H__

#include <Arduino.h>
#include <cstdio>

static volatile char _cRam[17];
static int _pinClk;     // SCK
static int _pinDat;     // DIO
static int _pinLatch;   // RCK
                        // GND
                        // 3.3V - 5V

// first byte (LSB first, inverted)
const unsigned int _getChar[] = {
  //         abcdefgp
  /*  0 */ 0b00000011, // 0
  /*  1 */ 0b10011111, // 1
  /*  2 */ 0b00100101, // 2
  /*  3 */ 0b00001101, // 3
  /*  4 */ 0b10011001, // 4
  /*  5 */ 0b01001001, // 5
  /*  6 */ 0b01000001, // 6
  /*  7 */ 0b00011011, // 7
  /*  8 */ 0b00000001, // 8
  /*  9 */ 0b00001001, // 9
  /* 10 */ 0b11111111, // blank
  /* 11 */ 0b11101101, // colon
  /* 12 */ 0b11111110, // .
  /* 13 */ 0b00010001, // A
  /* 14 */ 0b11000001, // B
  /* 15 */ 0b01100011, // C
  /* 16 */ 0b10000101, // D
  /* 17 */ 0b01100001, // E
  /* 18 */ 0b01110001, // F
  /* 19 */ 0b01000011, // G
  /* 20 */ 0b10010001, // H
  /* 21 */ 0b11011111, // I
  /* 22 */ 0b10000111, // J
  /* 23 */ 0b01010001, // K
  /* 24 */ 0b11100011, // L
  /* 25 */ 0b00010011, // M
  /* 26 */ 0b11010101, // N
  /* 27 */ 0b11000101, // O
  /* 28 */ 0b00110001, // P
  /* 29 */ 0b00100001, // Q
  /* 30 */ 0b11110101, // R
  /* 31 */ 0b11001001, // S
  /* 32 */ 0b11100001, // T
  /* 33 */ 0b11000111, // U
  /* 34 */ 0b10000011, // V
  /* 35 */ 0b10000001, // W
  /* 36 */ 0b10010001, // X
  /* 37 */ 0b10001001, // Y
  /* 38 */ 0b00100111, // Z
  /* 39 */ 0b11111101, // -
  /* 40 */ 0b00000010, // 0.
  /* 41 */ 0b10011110, // 1.
  /* 42 */ 0b00100100, // 2.
  /* 43 */ 0b00001100, // 3.
  /* 44 */ 0b10011000, // 4.
  /* 45 */ 0b01001000, // 5.
  /* 46 */ 0b01000000, // 6.
  /* 47 */ 0b00011010, // 7.
  /* 48 */ 0b00000000, // 8.
  /* 49 */ 0b00001000, // 9.
  // you can define character patterns here as you like.

};

// character map
const unsigned char _charMap[256] = {
//       0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
/* 0 */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* 1 */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* 2 */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 39, 12, 10, 
/* 3 */  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 11, 10, 10, 10, 10, 10,
/* 4 */ 10, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 
/* 5 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 10, 10, 10, 10, 10, 
/* 6 */ 10, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 
/* 7 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 10, 10, 10, 10, 10, 
/* 8 */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* 9 */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* a */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* b */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* c */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* d */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* e */ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
/* f */ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 10, 10, 10, 10, 10, 10, 
}; 

// second byte (LSB first)
const unsigned int _getDigit[8] = {
  0b00010000,
  0b00100000,
  0b01000000,
  0b10000000,
  0b00000001,
  0b00000010,
  0b00000100,
  0b00001000,
};

class HC595LED {
  private:
  static void task7segDrv(void *param) {
    for(;;) {
      for(int i = 0; i < 8; i++) {
        shiftOut(_pinDat, _pinClk, LSBFIRST, _cRam[i]);
        digitalWrite(_pinLatch, LOW);
        shiftOut(_pinDat, _pinClk, LSBFIRST, _getDigit[i]);
        digitalWrite(_pinLatch, HIGH);
        delay(1);
      }
    }
  }

  public:
  HC595LED(int pinClk, int pinDat, int pinLatch) {
    memset((void *)_cRam, 0, sizeof(_cRam));

    _pinClk = pinClk;
    _pinDat = pinDat;
    _pinLatch = pinLatch;
    pinMode(_pinClk, OUTPUT);
    pinMode(_pinDat, OUTPUT);
    pinMode(_pinLatch, OUTPUT);

    for(int i = 0; i < 16; i++) {
      digitalWrite(_pinLatch, LOW);
      shiftOut(_pinDat, _pinClk, LSBFIRST, 0b11111111);
      digitalWrite(_pinLatch, HIGH);
    }
    xTaskCreateUniversal(task7segDrv, "task7segDrv", 1024, NULL, 1, NULL, 1);
  }

  int setToLED(char *str) {
    int len;
    int i;
    char buf[20] = {0};

    strcpy(buf, str);
    len = strlen(buf);

    // join dot to a previous number,
    // and shorten the length of string by the number of dots.
    for(i = 1; i < len; i++) {
        if(buf[i] == '.' && buf[i - 1] >= '0' && buf[i - 1] <= '9') {
            buf[i - 1] += 0xc0;
            for(int j = 0; j < len - i; j++) {
                buf[i + j] = buf[i + j + 1];
            }
            len--;
        }
    }

    // set character patterns to C-RAM.
    for(i = 0; i < len; i++) {
      if(buf[i] == 0) {
        break;
      }
      _cRam[len - 1 - i] = _getChar[_charMap[buf[i]]];
    }
    _cRam[i] = 0;

    return 0;
  }
};

#endif /* __H_HC595LED_H__ */

動作確認用サンプルアプリケーションも掲載しておきます。

main.cpp
/////////////////////////////////////////////////////////////
// all you have to do is to include the header file below!
/////////////////////////////////////////////////////////////
#include "hc595led.h"

//#include <SPI.h>
#include <Arduino.h>
#include <FreeRTOS.h>
#include <WiFi.h>
//#include <WebServer.h>

void ntpTest(const char *srv) {
  configTime(9 * 3600, 0, srv);
  struct tm timeInfo;
  getLocalTime(&timeInfo);
  Serial.printf(" %04d/%02d/%02d %02d:%02d:%02d\n",
          timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
          timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
}

// declare the global instance. 
HC595LED led = HC595LED(17,   // SCK
                        21,   // DIO
                        22);  // RCK

void setup(void) {
  Serial.begin(115200);

  WiFi.begin("rs500m-14qaf8-1", "6a6a227fc3f17");
  while(WiFi.status() != WL_CONNECTED) {
    delay(250);
  }
  Serial.print("IP Addr. : ");
  Serial.println(WiFi.localIP());

  ntpTest("time.google.com");

  Serial.println("set-up done.");
}

void loop() {
  static char buf[20] = {0};
  struct tm timeInfo;

  getLocalTime(&timeInfo);
  sprintf(buf, "Jp%02d.%02d.%02d", timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
  led.setToLED(buf);

  // once a day at 3:59:59,
  if(timeInfo.tm_hour == 3 && timeInfo.tm_min == 59 && timeInfo.tm_sec == 59) {
      // adjust time
      led.setToLED("-adjust-");
      ntpTest("time.google.com");
      delay(1000);
  } else {
    delay(500);
  }  
}
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?