参考借鉴:SC12B12官方手册
1. 概览
1.1 概述
SC12B 是带自校正的容性触摸感应器,可以检测 12 个感应盘是否被触摸。它可以通过任何非导电介质 (如玻璃和塑料)来感应电容变化。这种电容感应的开关可以应用在很多电子产品上,提高产品的附加值。
1.2 特征
- 12 个完全独立的触摸感应按键
- 保持自动校正,无需外部干预
- 按键输出经过完全消抖处理
- 多接口 – I 2C 串行接口 / BCD 码输出
- 多种灵敏度调节方式 – 共用灵敏度电容/寄存器配置
- 空闲状态可以节省功耗
- 2.5V ~ 6.0V 工作电压
- 符合 RoHS 指令的环保 SSOP-24(0.635)封装
1.2 封装
1.3 管脚
1.3.1 管脚说明
VDD, GND :
电源正负输入端。
CMOD :
电荷收集电容输入端,接固定值的电容,和灵敏度无关。
CDC :
接灵敏度电容,电容范围是最小5pf,最大100pf。根据使用环境选择合适的电容值,数值越
小,灵敏度越高。
SC12B 规格书 v1.1
4/24
CIN0~CIN11 :
接感应盘,是感应电容的输入检测端口。
BCD3~BCD0 :
BCD码输出端口。无按键时,全部输出高电平;有按键时,输出相应BCD码。多按键时,只输
出优先级最高的按键码。
ASEL:
I 2C器件地址选择端口。
SCL, SDA:
SCL 是I 2C时钟输入端口。SDA是I 2C数据输入输出端口。 SDA 端口有内部弱上拉。
INT:
触摸信号输出指示端口。有按键时输出高电平, 无按键时输出低电平。
2. 芯片功能
2.1 初始化时间
上电复位后,芯片需要300ms进行初始化,计算感应管脚的环境电容,然后才能正常工作。
2.2 灵敏度
灵敏度由CDC端口接的电容值决定。电容范围是最小5pf,最大100pf。数值越小,灵敏度越高。为了保证
灵敏度的一致性,CDC电容要求使用10%或以上的精度的涤纶电容、NPO材质电容或者COG材质电容为最佳。
务必在PCB布局时,将CDC电容尽量贴近IC放置。
2.3 自校正
根据外部环境温度和湿度等的漂移,按键电容基准参考值也会发生漂移,芯片会自动调整校正每个按键的
电容基准参考值,以适应当前环境的变化。
当检测到按键后,芯片会立即停止校正一段时间,这段时间大约 50 秒。停止校正时间一到,芯片会继续
自校正,如果当前按键还是持续有效,按键信息会被当做环境的漂移立即被更新,也就是说检测按键有效的时
间不会超过 50 秒。通过设置寄存器中的 KVF 位可以将按键修改为一直输出有效。
2.4 触摸反应时间
每个通道大约每隔12.5ms采样一次。经过按键消抖处理以后,检测到按键按下的反应时间大概是68毫秒,
检测按键离开的反应时间大概是44毫秒。所以检测按键的最快频率大概是每秒9次。如果想要提高反应速度,可
以设置内部寄存器,详情参考“控制寄存器 CTRL0中的RTM[1:0]”。
3. 应用电路
3.1 Start 和 Stop 信号
3.2 器件地址
4. I2C软件模拟读写代码
4.1 Driver_KEYBOARD.h
//
// Created by seven on 2024/10/23.
//
#ifndef HELLOWORLD_DRIVER_KEYBOARD_H
#define HELLOWORLD_DRIVER_KEYBOARD_H
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define I2C_SCL 1
#define I2C_SDA 2
#define KEYBOARD_INT GPIO_NUM_0
#define UNDONE 0
#define DONE 1
#define I2C_SDA_OUT_1 gpio_set_direction(I2C_SDA, GPIO_MODE_DEF_OUTPUT) //定义 SDA 输出
#define I2C_SDA_IN_0 gpio_set_direction(I2C_SDA, GPIO_MODE_DEF_INPUT) //定义 SDA 输入
#define SET_SDA_HIGH gpio_set_level(I2C_SDA, 1)
#define SET_SDA_LOW gpio_set_level(I2C_SDA, 0)
#define SET_SCL_HIGH gpio_set_level(I2C_SCL, 1)
#define SET_SCL_LOW gpio_set_level(I2C_SCL, 0)
#define READ_SDA gpio_get_level(I2C_SDA)
void KEYBOARD_Init(void);
#endif //HELLOWORLD_DRIVER_KEYBOARD_H
4.2 Driver_KEYBOARD.c
//
// Created by seven on 2024/10/23.
//
#include "Driver_KEYBOARD.h"
void Delay(uint32_t time) {
vTaskDelay(time / portTICK_PERIOD_MS);
}
void I2C_Start(void) {
I2C_SDA_OUT_1;
SET_SDA_HIGH;
SET_SCL_HIGH;
Delay(1);
SET_SDA_LOW;
Delay(1);
SET_SCL_LOW;
Delay(1);
}
uint8_t SendByteAndGetNACK(uint8_t dataToSend) {
uint8_t i;
I2C_SDA_OUT_1;
for (i = 0; i < 8; i++) {
SET_SCL_LOW;
Delay(1);
if ((dataToSend >> 7) & 0x01) {
SET_SDA_HIGH;
} else {
SET_SDA_LOW;
}
Delay(1);
SET_SCL_HIGH;
Delay(1);
dataToSend <<= 1;
}
SET_SCL_LOW;
Delay(3);
I2C_SDA_IN_0;
Delay(3);
SET_SCL_HIGH;
Delay(1);
i = 250;
while (i--) {
if (!READ_SDA) {
SET_SCL_LOW;
return 0;
}
}
SET_SCL_LOW;
return (1);
}
void I2C_Respond(uint8_t ACKSignal)
{
I2C_SDA_OUT_1;
SET_SDA_LOW;
SET_SCL_LOW;
if (ACKSignal){
SET_SDA_HIGH;
} else{
SET_SDA_LOW;
}
Delay(1);
SET_SCL_HIGH;
Delay(1);
SET_SCL_LOW;
}
void I2C_Stop()
{
SET_SCL_LOW;
I2C_SDA_OUT_1;
SET_SDA_LOW;
Delay(1);
SET_SCL_HIGH;
Delay(1);
SET_SDA_HIGH;
}
uint8_t I2C_Receive8Bit(void)
{
uint8_t i,buffer = 0;
I2C_SDA_IN_0;
SET_SCL_LOW;
for (i = 0; i < 8; i++)
{
Delay(1);
SET_SCL_HIGH;
buffer = (buffer<<1)|READ_SDA;
Delay(1);
SET_SCL_LOW;
}
return (buffer);
}
/*******************************************************************************************************************************
* SC12B 读取寄存器数值函数
deviceAddr 设置器件地址 REG 设置寄存器地址 DAT16 读取地址对应数据内容
**************************************************************************************************************************************/
bool I2C_Read_From_Device(uint8_t deviceAddr,uint8_t REG,uint16_t * DAT16)
{
uint8_t buf1,buf2;
I2C_Start();
if (SendByteAndGetNACK((deviceAddr<<1) & ~0x01)) {
I2C_Stop();
return UNDONE;
}
if (SendByteAndGetNACK(REG)) {
I2C_Stop();
return UNDONE;
}
I2C_Stop();
I2C_Start();
if (SendByteAndGetNACK((deviceAddr<<1) | 0x01)) {
I2C_Stop();
return UNDONE;
}
buf1 = I2C_Receive8Bit();
I2C_Respond(0);
buf2 = I2C_Receive8Bit();
I2C_Respond(1);
I2C_Stop();
* DAT16= ((uint16_t)buf1 <<8)|buf2;
return DONE;
}
void KEYBOARD_Init(void) {
gpio_config_t io_conf;
io_conf.pin_bit_mask = (1ULL << I2C_SCL) | (1ULL << I2C_SDA); //配置为引脚 1 和 2
io_conf.mode = GPIO_MODE_OUTPUT; //设置引脚为输出模式
io_conf.intr_type = 0; //禁用中断
gpio_config(&io_conf);
io_conf.intr_type = 1;// 配置为上升沿中断触发
io_conf.mode = GPIO_MODE_INPUT; //设置引脚为输入模式
io_conf.pin_bit_mask = (1ull << 0);
gpio_config(&io_conf);
}