1.电路图
2.从手册知道CH455G的INT引脚为SEG7,但是要设置工作在7段模式。此外通过esp32的IIC的地址来看可以把CH455G的读地址写为:(0x4F-0x01)/0x02=0x27,写地址分为(0x48-0x00)/0x02 = 0x24.
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.测试效果,按下蜂鸣器响一声,打印对于的键值
|