0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CH552Tマイコンで7seg制御のLチカボード Ver.1.0

Posted at

商品説明

この製品は、7セグメントLEDの制御を楽しむための電子工作キットです。
USB接続対応のCH552Tマイコンを使用して、手軽にプログラミング体験が可能。
RTCモジュール(別売)を接続すれば、時刻表示などの実用的な機能も追加できます。
遊んで学べる、ちょっと便利なマイコンアイテムとしてぜひお試しください!

ハードウェアの主な仕様

  • 7セグメントLEDを6桁分搭載。数値や時刻表示など、わかりやすく視覚化できます。
  • LEDドライバ搭載により、ダイナミック制御が簡素化されており、初級者の方でも扱いやすい設計です。
  • RTC(リアルタイムクロック)モジュールはボタン電池によるバックアップが可能で、電源が切れても時刻情報を保持します。
  • CH552Tを使ったUSBプログラミング対応で、手軽に制御や応用開発が可能です。

回路図詳細

電源ブロック
image.png

接続・保護機能について

  • 本製品はUSBでパソコンと直接接続することができ、USBシリアル変換器は不要です。
  • USBと制御回路の間にはスイッチIC「CH217K」を搭載しており、過電流が発生した際にはパソコンなどのUSBポートをしっかり保護します。
  • 安心して電子工作に取り組めるよう、扱いやすさと安全性を両立しています。

マイコンブロック
image.png

接続と構成のポイント

  • マイコンとTM1640 LEDドライバは、シリアル通信で接続されています。
  • RTCモジュールはI²C通信を利用して接続しており、時刻の取得や管理が可能です。
  • P3.3端子には、Lチカ制御用のLEDを搭載。プログラムの動作確認などにも便利です。
  • 高精度なタイミング制御は不要と判断し、24MHzの水晶発振子は非搭載としています。

LEDドライバブロック
image.png

TM1640 LEDドライバについて

  • TM1640 LEDドライバは最大16桁までの表示制御が可能ですが、本製品では6桁の7セグメントLEDに絞って使用しています。
  • 制御の負担を軽減し、扱いやすさを重視した構成となっています。
  • また、J4コネクタに5V電源を接続することで、USB接続なしでも時刻表示が可能になり、単体での動作にも対応しています。

7segおよびRTCモジュール接続ブロック

image.png
接続仕様と制御概要

  • 本製品の7セグメントLEDは、A〜Gのセグメントに加え、ドットポイント(DP)を含む計8つの制御線で構成されています。これらのセグメントはコモン(CC)と接続され、ダイナミック点灯方式により制御が簡素化されています。
  • マイコンのP3.0端子にはSCL(クロック)、P3.1端子にはSDA(データ)が割り当てられており、ソフトウェアI²C通信によってRTCモジュールと接続可能です。
  • 一部のマイコン端子には追加で接続用ランド(パッド)が用意されており、外部機器やカスタム配線を行う際にも活用できます。

参考制御コード

#include <SoftI2C.h>

// decimal → BCD 変換
uint8_t dec2bcd(uint8_t val) {
  return ((val / 10) << 4) | (val % 10);
}

void setup() {
  Wire_begin(30, 31);  // SDA = P3.1, SCL = P3.0
  I2CInit();
  USBSerial_println("RTC write start");

  uint8_t rtcAddr = 0x68;

  // 送信データ:先頭に0x00(レジスタアドレス)を追加
  __xdata uint8_t dataToSend[8] = {
    0x00,          // 書き込み先レジスタアドレス(秒から)
    dec2bcd(30),   // 秒
    dec2bcd(0),   // 分
    dec2bcd(10),   // 時
    dec2bcd(7),    // 曜日(1=日曜〜7=土曜)
    dec2bcd(19),   // 日
    dec2bcd(7),    // 月
    dec2bcd(25)    // 年(下2桁)
  };

  if (Wire_writeBytes(rtcAddr, dataToSend, 8)) {
    USBSerial_println("RTC time set OK!");
  } else {
    USBSerial_println("RTC time set FAILED!");
  }
}

void loop() {
  // ループ処理なし
}

RTCモジュールの時刻書き込みについて
RTC(リアルタイムクロック)モジュールへ時刻情報を書き込む際の参考プログラムをご用意しています。
設定は、プログラム内の「年月日」「曜日」「時分秒」などの項目にある括弧内の値を変更することで行えます。
なお、書き込みボタンを押してから実際にRTCへ反映されるまでには、パソコンの処理性能などにより数秒程度のタイムラグが発生することがあります。
そのため、実際の時刻よりも約5秒先の時間を設定すると、より正確に反映されやすくなります。

時刻表示参考プログラム

#include <Arduino.h>
#include <SoftI2C.h>  // CH552用ソフトI2C

#define PIN_DIN 16
#define PIN_SCLK 15

// dp-g-f-e-d-c-b-a
static uint8_t NumPattern[] = {
  0x7E, // 0
  0x06, // 1
  0x6B, // 2
  0x4F, // 3
  0x17, // 4
  0x5D, // 5
  0x7D, // 6
  0x0E, // 7
  0x7F, // 8
  0x5F  // 9
};

// ==== TM1640制御関数 ====

void sendStart() {
  digitalWrite(PIN_DIN, LOW);
  delayMicroseconds(10);
  digitalWrite(PIN_SCLK, LOW);
  delayMicroseconds(10);
}

void sendStop() {
  digitalWrite(PIN_SCLK, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_DIN, HIGH);
  delayMicroseconds(10);
}

void sendData(uint8_t data) {
  for (int i = 0; i < 8; i++) {
    digitalWrite(PIN_SCLK, LOW);
    digitalWrite(PIN_DIN, (data & 0x01) ? HIGH : LOW);
    delayMicroseconds(1);
    digitalWrite(PIN_SCLK, HIGH);
    delayMicroseconds(1);
    data >>= 1;
  }
  delayMicroseconds(1);
  digitalWrite(PIN_SCLK, LOW);
  digitalWrite(PIN_DIN, LOW);
  delayMicroseconds(1);
}

void sendComand(uint8_t data) {
  sendStart();
  sendData(data);
  sendStop();
}

void disp1Grid(uint8_t grid, uint8_t data) {
  sendComand(0x44);  // 固定アドレスモード
  sendStart();
  sendData((grid & 0x0F) | 0xC0);
  sendData(data);
  sendStop();
}

void setBrightness(uint8_t brightness) {
  brightness = (brightness & 0x06) | 0x88;
  sendComand(0x44);
  sendComand(brightness);
}

// ==== RTC関連 ====

__xdata uint8_t timeData[3]; // 秒、分、時格納

uint8_t bcd2dec(uint8_t val) {
  return ((val >> 4) * 10) + (val & 0x0F);
}

bool getTimeFromRTC() {
  uint8_t rtcAddr = 0x68;
  return Wire_readRegister(rtcAddr, 0x00, timeData, 3);
}

// ==== 初期化 ====

void setup() {
  Wire_begin(30, 31); // SDA = P3.1, SCL = P3.0
  I2CInit();

  pinMode(PIN_DIN, OUTPUT);
  pinMode(PIN_SCLK, OUTPUT);
  digitalWrite(PIN_DIN, HIGH);
  digitalWrite(PIN_SCLK, HIGH);

  sendComand(0x40);   // 自動アドレスモード(初期化)
  setBrightness(3);   // 明るさ(0~7)

  // 全グリッド消灯
  for (uint8_t i = 0; i < 6; i++) {
    disp1Grid(i, 0x00);
  }
}

// ==== メインループ ====

void loop() {
  if (getTimeFromRTC()) {
    uint8_t sec  = bcd2dec(timeData[0] & 0x7F);
    uint8_t min  = bcd2dec(timeData[1]);
    uint8_t hour = bcd2dec(timeData[2] & 0x3F); // 24時間制

    // 桁分解
    uint8_t digits[6] = {
      hour / 10, hour % 10,
      min / 10,  min % 10,
      sec / 10,  sec % 10
    };

    // 各グリッドに表示
    for (uint8_t i = 0; i < 6; i++) {
      disp1Grid(i, NumPattern[digits[i]]);
    }
  }

  delay(200); // 更新周期
}
  • RTCと7セグメント表示の動作について
    RTC(リアルタイムクロック)モジュールに記録された時刻データは、マイコンよりも高精度で安定して保持されます。
    マイコンはこの時刻情報を定期的に読み取り、時・分・秒のそれぞれを「10の位」「1の位」に分けて数値データとして処理。
    その情報をLEDドライバ経由で7セグメントLEDに送信することで、見やすく時刻を表示します。
    この動作はプログラムによって繰り返し実行され、常に現在時刻が表示されるようになっています。

RTCからのデータをシリアルモニタに表示させる

#include <SoftI2C.h>

// BCD → decimal 変換
uint8_t bcd2dec(uint8_t val) {
  return ((val >> 4) * 10) + (val & 0x0F);
}

void setup() {
  Wire_begin(30, 31);  // SDA = P3.1, SCL = P3.0
  I2CInit();           // ピン状態の初期化
  USBSerial_println("RTC read start");
}

void loop() {
  uint8_t rtcAddr = 0x68;
  __xdata uint8_t buffer[3];

  // 秒レジスタ(0x00)から3バイト(秒、分、時)を読み出す
  if (Wire_readRegister(rtcAddr, 0x00, buffer, 3)) {
    uint8_t rawSec  = buffer[0] & 0x7F;  // CHビット除去
    uint8_t rawMin  = buffer[1];
    uint8_t rawHour = buffer[2];

    USBSerial_print("Time → ");
    USBSerial_print(bcd2dec(rawHour)); USBSerial_print(":");
    USBSerial_print(bcd2dec(rawMin));  USBSerial_print(":");
    USBSerial_println(bcd2dec(rawSec));
  } else {
    USBSerial_println("I2C read error");
  }

  delay(1000);
}

シリアルモニタへの時刻表示について
RTCモジュールが正しく接続され、I²C通信が行えていれば、シリアルモニタ上に現在時刻が表示されます。
動作確認の例として、以下のような出力が一定間隔で更新されて表示されます:

Time → 10:03:43  
Time → 10:03:44  
Time → 10:03:45  

LED制御デモコード

 * TM1640 LED データ送信コード
 */
#include <Arduino.h>

#define PIN_DIN 16
#define PIN_SCLK 15

// 表示パターン(dp-g-f-e-d-c-b-a の順)
// static uint8_t dispPattern[] = {0x01, 0x02, 0x04, 0x08,
//                                 0x10, 0x20, 0x40, 0x80};

static uint8_t dispPattern[] = {0x08, 0x02, 0x04, 0x40,
                                0x20, 0x10, 0x01, 0x80};

static uint8_t NumPattern[] = {0x7E, 0x06, 0x6B, 0x4F, 0x17, 0x5D, 0x7D, 0x0E, 0x7F, 0x7E};


// 通信開始
void sendStart() {
  digitalWrite(PIN_DIN, LOW);
  delayMicroseconds(10);
  digitalWrite(PIN_SCLK, LOW);
  delayMicroseconds(10);
}

// 通信終了
void sendStop() {
  digitalWrite(PIN_SCLK, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_DIN, HIGH);
  delayMicroseconds(10);
}

// 1バイト送信
void sendData(uint8_t data) {
  for (int i = 0; i < 8; i++) {
    digitalWrite(PIN_SCLK, LOW);
    digitalWrite(PIN_DIN, (data & 0x01) ? HIGH : LOW);
    delayMicroseconds(1);
    digitalWrite(PIN_SCLK, HIGH);
    delayMicroseconds(1);
    data >>= 1;
  }
  delayMicroseconds(1);
  digitalWrite(PIN_SCLK, LOW);
  digitalWrite(PIN_DIN, LOW);
  delayMicroseconds(1);
}

// コマンド送信
void sendComand(uint8_t data) {
  sendStart();
  sendData(data);
  sendStop();
}

// グリッド指定で1バイト表示
void disp1Grid(uint8_t grid, uint8_t data) {
  sendComand(0x44);  // 固定アドレスモード
  sendStart();
  sendData((grid & 0x0F) | 0xC0);
  sendData(data);
  sendStop();
}

// 明るさ設定(0〜7)
void setBrightness(uint8_t brightness) {
  brightness = (brightness & 0x07) | 0x88;
  sendComand(0x44);
  sendComand(brightness);
}

void setup() {
  // ピン初期化
  pinMode(PIN_DIN, OUTPUT);
  pinMode(PIN_SCLK, OUTPUT);
  digitalWrite(PIN_DIN, HIGH);
  digitalWrite(PIN_SCLK, HIGH);

  // 初期コマンド
  sendComand(0x40);     // 自動アドレスモード
  setBrightness(3);     // 明るさ設定(中程度)

  // グリッド0〜5をすべて消灯
  for (uint8_t i = 0; i <= 5; i++) {
    disp1Grid(i, 0x00);
  }

  // 1桁目(グリッド0)に表示
  disp1Grid(0, dispPattern[0]);
}

void loop() {
  static uint8_t grid = 0;  // 現在のグリッド番号(初期は0)

  // dispPattern[0〜7] を順に送信(100ms間隔)
  for (int i = 0; i < 8; i++) {
    disp1Grid(grid, dispPattern[i]);
    delay(150);
  }

  // 次のグリッドへ
  grid++;

  // グリッドが6になったら全グリッド消灯してグリッド0へ戻す
  if (grid > 5) {
    for (uint8_t i = 0; i <= 5; i++) {
      disp1Grid(i, 0x00);  // 消灯パターン送信
    }
    grid = 0;
  }
}

各桁のLED制御について
このプログラムでは、7セグメントLEDの各桁を個別に点灯制御するためのパターンを定義しています。

static uint8_t dispPattern[] = {0x08, 0x02, 0x04, 0x40,
                                0x20, 0x10, 0x01, 0x80};

それぞれの値は、各LEDセグメントの制御信号に対応しており、どの場所を光らせるかを示すビットパターンとして機能します。
この配列を使うことで、特定の桁だけを順番に点灯させるなど、動きのある表示を簡単に実装することができます。

IMG20250715233806~2.jpg

参考プログラムについて
この参考プログラムは、本製品のボード構成に対応しています。
CH552Tマイコンを使って、I²C接続のモジュールと通信できることが確認でき、通信機能の活用に自信が持てるようになります。
今後は、さまざまなI²C対応デバイスとの接続にも応用できるため、工作やカスタマイズの幅が広がり、さらに楽しくご活用いただけます。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?