涂鸦智能烧水壶软件实现之TS02N触摸按键驱动
Posted 三明治开发社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了涂鸦智能烧水壶软件实现之TS02N触摸按键驱动相关的知识,希望对你有一定的参考价值。
智能烧水壶软件实现之TS02N触摸按键驱动
前言
本文主要内容是实现烧水壶的触摸按键驱动,触摸按键芯片选用TS02N。
一、智能烧水壶按键功能设定
- 智能烧水壶的按键功能设定如下,实现功能之前,我们首先要实现按键采集芯片的驱动。
功能 | 说明 |
---|---|
煮沸 | 触摸按键1,触发方式:轻触。默认煮沸。 触摸按键控制煮沸键 按下开启,再按关闭 app控制:煮沸 |
保温键 | 触摸按键1,触发方式:轻触 轻触进入默认的自来水模式下的55度保温模式,按下开启,再按关闭 长按5s进入配网模式 不操作,app也无操作,默认凉白开模式 |
二、按键采集的方案制定
1.硬件电路图
- 按键采集电路如下:
-
TS02N使用说明
输入P1\\P2:低电平触发
P1触发后OUT1输出低电平
P2触发后OUT2输出低电平
通信引脚设定:
OUT1 | P7 煮沸键
OUT2 | P8 保温键
2.嵌入式方案设定
为了后期的程序扩展,采用回调函数注册的方式实现按键控制。
1.按键按下时,按键指示灯亮,按键松开,按键指示灯灭;按一次按键蜂鸣器响一下
2.可以使用注册函数直接注册所用IO口,以及注册按键按下触发的回调函数
3.可以设置长按时间,配置按键长按触发的回调函数
三、功能实现
1.代码实现
- 在之前开发的基础上增加程序,增加ts02n_key.c文件和其头文件,目前整个工程的文件结构如下:
├── src
| ├── tuya_drive
| | └── b3950
| | └── b3950.c //温度传感器驱动相关
| | └── gpio_control
| | └── gpio_control.c //gpio 控制相关
| | └── ts02n_key
| | └── ts02n_key.c //按键驱动
| | └── timer
| | └── timer.c //定时器相关
| ├── tuya_device.c //应用层入口文件
| └── kettle_app.c //智能烧水壶主要应用文件
|
├── include //头文件目录
| ├── tuya_drive_h
| | └── b3950_h
| | └── b3950.h
| | └── gpio_control_h
| | └── gpio_control.h
| | └── ts02n_key_h
| | └── ts02n_key.h //按键驱动
| | └── timer_h
| | └── timer.h //定时器相关
| ├── tuya_device.h
| └── kettle_app.h
|
└── output //编译产物
ts02n_key.c中函数实现如下:主要内容是实现扫描函数,根据传入的配置参数进行初始化
/*使用时只需要通过ts02n_key_init(TS02N_KEY_DEF_S* user_key_def)函数进行注册,注册后会自动开启一个定时扫描任务去采集按键信息,按键触发后也会自动调用注册的回调函数*/
typedef VOID(* KEY_CALLBACK)();
typedef struct { // user define
unsigned int key_pin1; //ts02n CH1 PIN
unsigned int key_pin2; //ts02n CH2 PIN
KEY_CALLBACK key1_cb; //normal press key1 callback function
KEY_CALLBACK key2_cb; //normal press key2 callback function
KEY_CALLBACK key1_long_press_cb; //normal press key1 callback function
KEY_CALLBACK key2_long_press_cb; //normal press key2 callback function
KEY_CALLBACK key1_Low_level_cb; //Key1 low level process callback function
KEY_CALLBACK key2_Low_level_cb; //Key2 low level process callback function
unsigned int long_time_set; //long press key time set
unsigned int scan_time; //Scan cycle set unit: ms
}TS02N_KEY_DEF_S;
typedef struct {
unsigned int down_time; //记录按键按下的时间
unsigned char status;
}KEY_PRESS_STATUS_S;
typedef struct {
TS02N_KEY_DEF_S* ts02n_def_s;//用户注册的相关信息,回调函数,pin口等
KEY_PRESS_STATUS_S key_status;
}TS02N_KEY_MANAGE_S;
/* Private function prototypes -----------------------------------------------*/
static int key_scan();
static void key_timer_cb();
/* Private variables ---------------------------------------------------------*/
static TIMER_ID key_timer;
static TS02N_KEY_MANAGE_S *key_mag = NULL;
enum KEY_STAT_E{
KEY1_UP = 0,
KEY1_DOWN,
KEY1_FINISH,
KEY2_UP,
KEY2_DOWN,
KEY2_FINISH,
};
enum KEY_PRESS_STAT{
KEY1_NORMAL_PRESS = 0,
KEY2_NORMAL_PRESS,
KEY1_LONG_PRESS,
KEY2_LONG_PRESS,
NO_KEY_PRESS,
};
/* Private functions ---------------------------------------------------------*/
/**
* @Function: ts02n_key_init
* @Description: key init
* @Input: none
* @Output: none
* @Return: none
* @Others:
*/
int ts02n_key_init(TS02N_KEY_DEF_S* user_key_def)
{
int op_ret = 0;
key_mag = (TS02N_KEY_MANAGE_S *)Malloc(SIZEOF(TS02N_KEY_MANAGE_S));
memset(key_mag, 0, SIZEOF(TS02N_KEY_MANAGE_S));
//No callback function is registered key init err
if((user_key_def->key1_cb == NULL) && (user_key_def->key2_cb == NULL) && \\
(user_key_def->key1_long_press_cb == NULL) && (user_key_def->key2_long_press_cb == NULL)){
return KEY_INIT_ERR;
}
//key pin init
tuya_pin_init(user_key_def->key_pin1, TUYA_PIN_MODE_IN_PU);
tuya_pin_init(user_key_def->key_pin2, TUYA_PIN_MODE_IN_PU);
//get user define
key_mag->ts02n_def_s = user_key_def;
//creat key scan handle timer
op_ret = sys_add_timer(key_timer_cb,NULL,&key_timer);
if(op_ret != KEY_INIT_OK) {
return KEY_INIT_ERR;
PR_ERR("add timer err");
}
op_ret = sys_start_timer(key_timer,key_mag->ts02n_def_s->scan_time,TIMER_CYCLE);
if(op_ret != KEY_INIT_OK) {
return KEY_INIT_ERR;
PR_ERR("start timer err");
}
}
/**
* @Function: key_timer_cb
* @Description: Timing key scan processing function
* @Input: none
* @Output: none
* @Return: none
* @Others:
*/
static void key_timer_cb()
{
int ret = -1;
//get key press status
ret = key_scan();
switch (ret) {
case KEY1_NORMAL_PRESS: {
key_mag->ts02n_def_s->key1_cb();
}
break;
case KEY1_LONG_PRESS: {
key_mag->ts02n_def_s->key1_long_press_cb();
}
break;
case KEY2_NORMAL_PRESS: {
key_mag->ts02n_def_s->key2_cb();
}
break;
case KEY2_LONG_PRESS: {
key_mag->ts02n_def_s->key2_long_press_cb();
}
break;
default:
break;
}
}
/**
* @Function: key_scan
* @Description: key scan handle function
* @Input: none
* @Output: none
* @Return: none
* @Others:
*/
static int key_scan()
{
if((tuya_pin_read(key_mag->ts02n_def_s->key_pin1) == 0) && (tuya_pin_read(key_mag->ts02n_def_s->key_pin2) == 0 )) {
return NO_KEY_PRESS;
}
if(tuya_pin_read(key_mag->ts02n_def_s->key_pin1) == 0 ) {
key_mag->ts02n_def_s->key1_Low_level_cb();
key_mag->key_status.status = KEY1_DOWN;
key_mag->key_status.down_time += key_mag->ts02n_def_s->scan_time;
if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) {
key_mag->key_status.status = KEY1_FINISH;
}
}else {
if(key_mag->key_status.status == KEY1_DOWN) {
key_mag->key_status.status = KEY1_FINISH;
}
}
if(tuya_pin_read(key_mag->ts02n_def_s->key_pin2) == 0 ) {
key_mag->ts02n_def_s->key2_Low_level_cb();
key_mag->key_status.status = KEY2_DOWN;
key_mag->key_status.down_time += key_mag->ts02n_def_s->scan_time;
if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) {
key_mag->key_status.status = KEY2_FINISH;
}
}else {
if(key_mag->key_status.status == KEY2_DOWN) {
key_mag->key_status.status = KEY2_FINISH;
}
}
switch (key_mag->key_status.status) {
case (KEY1_FINISH): {
if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) {
PR_DEBUG("key_pin1 long press");
key_mag->key_status.down_time = 0;
key_mag->key_status.status = KEY1_UP;
return KEY1_LONG_PRESS;
}else {
key_mag->key_status.status = KEY1_UP;
key_mag->key_status.down_time = 0;
PR_DEBUG("key_pin1 press");
return KEY1_NORMAL_PRESS;
}
}
break;
case (KEY2_FINISH): {
if(key_mag->key_status.down_time >= key_mag->ts02n_def_s->long_time_set) {
PR_DEBUG("key_pin2 long press");
key_mag->key_status.down_time = 0;
key_mag->key_status.status = KEY2_UP;
return KEY2_LONG_PRESS;
}else {
key_mag->key_status.status = KEY2_UP;
key_mag->key_status.down_time = 0;
PR_DEBUG("key_pin2 press");
return KEY2_NORMAL_PRESS;
}
}
break;
default:
return NO_KEY_PRESS;
break;
}
}
- kettle_app.c文件中初始化按键,并注册回调函数,其中一些设置烧水壶状态的函数可以先不看,后面文章会说明
TS02N_KEY_DEF_S kettle_key_def_s = {
.key_pin1 = TY_GPIOA_8,
.key_pin2 = TY_GPIOA_7,
.key1_cb = key1_cb_fun,
.key2_cb = key2_cb_fun,
.key1_long_press_cb = NULL,
.key2_long_press_cb = key2_long_press_cb_fun,
.key1_Low_level_cb = key1_Low_level_cb_fun,
.key2_Low_level_cb = key2_Low_level_cb_fun,
.long_time_set = 5000,
.scan_time = 100,
};
VOID_T kettle_init()
{
b3950_init();
thread_init();
kettle_gpio_init();
ts02n_key_init(&kettle_key_def_s);//注册按键并初始化
}
//煮沸键按下再松开后触发
void key1_cb_fun()
{
//Button press prompt
led1_set(OFF);
buzzer_flag = 1;
//Button press prompt
if(get_kettle_work_status() == boil) { //if current status is boil, close boiling
set_kettle_work_status(nature);
set_dp_boil_value(FALSE);
report_one_dp_status(DP_BOIL);
}else {
set_kettle_work_status(boil);
set_dp_boil_value(TRUE);
report_one_dp_status(DP_BOIL);
}
}
//保温键按下再松开后触发
void key2_cb_fun()
{
//Button press prompt
led2_set(OFF);
buzzer_flag = 1;
//Button press prompt
if(get_kettle_work_status() == keep_warm_mode1) {//if current status is keep_warm_mode1,turn off insulation function
set_kettle_work_status(nature);
set_dp_keep_warm_switch(0);
report_one_dp_status(DP_KEEP_WARM);
}else {
set_kettle_work_status(keep_warm_mode1);
//tap water warm mode :1.boil -> 2.keep warm
set_kettle_keep_warm_temper(Default_Warm_Temperature);
set_dp_keep_warm_switch(1);
report_one_dp_status(DP_KEEP_WARM);
report_one_dp_status(DP_TEMP_SET);
}
}
//保温键长按5s触发,进行配网模式
void key2_long_press_cb_fun()
{
led2_set(OFF);
tuya_iot_wf_gw_unactive();
buzzer_flag = 1;
}
//按键按下时触发
void key1_Low_level_cb_fun()
{
PR_DEBUG("key1_Low_level_cb");
led1_set(ON);
if(buzzer_flag) {
timer_init();//蜂鸣器响一下
buzzer_flag = 0;
}
}
//按键按下时触发
void key2_Low_level_cb_fun()
{
led2_set(ON);
PR_DEBUG("key2_Low_level_cb");
if(buzzer_flag) {
timer_init();//蜂鸣器响一下
buzzer_flag = 0;
}
}
- 此时智能烧水壶的按键驱动功能已经实现了,其他功能实现请见后续文章。
技术支持
您可以通过以下方法获得涂鸦的支持:
- 开发者中心:https://developer.tuya.com
- 帮助中心: https://support.tuya.com/help
- 技术支持工单中心: https://service.console.tuya.com
以上是关于涂鸦智能烧水壶软件实现之TS02N触摸按键驱动的主要内容,如果未能解决你的问题,请参考以下文章