[其他芯片] CH455G在ESP32中的应用

[复制链接]
515|0
袁胜富 发表于 2025-10-24 15:36 | 显示全部楼层 |阅读模式
DIGI, , se, ig,

1.电路图
6839968fb282aac465.png

2.从手册知道CH455G的INT引脚为SEG7,但是要设置工作在7段模式。此外通过esp32的IIC的地址来看可以把CH455G的读地址写为:(0x4F-0x01)/0x02=0x27,写地址分为(0x48-0x00)/0x02 = 0x24.
4778268fb28b710ce3.png
3.ch455.h
#ifndef ch_455
#define ch_455

#include <Arduino.h>
#include "Wire.h"

class ch455
{
public:
    enum digitSegReadUnit_t
    {
        DIG0_SEG0 = 0x04,
        DIG0_SEG1 = 0x0c,
        DIG0_SEG2 = 0x14,
        DIG0_SEG3 = 0x1c,
        DIG0_SEG4 = 0x24,
        DIG0_SEG5 = 0x2c,
        DIG0_SEG6 = 0x34,
        DIG0_SEG0_1 = 0x3c,
        DIG1_SEG0 = 0x05,
        DIG1_SEG1 = 0x0d,
        DIG1_SEG2 = 0x15,
        DIG1_SEG3 = 0x1d,
        DIG1_SEG4 = 0x25,
        DIG1_SEG5 = 0x2d,
        DIG1_SEG6 = 0x35,
        DIG1_SEG0_1 = 0x3d,
        DIG2_SEG0 = 0x06,
        DIG2_SEG1 = 0x0e,
        DIG2_SEG2 = 0x16,
        DIG2_SEG3 = 0x1e,
        DIG2_SEG4 = 0x26,
        DIG2_SEG5 = 0x2e,
        DIG2_SEG6 = 0x36,
        DIG2_SEG0_1 = 0x3e,
        DIG3_SEG0 = 0x07,
        DIG3_SEG1 = 0x0f,
        DIG3_SEG2 = 0x17,
        DIG3_SEG3 = 0x1f,
        DIG3_SEG4 = 0x27,
        DIG3_SEG5 = 0x2f,
        DIG3_SEG6 = 0x37,
        DIG3_SEG0_1 = 0x3f,
    };

    ch455();
    void begin(uint8_t sda, uint8_t scl, uint8_t ledBrightness = 8, bool enabled = true, bool sleep = false, bool sevenSegment = false);
    void begin(uint8_t ledBrightness = 8, bool enabled = true, bool sleep = false, bool sevenSegment = false);
    void customDigit(uint8_t digit, bool seg0, bool seg1, bool seg2, bool seg3, bool seg4, bool seg5, bool seg6, bool seg7);
    void customDigit(uint8_t digit, uint8_t digitData);
    uint8_t readKeyboard();
    void digit(uint8_t digit, uint8_t number, bool dot = 0);
    void dotPosition(bool dot0, bool dot1 = 0, bool dot2 = 0, bool dot3 = 0);
    void show(uint8_t digit0, uint8_t digit1 = 0, uint8_t digit2 = 0, uint8_t digit3 = 0);
    void showWithDots(uint8_t digit0, bool dot0 = 0, uint8_t digit1 = 0, bool dot1 = 0, uint8_t digit2 = 0, bool dot2 = 0, uint8_t digit3 = 0, bool dot3 = 0);
    void configure(uint8_t brightness, bool enabled = true, bool sleep = false, bool sevenSegment = false);

private:
    void send(uint8_t id, uint8_t data);
    bool
        dotset = 0,
        dotP0,
        dotP1,
        dotP2,
        dotP3;
};

#endif


ch455.cpp




4.ch455.cpp

#include "ch455.h"
#include "Wire.h"

void ch455::send(uint8_t id, uint8_t data)
{
    Wire.beginTransmission(id);
    Wire.write(data);
    Wire.endTransmission();
}

void ch455::configure(uint8_t brightness, bool enabled, bool sleep, bool sevenSegment)
{
    if (brightness > 8)
        brightness = 8;
    else if (brightness < 1)
        brightness = 1;

    if (brightness < 8)
        brightness = (16 * brightness);

    bitWrite(brightness, 0, enabled);
    bitWrite(brightness, 2, sleep);
    bitWrite(brightness, 3, sevenSegment);
    //(0x48-0)/2 = 36
    send(36, brightness);
}

ch455::ch455() {}

void ch455::begin(uint8_t brightness, bool enabled, bool sleep, bool sevenSegment)
{
    Wire.begin();
    ch455::configure(brightness);
}

void ch455::begin(uint8_t sda, uint8_t scl, uint8_t brightness, bool enabled, bool sleep, bool sevenSegment)
{
    Wire.begin(sda, scl);
    ch455::configure(brightness, true, false, true);
}

uint8_t ch455::readKeyboard()
{
    //(0x4f-1)/2 = 39
    uint8_t bytesReceived = Wire.requestFrom(39, 1);
    if ((bool)bytesReceived)
    { // If received more than zero bytes
        return Wire.read();
    }
    return 0x00;
}

void ch455::customDigit(uint8_t digit, bool seg0, bool seg1, bool seg2, bool seg3, bool seg4, bool seg5, bool seg6, bool seg7)
{
    byte digitData = 0x00;
    bitWrite(digitData, 0, seg0);
    bitWrite(digitData, 1, seg1);
    bitWrite(digitData, 2, seg2);
    bitWrite(digitData, 3, seg3);
    bitWrite(digitData, 4, seg4);
    bitWrite(digitData, 5, seg5);
    bitWrite(digitData, 6, seg6);
    bitWrite(digitData, 7, seg7);

    digit += 52;

    send(digit, digitData);
}

void ch455::customDigit(uint8_t digit, uint8_t digitData)
{
    digit += 52;

    send(digit, digitData);
}

void ch455::digit(uint8_t digit, uint8_t number, bool dot)
{
    if (number > 9 || digit > 3)
    {
        Serial0.println("CH455 Library: Number or digit is too big, max 9 for number and max 3 for digit");
        return;
    }

    digit += 52;

    uint8_t digitData = 0x3F;

    switch (number)
    {
    case 1:
        digitData = 0x06;
        break;
    case 2:
        digitData = 0x5B;
        break;
    case 3:
        digitData = 0x4F;
        break;
    case 4:
        digitData = 0x66;
        break;
    case 5:
        digitData = 0x6D;
        break;
    case 6:
        digitData = 0x7D;
        break;
    case 7:
        digitData = 0x27;
        break;
    case 8:
        digitData = 0x7F;
        break;
    case 9:
        digitData = 0x6F;
        break;
    }

    bitWrite(digitData, 7, dot);
    send(digit, digitData);
}

void ch455::showWithDots(uint8_t digit0, bool dot0, uint8_t digit1, bool dot1, uint8_t digit2, bool dot2, uint8_t digit3, bool dot3)
{
    digit(0, digit0, dot0);
    digit(1, digit1, dot1);
    digit(2, digit2, dot2);
    digit(3, digit3, dot3);
}

void ch455::show(uint8_t digit0, uint8_t digit1, uint8_t digit2, uint8_t digit3)
{
    if (!dotset)
    {
        Serial0.println("CH455 Library: Please set dot position first.");
        return;
    }
    digit(0, digit0, dotP0);
    digit(1, digit1, dotP1);
    digit(2, digit2, dotP2);
    digit(3, digit3, dotP3);
}

void ch455::dotPosition(bool dot0, bool dot1, bool dot2, bool dot3)
{
    dotP0 = dot0;
    dotP1 = dot1;
    dotP2 = dot2;
    dotP3 = dot3;
    dotset = 1;
}






6.main.cpp







#include <Arduino.h>
#include "INO_Library/INO_Timer.h"
#include "CH455.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>

#define Beep 42
#define CH455_SCL 1
#define CH455_SDA 2
#define CH455_INT 41

// 定义蜂鸣器控制消息类型
typedef struct
{
  uint32_t duration_ms; // 蜂鸣器持续时间(毫秒)
} beep_command_t;

// 全局变量
ch455 ch455g;
QueueHandle_t beep_queue;             // 蜂鸣器控制队列
TaskHandle_t beep_task_handle = NULL; // 蜂鸣器任务句柄

// 蜂鸣器控制任务函数
void beep_control_task(void *parameter)
{
  bool beep_active = false;
  uint32_t beep_end_time = 0;

  while (1)
  {
    beep_command_t command;

    // 检查是否有新的蜂鸣命令(非阻塞方式)
    if (xQueueReceive(beep_queue, &command, 10 / portTICK_PERIOD_MS) == pdTRUE)
    {
      digitalWrite(Beep, HIGH);
      beep_active = true;
      beep_end_time = millis() + command.duration_ms;
    }

    // 检查当前蜂鸣是否需要关闭
    if (beep_active && millis() >= beep_end_time)
    {
      digitalWrite(Beep, LOW);
      beep_active = false;
    }

    // 短暂延时,让出CPU时间
    vTaskDelay(1 / portTICK_PERIOD_MS);
  }
}

// 发送蜂鸣命令函数
void beep_start(uint32_t duration_ms)
{
  beep_command_t command = {
      .duration_ms = duration_ms};

  // 发送命令到蜂鸣器队列(如果队列满则覆盖旧命令)
  xQueueOverwrite(beep_queue, &command);
}

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

  // 初始化CH455键盘
  ch455g.begin(CH455_SDA, CH455_SCL, 8, true, false, true);
  pinMode(CH455_INT, INPUT_PULLUP);

  // 初始化蜂鸣器
  pinMode(Beep, OUTPUT);
  digitalWrite(Beep, LOW);

  // 创建蜂鸣器控制队列(长度为1)
  beep_queue = xQueueCreate(1, sizeof(beep_command_t));

  // 创建蜂鸣器控制任务
  xTaskCreate(
      beep_control_task, // 任务函数
      "Beep Control",    // 任务名称
      2048,              // 栈大小
      NULL,              // 参数
      2,                 // 优先级(高于loop任务)
      &beep_task_handle  // 任务句柄
  );

  Serial0.println("System started with beep control thread");
}

void loop()
{
  // 检测键盘中断
  if (digitalRead(CH455_INT) == LOW)
  {
    Serial0.print("Have Key Press:0x");
    uint8_t Keycode = ch455g.readKeyboard();
    Serial0.println(Keycode, 16);

    // 发送蜂鸣命令(100ms)
    beep_start(100);

    // 添加短暂延时防止重复检测
    delay(80);
  }
  else
  {
    uint8_t Keycode = ch455g.readKeyboard();
    if (Keycode & 0x40) // 按键按下没有释放
    {
      Serial0.println("Key NoRelase");
    }
    delay(80);
  }

}



7.测试效果,按下蜂鸣器响一声,打印对于的键值
8562868fb2c4d208f3.png






5855568fb2b3a083d2.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

166

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部