SC12B驱动

这里只是把数据手册中使用到的重要部分摘取出来,完整版请看SC12B.pdf,这只是这个项目中的一个驱动代码,后续继续更新项目代码。项目实现功能请先看,智能门锁专栏 / 智能门锁功能实现这篇文章,里面介绍了实现的功能,后续将更新详细项目介绍

一. 简介

  • SC12B 是带自校正的容性触摸感应器,可以检测12个感应盘是否被触摸。它可以通过任何非导电介质 (如玻璃和塑料)来感应电容变化。

  • 12个完全独立的触摸感应按键

  • 保持自动校正,无需外部干预

  • 按键输出经过完全消抖处理

  • 多接口 – I2C 串行接口 / BCD码输出

  • 多种灵敏度调节方式 – 共用灵敏度电容/寄存器配置

  • 空闲状态可以节省功耗

  • 引脚说明

    管脚编号 名称 类型 功能 不使用时
    1 GND Pwr 电源地 -
    2 CMOD I/O 接电荷收集电容 -
    3 CDC I/O 接灵敏度电容 -
    4 CIN0 I/O 感应按键0检测输入 悬空
    5 CIN1 I/O 感应按键1检测输入 悬空
    6 CIN2 I/O 感应按键2检测输入 悬空
    7 CIN3 I/O 感应按键3检测输入 悬空
    8 CIN4 I/O 感应按键4检测输入 悬空
    9 CIN5 I/O 感应按键5检测输入 悬空
    10 CIN6 I/O 感应按键6检测输入 悬空
    11 CIN7 I/O 感应按键7检测输入 悬空
    12 CIN8 I/O 感应按键8检测输入 悬空
    13 CIN9 I/O 感应按键9检测输入 悬空
    14 CIN10 I/O 感应按键10检测输入 悬空
    15 CIN11 I/O 感应按键11检测输入 悬空
    16 BCD3 O BCD码输出 悬空
    17 BCD2 O BCD码输出 悬空
    18 BCD1 O BCD码输出 悬空
    19 BCD0 O BCD码输出 悬空
    20 ASEL I 地址选择引脚 悬空
    21 SCL I I2C 时钟输入 连接GND或VDD
    22 SDA I/O I2C 数据输入输出 连接GND或VDD 或者悬空
    23 INT O 触摸指示输出
    24 VDD Pwr 电源正极 -

    VDD, GND :电源正负输入端。

    CMOD :电荷收集电容输入端,接固定值的电容,和灵敏度无关。

    CDC :接灵敏度电容,电容范围是最小5pf,最大100pf。根据使用环境选择合适的电容值,数值越小,灵敏度越高。

    CIN0~CIN11 :接感应盘,是感应电容的输入检测端口。

    BCD3~BCD0 :BCD码输出端口。无按键时,全部输出高电平;有按键时,输出相应BCD码。多按键时,只输 出优先级最高的按键码。

    ASEL:I2C器件地址选择端口。

    SCL, SDA:SCL 是I2C时钟输入端口。SDA是I2C数据输入输出端口。 SDA 端口有内部弱上拉。

    INT: 触摸信号输出指示端口。有按键时输出高电平, 无按键时输出低电平。

二. 关键参数

  • 使用I2C通信,读写地址,因为开发板的ASEL接地,所以后面地址使用0x42

    状态 ASEL为高电平 ASEL悬空 ASEL为低电平
    地址 (A[6:0]) 44H 40H 42H
    读命令 (A[6:0]+RWB) 89H 81H 85H
    写命令 (A[6:0]+RWB) 88H 80H 84H
  • 寄存器列表

    image-20250814130932130

      1. 灵敏度控制寄存器 SenSet0(地址 00H) SenSetCOM (地址 01H)

      SENCH0[7:0] CIN4 的灵敏度设置

      SENCOM[7:0] 其余通道的灵敏度设置

      共有 16 档灵敏度可以设置, 由低到高为:【04H】 【15H】 【25H】 【36H】 【47H】 【58H】 【68H】【79H】 【8AH】 【9BH】 【ACH】 【BCH】 【CDH】 【DEH】 【EFH】 【FFH】 其中 79H 为初始值。该寄存器涉及到手指触摸阈值及手指离开阈值,如无特殊运用,建议客户按照如上参数设置。CIN4 单独设置灵敏度是可以把这个按键当做接近感应电极来用,或者隔空唤醒功能,如果 用作普通按键,把SENCH0[7:0]设成和SENCOM[7:0]一样就可以了。

      1. **控制寄存器 **CTRL0(地址 02H) SLPCYC[2:0] 睡眠时, 采样周期间隔,设置越大,唤醒速度越慢,功耗越低。

      image-20250814131259742

      1. 控制寄存器 CTRL1(地址 03H)

        CSEL3~CSEL0:内部基准通道电容的选择,默认值为 1000,对应的电容选择为8PF,该值一般 用来修正外部通道的触摸感应量,该值可以设定范围0100~1111,对应值电容选择为4PF~15PF, 如无特殊应用,建议设置默认值8PF。

      1. 按键信息寄存器 Output0 (地址 08H) Output1 (地址 09H)

        CH[11:0] 分别对应 CIN[11:0]的按键情况。 无按键时为0, 有按键时为1。

      1. **采样值寄存器 **SAMPH (地址 0AH) SAMPL (地址 0BH)

        CS[3:0] 采样值对应的通道,采样时候对应是采样13个通道,而我们SC012B通道CIN0到CIN11 对应是内部通道1到12。即当读取到CS值为1的时候,对应的SAMP值即为对应CIN0的采样值。 SAMP[11:0] 采样值

image-20250814131851042

  • 如果在一段时间内(75秒左右)没有检测到按键并且SDA端口一直保持高电平,芯片会自动进入省电模式。 只要让SDA保持高电平时间不超过75秒,芯片就不会进入睡眠模式。在睡眠模式中,按键的采样间隔会变长, 电流消耗(Idd)会减小。如果检测到按键,芯片会马上离开睡眠模式,进入正常模式。

image-20250814125347187

  • Ts 大约是固定的950us左右。

  • 正常模式下,采样间隔Tsin 是固定的大约12.5毫秒。

  • 睡眠模式下,采样间隔Tsis通过寄存器SLPCYC[2:0] 配置,采样间隔越长,对应电流消耗Idds越低,但是唤醒的速度会相对变慢。

三. 代码

硬件抽象层

HAL_i2c.c

#include "HAL_i2c.h"

/**
 * @brief 初始化i2c
 *
 * @param 无
 *
 * @return 无
 */
void i2c_Init(void)
{
    /* 配置i2c */
    i2c_config_t i2c_config = 
    {
        .master.clk_speed = I2C_MASTER_CLK_SPEED,
        .mode = I2C_MODE_MASTER,
        .scl_io_num = I2C_SCL_GPIO,
        .scl_pullup_en = true,
        .sda_io_num = I2C_SDA_GPIO,
        .sda_pullup_en = true,
    };
    i2c_param_config(I2C_PORT, &i2c_config);
    /* 安装i2c驱动 */
    i2c_driver_install(I2C_PORT,
                       I2C_MODE_MASTER,
                       0, 
                       0, 
                       0);
}

/**
 * @brief i2c发送数据
 *
 * @param 无
 *
 * @return 无
 */
void i2c_send_byte(uint8_t reg_addr,uint8_t data)
{
    uint8_t tx_buff[2] = {reg_addr, data};
    i2c_master_write_to_device(I2C_PORT,
                               I2C_SLAVE_ADDR,
                               tx_buff,
                               sizeof(tx_buff),
                               1000);
}

/**
 * @brief i2c接收数据
 *
 * @param 无
 *
 * @return 无
 */
uint8_t i2c_receive_byte(uint8_t reg_addr)
{
    uint8_t rx_buff;
    i2c_master_write_read_device(I2C_PORT,
                                 I2C_SLAVE_ADDR,
                                 &reg_addr,
                                 1,
                                 &rx_buff,
                                 1,
                                 1000);
    return rx_buff;
}   

Dri_i2c.h

#ifndef HAL_I2C_H
#define HAL_I2C_H

#include <stdio.h>

#include "driver/gpio.h"
#include "driver/i2c.h"

/* i2c 端口号 */
#define I2C_PORT                            I2C_NUM_0
/* i2c 时钟频率 400k */
#define I2C_MASTER_CLK_SPEED                   400000
/* i2c 引脚 */
#define I2C_SCL_GPIO                       GPIO_NUM_1
#define I2C_SDA_GPIO                       GPIO_NUM_2
/* i2c 从机地址 */
#define I2C_SLAVE_ADDR                           0x42

/**
 * @brief 初始化i2c
 *
 * @param 无
 *
 * @return 无
 */
void i2c_Init(void);

/**
 * @brief i2c发送数据
 *
 * @param 无
 *
 * @return 无
 */
void i2c_send_byte(uint8_t reg_addr,uint8_t data);

/**
 * @brief i2c接收数据
 *
 * @param 无
 *
 * @return 无
 */
uint8_t i2c_receive_byte(uint8_t reg_addr);

#endif

驱动层

Dri_SC12B.c

#include "Dri_SC12B.h"

/* 按下按键二值信号量 */
extern SemaphoreHandle_t g_xBinarySemaphoreTouchKey;

/**
 * @brief 初始化SC12B
 *
 * @param 无
 *
 * @return 无
 */
void SC12B_Init(void)
{
    /* 设置灵敏度 */
    i2c_send_byte(SENSET0,   SENSITIVITY_LEVEL_3);
    i2c_send_byte(SENSETCOM, SENSITIVITY_LEVEL_3);
}

/**
 * @brief 读取按键值
 *
 * @param 无
 *
 * @return 读到的按键
 */
touch_key_t SC12B_read_key(void)
{
    uint16_t key = 0;
    key = i2c_receive_byte(OUTPUT1);
    key <<= 8;
    key |= i2c_receive_byte(OUTPUT2);
    switch (key)
    {
        case 0x8000:
            return KEY_0;
            break;
        case 0x4000:
            return KEY_1;
            break;
        case 0x2000:
            return KEY_2;
            break;
        case 0x1000:
            return KEY_3;
            break;
        case 0x0800:
            return KEY_4;
            break;
        case 0x0400:
            return KEY_5;
            break;
        case 0x0200:
            return KEY_6;
            break;
        case 0x0100:
            return KEY_7;
            break;
        case 0x0080:
            return KEY_8;
            break;
        case 0x0040:
            return KEY_9;
            break;
        case 0x0020:
            return KEY_M;
            break;
        case 0x0010:
            return KEY_SHARP;
            break;
        default:
            return KEY_NO;
            break;
    }
}

Dri_SC12B.h

#ifndef INF_SC12B_H
#define INF_SC12B_H

#include <stdio.h>

#include "Dri_i2c.h"

/* SC12B 寄存器地址 */
#define SENSET0             (0x00)                      /* 灵敏度控制寄存器 */
#define SENSETCOM           (0x01)                      /* 灵敏度控制寄存器 */
#define CTRL0               (0x02)                      /* 控制寄存器       */
#define CTRL1               (0x03)                      /* 控制寄存器       */
#define OUTPUT1             (0x08)                      /* 按键信息寄存器   */
#define OUTPUT2             (0x09)                      /* 按键信息寄存器   */
#define SAMPH               (0x0A)                      /* 采样值寄存器     */
#define SAMPL               (0x0B)                      /* 采样值寄存器     */


/**
 * 灵敏度等级枚举(16档,按升序排列)
 *
 */
typedef enum {
    SENSITIVITY_LEVEL_MIN  = 0x04,                      /* 最低等级        */ 
    SENSITIVITY_LEVEL_2    = 0x15,
    SENSITIVITY_LEVEL_3    = 0x25,
    SENSITIVITY_LEVEL_4    = 0x36,
    SENSITIVITY_LEVEL_5    = 0x47,
    SENSITIVITY_LEVEL_6    = 0x58,
    SENSITIVITY_LEVEL_7    = 0x68,
    SENSITIVITY_LEVEL_8    = 0x79,
    SENSITIVITY_LEVEL_9    = 0x8A,
    SENSITIVITY_LEVEL_10   = 0x9B,
    SENSITIVITY_LEVEL_11   = 0xAC,
    SENSITIVITY_LEVEL_12   = 0xBC,
    SENSITIVITY_LEVEL_13   = 0xCD,
    SENSITIVITY_LEVEL_14   = 0xDE,
    SENSITIVITY_LEVEL_15   = 0xEF,
    SENSITIVITY_LEVEL_MAX  = 0xFF                       /* 最高等级        */ 
} sensitivity_level_t;

/* 按键 */
typedef enum
{
   KEY_0,
   KEY_1,
   KEY_2,
   KEY_3,
   KEY_7,
   KEY_5,
   KEY_6,
   KEY_4,
   KEY_9,
   KEY_M,
   KEY_SHARP,
   KEY_8,
   KEY_NO
}touch_key_t;

/**
 * @brief 初始化SC12B
 *
 * @param 无
 *
 * @return 无
 */
void SC12B_Init(void);

/**
 * @brief 读到的按键
 *
 * @param 无
 *
 * @return 读到的按键
 */
touch_key_t SC12B_read_key(void);

#endif

posted @ 2025-08-15 14:29  2666666  阅读(178)  评论(0)    收藏  举报