
I2C制御による2桁7セグメント表示器の製作
はじめに
秋月電子で販売されたいるCH32V003を使用して、I2C通信、特にスレーブを活用について調べたいと思い、I2Cのスレーブ用の7セグメントの表示器を製作に取り組みました。
部品について
部品については表1の部品を使いました。7セグメントLEDの点灯制御にはダイナミック点灯制御を使用しています。
部品名 | 型番・値 | 備考 |
---|---|---|
マイコン | CH32v003J4M6 | 8ピン |
トランジスタアレイ | TBD62783AFG | 8ch ソースタイプ DMOS |
トランジスタアレイ | TBD62083AFG | 8ch シンクタイプ DMOS |
赤色7セグメントLED | A-2301SRD-A | アノードコモン |
チップ抵抗 | 100Ω,270Ω | 7セグメント電流制限用 |
チップ抵抗 | 4.7kΩ | I2Cプルアップ抵抗用 |
チップ抵抗 | 1kΩ | 電源確認用LED電流制限用 |
チップLED | OSO50805C1C | オレンジ 7セグメント電源確認 |
チップLED | OSY50805C1C | 黄色 マイコン用電源確認 |
コネクタ | S3B-XH-A | 制御プログラム書込み用 |
コネクタ | S4B-XH-A | I2Cデータ用 |
コネクタ | S2B-XH-A | 7セグメント電源用 |
回路図
回路図は下の図のようになります。
I2Cで受け取った7セグメントの表示データを74HC595でシリアル出力にして、ソース型のトランジスタアレイとシンク型のトランジスタアレイを使用して7セグメントLEDをダイナミック点灯をできるように回路を製作しています。
今回製作した回路を基板業者に発注して基板を製作しました。しかし、私の確認不足で設計にミスがあり、ジャンパををして修正しました。(回路図の回路は今回修修正したものの回路図です。)
プログラムについて
今回のCH32V003J4M6を利用したプログラム作成にはPlatformIOとFrameworkにch32v003funを利用して作成しました。CH32V003J4M6をI2Cのスレーブで動作させ、マスタから7セグメントの表示データを受け取り、1msごとに割込を入れて、7セグメントLEDをダイナミック点灯させています。メインの部分だけを掲載しています。プログラム全体は私のGitHubのリポジトリに置いてあるので見ていただけたらと思います。
メインプログラム
#include "ch32v003fun.h"
#include <stdint.h>
#include <stdio.h>
#include <systick.h>
#include <vcruntime.h>
#include "i2c_slave.h"
#define SER PC4 // シリアルデーア
#define RCLK PA2 // 書き込み
#define LATCH PA1 // ラッチ
#define DIGIT 2 // 桁数
volatile unsigned int timer1;
volatile unsigned char dig;
volatile uint8_t i2c_registers[32] = {0x00};
// 74HC595 データ出力処理
void shiftOut(unsigned short data){
unsigned char i;
// LATCH OFF
funDigitalWrite(LATCH, FUN_LOW);
// Write Data
for(i=0;i<16;i++){
//if((data >> i) & 0x01){ // LSB First
if((data << i) & 0x8000){ // MSB First
funDigitalWrite(SER, FUN_HIGH);
} else {
funDigitalWrite(SER, FUN_LOW);
}
// Clock HIGH
funDigitalWrite(RCLK, FUN_HIGH);
// Clock LOW
funDigitalWrite(RCLK, FUN_LOW);
}
// LATCH ON
funDigitalWrite(LATCH, FUN_HIGH);
}
int main(void) {
// システム初期化 -> 必ずいる!
SystemInit();
// 待機時間(ブートローダ待ち)
//Delay_Ms(100); //
// SysTick初期設定(1ms割込設定)
systick_init();
// Enable GPIOA,GPIOC, GPIOD and TIM1
RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC);
// PA1 is 10MHz Output alt func, push-pull(PWM CH2N)
funPinMode(PA1, GPIO_CFGLR_OUT_10Mhz_PP);
funPinMode(PA2, GPIO_CFGLR_OUT_10Mhz_PP);
funPinMode(PC4, GPIO_CFGLR_OUT_10Mhz_PP);
funPinMode(PC1, GPIO_CFGLR_OUT_10Mhz_AF_OD); // SDA
funPinMode(PC2, GPIO_CFGLR_OUT_10Mhz_AF_OD); // SCL
SetupI2CSlave(0x9, i2c_registers, sizeof(i2c_registers), NULL, NULL, false);
while (1) {
}
}
/*
* SysTick ISR - must be lightweight to prevent the CPU from bogging down.
* Increments Compare Register and systick_millis when triggered (every 1ms)
* NOTE: the `__attribute__((interrupt))` attribute is very important
*/
void SysTick_Handler(void) __attribute__((interrupt));
void SysTick_Handler(void)
{
// Increment the Compare Register for the next trigger
// If more than this number of ticks elapse before the trigger is reset,
// you may miss your next interrupt trigger
// (Make sure the IQR is lightweight and CMP value is reasonable)
SysTick->CMP += SYSTICK_ONE_MILLISECOND;
// 割込フラグクリア
SysTick->SR = 0x00000000;
// タイマ値更新
timer1++;
// ダイナミック点灯制御
if((dig++) >= DIGIT) dig = 0;
switch (dig) {
// 1の位
case 0x00: shiftOut( 0x0200 | (unsigned short)i2c_registers[dig]);
break;
// 10の位
case 0x01: shiftOut( 0x0400 | (unsigned short)i2c_registers[dig]);
break;
default: break;
}
}
最後に
今回はCH32V003のI2Cスレーブで動作させる実験を兼ねて7セグメントLEDの表示器を製作しました。価格が安いマイコンで簡単にI2Cが利用できるので、制御系の回路を作るときには役に立つと思います。皆さんの何か参考になれば嬉しいです。
投稿者の人気記事
-
keiske-hongyo
さんが
2025/04/20
に
編集
をしました。
(メッセージ: 初版)
-
keiske-hongyo
さんが
2025/04/20
に
編集
をしました。
(メッセージ: 文章の言い回しを変更)
ログインしてコメントを投稿する