IllusionLee 6 سال پیش
کامیت
c91428fcb2
7فایلهای تغییر یافته به همراه496 افزوده شده و 0 حذف شده
  1. 53 0
      .gitignore
  2. 21 0
      LICENSE
  3. 110 0
      README.md
  4. 13 0
      SConscript
  5. 66 0
      inc/bs8116a.h
  6. 76 0
      samples/bs8116a_sample.c
  7. 157 0
      src/bs8116a.c

+ 53 - 0
.gitignore

@@ -0,0 +1,53 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Illusion Lee
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 110 - 0
README.md

@@ -0,0 +1,110 @@
+# bs8116a
+
+## 1、介绍
+
+**bs8116a** 是合泰的bs8116a-3的触摸按键芯片的中断使用软件包。
+
+### 1.1 目录结构
+
+| 名称 | 说明 |
+| ---- | ---- |
+| examples | 例子目录 |
+| inc  | 头文件目录 |
+| src  | 源代码目录 |
+
+### 1.2 许可证
+
+`bs8116a` 软件包使用 `MIT` 软件包许可协议,请见 `bs8116a/LICENSE` 文件。
+
+### 1.3 依赖
+
+- RT-Thread 3.0+
+
+## 2、如何打开 bs8116a
+
+使用 bs8116a package 需要在 RT-Thread 的包管理器中选择它,具体路径如下:
+
+```shell
+RT-Thread online packages
+    tools packages --->
+        [*] bs8116a: Touch key of HOLTEK BS8116A-3.
+```
+
+然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。
+
+## 3、使用 bs8116a
+
+### 初始化键值对应表
+
+定义一个数组,按照实际按键键值进行定义,如:
+
+```c
+/* 芯片1对应的键值 */
+static rt_uint8_t keyvalue1[15] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+```
+
+### 芯片初始化
+
+芯片可以进行参数配置,所以需要对参数进行定义:
+
+```c
+/* 按键的初始化数组 */
+static rt_uint8_t touch_key_init_buff[22] = {
+    0x00,                           /* 触发模式 */
+    0x00, 0x83, 0xF3,               /* 固定协议 */
+    0x98,                           /* 省电模式 */
+    0x20, 0x20, 0x20, 0x20, 0x20,   /* 触摸阈值 */
+    0x20, 0x20, 0x20, 0x20, 0x20,   /* 触摸阈值 */
+    0x20, 0x20, 0x20, 0x20, 0x20,   /* 触摸阈值 */
+    0x40,                           /* 中断模式 */
+    0x2E                            /* SUM校验和 */
+};
+```
+
+具体设置,请参考官方数据手册。
+
+### 芯片数量定义
+
+```c
+/* 使用BS8116A芯片的数量 */
+rt_uint8_t BS8116A_CHIP_NUMS = 3;
+```
+
+### 实现按键回调函数:
+
+```c
+/* 按键触发调用函数 */
+void got_key_callback(rt_uint8_t key_code) {
+    rt_kprintf("got_key:%d\n", key_code);
+}
+```
+
+## 4、示例演示
+
+在 MSH 中输入命令 `bs8116a_test_func`,点击BS8116A-3的触摸按键,可以在串口助手上看到输出了对应的键值。
+
+```
+msh >bs8116a_test_func
+BS8116A_CHIP_NUMS : 3
+Find i2c1soft device OK!
+Find i2c2soft device OK!
+Find i2c3soft device OK!
+msh >
+msh >got_key:1
+got_key:8
+got_key:15
+got_key:22
+got_key:31
+```
+
+## 5、注意事项
+
+- 需要menuconfig 中配置I2C使能,且按照实际i2c数量进行配置。
+- 必须实现 `got_key_callback`方法
+- 必须定义`BS8116A_CHIP_NUMS`
+- 键值对应关系根据实际PCB布局进行定义
+
+## 6、联系方式
+
+* 维护:[illusionlee](https://github.com/illusionlee)
+* 主页:https://github.com/illusionlee/lunar_calendar.git

+ 13 - 0
SConscript

@@ -0,0 +1,13 @@
+from building import *
+
+cwd  = GetCurrentDir()
+
+src = Glob('src/bs8116a.c')
+if GetDepend(['PKG_USING_BS8116A']):
+    src += Glob('samples/bs8116a_sample.c')
+
+CPPPATH = [cwd + '/inc']
+
+group = DefineGroup('bs8116a', src, depend = ['PKG_USING_BS8116A'], CPPPATH = CPPPATH)
+
+Return('group')

+ 66 - 0
inc/bs8116a.h

@@ -0,0 +1,66 @@
+/**
+ * The MIT License
+ *
+ * Copyright (c) 2019 Illusion Lee
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __BS8116A_H_
+#define __BS8116A_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+
+/* 使用的BS8116A芯片数量 需要使用者进行定义和赋值 */
+extern rt_uint8_t BS8116A_CHIP_NUMS;
+
+/* 按键参数结构体 */
+struct bs8116a_key_arg {
+	rt_uint8_t *key_value;          /* 键值对应关系数组 */
+	rt_uint8_t key_size;            /* 实际使用的按键个数 */
+	rt_uint8_t *init_buff;          /* 初始化芯片的参数数组 */
+};
+
+/* 中断配置结构体 */
+struct bs8116a_irq_arg {
+	rt_uint8_t irq_pin_id;          /* 中断引脚编号 */
+	struct rt_i2c_bus_device *bus;  /* i2c设备结构体 */
+	struct bs8116a_key_arg *key;    /* 按键参数结构体 */
+	char bus_name[16];              /* 使用的i2c设备名 */
+};
+
+/* 申请i2c总线函数 */
+extern void keypad_init(struct bs8116a_irq_arg arg[]);
+
+/* 对BS8116A芯片进行初始化配置,需要在上电后的8秒内调用 */
+extern void init_buf_to_bus(struct bs8116a_irq_arg arg[]);
+
+/* 注册中断引脚 绑定中断函数 */
+extern void key_irq_entry(struct bs8116a_irq_arg arg[]);
+
+/* 回调用户定义的函数 需要使用者实现方法体 */
+extern void got_key_callback(rt_uint8_t key_code);
+
+#ifdef __cplusplus
+}
+#endif  /* __cplusplus */
+
+#endif  /* __BS8116A_H_ */

+ 76 - 0
samples/bs8116a_sample.c

@@ -0,0 +1,76 @@
+#include <rtthread.h>
+
+#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
+#include <finsh.h>
+#include "bs8116a.h"
+
+/* 芯片1对应的键值 */
+static rt_uint8_t keyvalue1[15] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+/* 芯片2对应的键值 */
+static rt_uint8_t keyvalue2[15] = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
+/* 芯片3对应的键值 */
+static rt_uint8_t keyvalue3[6]  = {31, 32, 33, 34, 35, 36};
+/* 按键的初始化数组 */
+static rt_uint8_t touch_key_init_buff[22] = {
+    0x00,                           /* 触发模式 */
+    0x00, 0x83, 0xF3,               /* 固定协议 */
+    0x98,                           /* 省电模式 */
+    0x20, 0x20, 0x20, 0x20, 0x20,   /* 触摸阈值 */
+    0x20, 0x20, 0x20, 0x20, 0x20,   /* 触摸阈值 */
+    0x20, 0x20, 0x20, 0x20, 0x20,   /* 触摸阈值 */
+    0x40,                           /* 中断模式 */
+    0x2E                            /* SUM校验和 */
+};
+/* 使用BS8116A芯片的数量 */
+rt_uint8_t BS8116A_CHIP_NUMS = 3;
+
+/* 按键触发调用函数 */
+void got_key_callback(rt_uint8_t key_code) {
+    rt_kprintf("got_key:%d\n", key_code);
+}
+
+static void bs8116a_test_func(void) {
+    rt_kprintf("BS8116A_CHIP_NUMS : %d\n", BS8116A_CHIP_NUMS);
+
+    /* 需要与 BS8116A_CHIP_NUMS 数量对应*/
+    static struct bs8116a_irq_arg b_i_a[3];
+
+    /* 芯片1的参数配置*/
+    static struct bs8116a_key_arg b_k_a_1 = {
+        .key_value = keyvalue1,
+        .key_size = 15,
+        .init_buff = touch_key_init_buff,
+    };
+    b_i_a[0].key = &b_k_a_1;
+    b_i_a[0].irq_pin_id = 29;
+    strcpy(b_i_a[0].bus_name, "i2c1soft");
+
+    /* 芯片2的参数配置*/
+    static struct bs8116a_key_arg b_k_a_2 = {
+        .key_value = keyvalue2,
+        .key_size = 15,
+        .init_buff = touch_key_init_buff,
+    };
+    b_i_a[1].key = &b_k_a_2;
+    b_i_a[1].irq_pin_id = 28;
+    strcpy(b_i_a[1].bus_name, "i2c2soft");
+
+    /* 芯片3的参数配置*/
+    static struct bs8116a_key_arg b_k_a_3 = {
+        .key_value = keyvalue3,
+        .key_size = 6,
+        .init_buff = touch_key_init_buff,
+    };
+    b_i_a[2].key = &b_k_a_3;
+    b_i_a[2].irq_pin_id = 27;
+    strcpy(b_i_a[2].bus_name, "i2c3soft");
+
+    /* 申请i2c总线函数 */
+    keypad_init(b_i_a);
+    /* 对BS8116A芯片进行初始化配置,需要在上电后的8秒内调用 */
+    init_buf_to_bus(b_i_a);
+    /* 注册中断引脚 绑定中断函数 */
+    key_irq_entry(b_i_a);
+}
+MSH_CMD_EXPORT(bs8116a_test_func, bs8116a test function.);
+#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */

+ 157 - 0
src/bs8116a.c

@@ -0,0 +1,157 @@
+/**
+ * The MIT License
+ *
+ * Copyright (c) 2019 Illusion Lee
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "bs8116a.h"
+
+/* BS8116A 触摸引脚数量 */
+#define KEYBOARD_SIZE             16
+/* BS8116A 获取键值地址 */
+static rt_uint8_t GET_DATA_ADDR = 0x08;
+/* BS8116A 参数配置地址 */
+static rt_uint8_t SET_ATTR_ADDR = 0xB0;
+/* BS8116A总线地址 */
+static rt_uint8_t BS8116A_ADDR  = 0x50;
+/* BS8116A 初始化数组的大小 */
+static rt_uint8_t INIT_BUF_SIZE = 0x16;
+/* BS8116A引脚对应keycode */
+static rt_uint16_t key_array[KEYBOARD_SIZE] = {
+    0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
+};
+
+/* 写BS8116A寄存器 */
+static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t len) {
+    rt_uint8_t buf[len + 1];
+    rt_uint8_t i;
+    struct rt_i2c_msg msgs;
+
+    buf[0] = reg;
+    for (i = 0; i < len; i++) {
+        buf[i + 1] = data[i];
+    }
+    msgs.addr  = BS8116A_ADDR;
+    msgs.flags = 0;
+    msgs.buf   = buf;
+    msgs.len   = len + 1;
+
+    /* 调用I2C设备接口传输数据 */
+    if (rt_i2c_transfer(bus, &msgs, 1) == 1) {
+        return RT_EOK;
+    } else {
+        rt_kprintf("write_reg rt_i2c_transfer RT_ERROR[%d]\n", RT_ERROR);
+        return -RT_ERROR;
+    }
+}
+
+/* 对BS8116A芯片进行初始化配置,需要在上电后的8秒内调用 */
+void init_buf_to_bus(struct bs8116a_irq_arg irq_arg[]) {
+    int i_num = 0;
+    int ret = RT_EOK;
+    for (i_num = 0; i_num < BS8116A_CHIP_NUMS; ++i_num) {
+        ret = write_reg(irq_arg[i_num].bus, SET_ATTR_ADDR, irq_arg[i_num].key->init_buff, INIT_BUF_SIZE);
+        if (ret != RT_EOK) {
+            rt_kprintf("init_buf_to_bus %s RT_ERROR[%d]\n", irq_arg[i_num].bus_name, RT_ERROR);
+        }
+    }
+}
+
+/* 使用i2c获取触摸按键的key */
+static rt_err_t get_key(struct rt_i2c_bus_device *bus, rt_uint8_t *reg, rt_uint8_t *value) {
+    struct rt_i2c_msg msgs[2];
+    msgs[0].addr  = BS8116A_ADDR;
+    msgs[0].flags = 0;
+    msgs[0].len   = 1;
+    msgs[0].buf   = reg;
+
+    msgs[1].addr  = BS8116A_ADDR;
+    msgs[1].flags = RT_I2C_RD;
+    msgs[1].buf   = value;
+    msgs[1].len   = 2;
+
+    if (rt_i2c_transfer(bus, msgs, 2) == 2) {
+        return RT_EOK;
+    } else {
+        rt_kprintf("get_key rt_i2c_transfer RT_ERROR[%d]\n", RT_ERROR);
+        return -RT_ERROR;
+    }
+}
+
+/* 将BS8116A获取到的 touch_code 转换为用户定义的键值函数 */
+static rt_uint8_t get_key_code(struct bs8116a_key_arg *key, rt_uint16_t touch_code) {
+    rt_uint8_t loop_key_i = 0;
+    for (loop_key_i = 0; loop_key_i < key->key_size; loop_key_i++) {
+        if (key_array[loop_key_i] == touch_code) {
+            return key->key_value[loop_key_i];
+        }
+    }
+    return 0xFF;
+}
+
+/* 申请i2c总线函数 */
+void keypad_init(struct bs8116a_irq_arg irq_arg[]) {
+    int i_num = 0;
+    for (i_num = 0; i_num < BS8116A_CHIP_NUMS; ++i_num) {
+        irq_arg[i_num].bus = (struct rt_i2c_bus_device *)rt_device_find(irq_arg[i_num].bus_name);
+
+        if (irq_arg[i_num].bus == RT_NULL) {
+            rt_kprintf("Can't find %s device!\n", irq_arg[i_num].bus_name);
+        } else {
+            rt_kprintf("Find %s device OK!\n", irq_arg[i_num].bus_name);
+        }
+    }
+}
+
+/* 中断处理函数 */
+void *get_irq_key_entry(void *arg) {
+    struct bs8116a_irq_arg *irq_arg = (struct bs8116a_irq_arg *)arg;
+    rt_uint16_t KeyCode     = 0;
+    rt_uint8_t touched_code = 0;
+    rt_uint8_t key_value[2] = {0, 0};
+
+    get_key(irq_arg->bus, &GET_DATA_ADDR, key_value);
+    KeyCode = key_value[0] + (key_value[1] << 8);
+
+    if (KeyCode) {
+        touched_code = get_key_code(irq_arg->key, KeyCode);
+        if (touched_code != 0xFF) {
+            /* 回调用户定义的函数 */
+            got_key_callback(touched_code);
+        }
+    }
+}
+
+/* 注册中断引脚 绑定中断函数 */
+void key_irq_entry(struct bs8116a_irq_arg irq_arg[]) {
+    rt_uint8_t i_num = 0;
+    for (i_num = 0; i_num < BS8116A_CHIP_NUMS; ++i_num) {
+        if (irq_arg[i_num].bus != RT_NULL) {
+            rt_pin_mode(irq_arg[0].irq_pin_id, PIN_MODE_INPUT_PULLUP);
+            rt_pin_attach_irq(irq_arg[i_num].irq_pin_id, PIN_IRQ_MODE_FALLING, get_irq_key_entry, (void *)&irq_arg[i_num]);
+            rt_pin_irq_enable(irq_arg[i_num].irq_pin_id, PIN_IRQ_ENABLE);
+        } else {
+            rt_kprintf("%s device isn't Initialize!\n", irq_arg[i_num].bus_name);
+        }
+    }
+}