新增兼容两种墙壁开关
This commit is contained in:
@@ -234,11 +234,11 @@ void scan_433(void)
|
||||
long_timer--;
|
||||
}
|
||||
|
||||
if(rf433_sw_flag==1)
|
||||
{
|
||||
rf433_sw_flag=0;
|
||||
}
|
||||
else if(rf433_sw_flag==2)
|
||||
// if(rf433_sw_flag==1)
|
||||
// {
|
||||
// rf433_sw_flag=0;
|
||||
// }
|
||||
if(rf433_sw_flag==2)
|
||||
{
|
||||
rf433_sw_flag=0;
|
||||
power=4;
|
||||
|
||||
@@ -1,429 +1,587 @@
|
||||
#include "switch_s.h"
|
||||
#include "xc_drv_gpio.h"
|
||||
#include "rf433.h"
|
||||
// ==================== GPIO1 检测 ====================
|
||||
uint8_t trig1_cnt = 0; // 连续触发次数
|
||||
uint16_t trig1_timeout = 0; // 300ms 倒计时
|
||||
uint8_t trig1_wait = 0; // 0=空闲 1=连续出触发
|
||||
|
||||
// ==================== GPIO19 检测 ====================
|
||||
uint8_t trig2_cnt = 0; // 连续触发次数
|
||||
uint16_t trig2_timeout = 0; // 300ms 倒计时
|
||||
uint8_t trig2_wait = 0; // 0=空闲 1=连续出触发
|
||||
/*
|
||||
* ============================================================
|
||||
* GPIO1 / S1 检测变量
|
||||
* ============================================================
|
||||
*/
|
||||
uint8_t trig1_cnt = 0;
|
||||
uint16_t trig1_timeout = 0;
|
||||
uint8_t trig1_wait = 0;
|
||||
|
||||
uint8_t rf433_sw_flag=0; //进入对码标志
|
||||
/*
|
||||
* ============================================================
|
||||
* RF433 对码标志
|
||||
* ============================================================
|
||||
*
|
||||
* 0:无对码
|
||||
* 2:GPIO1 快速按 5 次及以上进入对码
|
||||
*/
|
||||
uint8_t rf433_sw_flag = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 防抖状态机变量
|
||||
* ============================================================
|
||||
*/
|
||||
static volatile debounce_state_t s1_state = DB_IDLE;
|
||||
static volatile debounce_state_t s2_state = DB_IDLE;
|
||||
static volatile uint16_t s1_debounce_cnt = 0;
|
||||
static volatile uint16_t s2_debounce_cnt = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 按下持续时间计数
|
||||
* ============================================================
|
||||
*/
|
||||
static volatile uint16_t s1_press_cnt = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 长按普通开关已处理标志
|
||||
* ============================================================
|
||||
*/
|
||||
static volatile uint8_t s1_long_press_done = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 回弹点击标志
|
||||
* ============================================================
|
||||
*/
|
||||
static volatile uint8_t s1_return_click_flag = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 5次对码失效标志
|
||||
* ============================================================
|
||||
*
|
||||
* 作用:
|
||||
* 快速拨动达到 5 次后,如果最后一次停留在打开状态超过 200ms,
|
||||
* 则本次 5 次对码序列失效。
|
||||
*
|
||||
* 这样可以避免:
|
||||
* 快速拨动 5 次后停留在打开一段时间,再关闭,仍然进入对码。
|
||||
*/
|
||||
static volatile uint8_t s1_pair_invalid_flag = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 防抖时间
|
||||
* ============================================================
|
||||
* trigger_check_process() 如果 10ms 调用一次:
|
||||
* DEBOUNCE_MS = 2 表示 20ms 防抖
|
||||
*/
|
||||
#define DEBOUNCE_MS 2
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 释放标志
|
||||
* ============================================================
|
||||
*/
|
||||
uint8_t switch1_RELEASE_flag = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 普通不回弹开关第一次按下标志
|
||||
* ============================================================
|
||||
*/
|
||||
uint8_t s1_first_press_flag = 0;
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 上电时开关状态
|
||||
* ============================================================
|
||||
*/
|
||||
uint8_t S1_first_on_state = 0;
|
||||
|
||||
|
||||
|
||||
#define DEBOUNCE_MS 2 //消抖时间40ms
|
||||
|
||||
//uint16_t switch1_debounce = 0;
|
||||
//uint16_t switch2_debounce = 0;
|
||||
|
||||
uint8_t switch1_RELEASE_flag=0;
|
||||
uint8_t switch2_RELEASE_flag=0;
|
||||
|
||||
uint8_t s1_first_press_flag = 0; //S2首次按下标志
|
||||
uint8_t s2_first_press_flag = 0; //S2首次按下标志
|
||||
|
||||
uint8_t S1_first_on_state=0; //上电时开关的状态
|
||||
uint8_t S2_first_on_state=0; //上电时开关的状态
|
||||
|
||||
|
||||
void switch_init(void)
|
||||
/*
|
||||
* ============================================================
|
||||
* S1 状态清理函数
|
||||
* ============================================================
|
||||
*/
|
||||
static void switch_s1_clear_action_state(void)
|
||||
{
|
||||
trig1_cnt = 0;
|
||||
trig1_timeout = 0;
|
||||
trig1_wait = 0;
|
||||
|
||||
GPIO_InitCfg_t GPIO_InitCfg = { 0 }; // 清零初始化配置结构体
|
||||
GPIO_InitCfg.Mux = GPIO_Mux0; // 选择功能复用器0
|
||||
GPIO_InitCfg.FunSel = GPIO_Dx; // 选择GPIO功能(非特殊功能)
|
||||
GPIO_InitCfg.Pull = GPIO_PULLUP; //上拉电阻使能
|
||||
|
||||
|
||||
GPIO_InitCfg.Dir = GPIO_DIR_INPUT; // 输出方向
|
||||
GPIO_InitCfg.Int = FAIL_EDGE_INT; //使能中断
|
||||
GPIO_InitCfg.Pin = SWITCH_S1_PIN; // 设置S1引脚
|
||||
xc_gpio_init(&GPIO_InitCfg); // 初始化GPIO
|
||||
|
||||
// GPIO_InitCfg.Dir = GPIO_DIR_INPUT; // 输出方向
|
||||
// GPIO_InitCfg.Int = FAIL_EDGE_INT; //使能中断
|
||||
// GPIO_InitCfg.Pin = SWITCH_S2_PIN; // 设置S2引脚
|
||||
// xc_gpio_init(&GPIO_InitCfg); // 初始化GPIO
|
||||
|
||||
xc_gpio_it_config(GPIO_1,FAIL_EDGE_INT);
|
||||
xc_gpio_it_config(GPIO_19,FAIL_EDGE_INT);
|
||||
NVIC_EnableIRQ(GPIO_IRQn);
|
||||
|
||||
|
||||
//判断首次上电开关状态
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN)==0)
|
||||
{
|
||||
S1_first_on_state=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
S1_first_on_state=0;
|
||||
}
|
||||
|
||||
if(xc_gpio_read_pin(SWITCH_S2_PIN)==0)
|
||||
{
|
||||
S2_first_on_state=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
S2_first_on_state=0;
|
||||
}
|
||||
|
||||
switch1_RELEASE_flag = 0;
|
||||
s1_first_press_flag = 0;
|
||||
|
||||
s1_return_click_flag = 0;
|
||||
s1_long_press_done = 0;
|
||||
s1_press_cnt = 0;
|
||||
|
||||
/*
|
||||
* 新增:
|
||||
* 清理 5 次对码失效标志。
|
||||
*/
|
||||
s1_pair_invalid_flag = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* S1 输出控制:GPIO5
|
||||
* ============================================================
|
||||
*/
|
||||
static void switch_s1_output_on(void)
|
||||
{
|
||||
xc_gpio_write_pin(GPIO_5, GPIO_PIN_SET);
|
||||
flash_ch1_state = xc_gpio_read_pin(GPIO_5);
|
||||
flash_run();
|
||||
}
|
||||
|
||||
static void switch_s1_output_off(void)
|
||||
{
|
||||
xc_gpio_write_pin(GPIO_5, GPIO_PIN_RESET);
|
||||
flash_ch1_state = xc_gpio_read_pin(GPIO_5);
|
||||
flash_run();
|
||||
}
|
||||
|
||||
static void switch_s1_output_toggle(void)
|
||||
{
|
||||
if(xc_gpio_read_pin(GPIO_5))
|
||||
{
|
||||
xc_gpio_write_pin(GPIO_5, GPIO_PIN_RESET);
|
||||
}
|
||||
else
|
||||
{
|
||||
xc_gpio_write_pin(GPIO_5, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
flash_ch1_state = xc_gpio_read_pin(GPIO_5);
|
||||
flash_run();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 开关 GPIO 初始化
|
||||
* ============================================================
|
||||
*/
|
||||
void switch_init(void)
|
||||
{
|
||||
GPIO_InitCfg_t GPIO_InitCfg = { 0 };
|
||||
|
||||
GPIO_InitCfg.Mux = GPIO_Mux0;
|
||||
GPIO_InitCfg.FunSel = GPIO_Dx;
|
||||
GPIO_InitCfg.Pull = GPIO_PULLUP;
|
||||
|
||||
/*
|
||||
* GPIO1 输入初始化
|
||||
*/
|
||||
GPIO_InitCfg.Dir = GPIO_DIR_INPUT;
|
||||
GPIO_InitCfg.Int = FAIL_EDGE_INT;
|
||||
GPIO_InitCfg.Pin = SWITCH_S1_PIN;
|
||||
xc_gpio_init(&GPIO_InitCfg);
|
||||
|
||||
/*
|
||||
* GPIO1 下降沿中断
|
||||
*/
|
||||
xc_gpio_it_config(GPIO_1, FAIL_EDGE_INT);
|
||||
NVIC_EnableIRQ(GPIO_IRQn);
|
||||
|
||||
/*
|
||||
* 上电时检测 GPIO1 初始状态
|
||||
*/
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 0)
|
||||
{
|
||||
S1_first_on_state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
S1_first_on_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 开关检测主处理函数
|
||||
* ============================================================
|
||||
*
|
||||
* 需要周期调用。
|
||||
* 当前按 SWITCH_SCAN_PERIOD_MS = 10ms 计算。
|
||||
*/
|
||||
void trigger_check_process(void)
|
||||
{
|
||||
if(S1_first_on_state==1)
|
||||
{
|
||||
S1_first_on_state=0;
|
||||
|
||||
s1_state=DB_PRESS_DEBOUNCE;
|
||||
}
|
||||
// if(S2_first_on_state==1)
|
||||
// {
|
||||
// S2_first_on_state=0;
|
||||
//
|
||||
// s2_state=DB_PRESS_DEBOUNCE;
|
||||
// }
|
||||
|
||||
// if(S1_first_on_state==1)
|
||||
// {
|
||||
// S1_first_on_state=0;
|
||||
// s1_first_press_flag=1;
|
||||
// s1_state=DB_PRESSED;
|
||||
// }
|
||||
// if(S2_first_on_state==1)
|
||||
// {
|
||||
// S2_first_on_state=0;
|
||||
// s2_first_press_flag=1;
|
||||
// s2_state=DB_PRESSED;
|
||||
// }
|
||||
|
||||
switch(s1_state)
|
||||
{
|
||||
case DB_IDLE: //空闲状态
|
||||
break;
|
||||
|
||||
case DB_PRESS_DEBOUNCE: //按下防抖
|
||||
if(s1_debounce_cnt>0) s1_debounce_cnt--;
|
||||
if(s1_debounce_cnt==0)
|
||||
{
|
||||
//防抖时间到,采样当前电平是否是低电平
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN)==0)
|
||||
{
|
||||
s1_state = DB_PRESSED; //进入按下状态,不响应中断
|
||||
if(trig1_wait == 0)
|
||||
{
|
||||
trig1_cnt = 1;
|
||||
trig1_timeout = TRIGGER_TIMEOUT_MS;
|
||||
trig1_wait = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(trig1_timeout>0)
|
||||
{
|
||||
trig1_cnt++;
|
||||
}
|
||||
|
||||
trig1_timeout = TRIGGER_TIMEOUT_MS;
|
||||
//
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 杂波导致误触,回到空闲
|
||||
s1_state = DB_IDLE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DB_PRESSED: //确认按下
|
||||
|
||||
|
||||
|
||||
// 等待引脚回高电平
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 1)
|
||||
/*
|
||||
* ========================================================
|
||||
* 上电时 GPIO1 已经按下
|
||||
* ========================================================
|
||||
*/
|
||||
if(S1_first_on_state == 1)
|
||||
{
|
||||
S1_first_on_state = 0;
|
||||
s1_state = DB_PRESS_DEBOUNCE;
|
||||
s1_debounce_cnt = DEBOUNCE_MS;
|
||||
}
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* S1 状态机
|
||||
* ========================================================
|
||||
*/
|
||||
switch(s1_state)
|
||||
{
|
||||
case DB_IDLE:
|
||||
/*
|
||||
* 空闲状态低电平补检,防止漏中断。
|
||||
*/
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 0)
|
||||
{
|
||||
s1_state = DB_RELEASE_DEBOUNCE;
|
||||
s1_debounce_cnt = DEBOUNCE_MS; // 释放30ms防抖
|
||||
s1_state = DB_PRESS_DEBOUNCE;
|
||||
s1_debounce_cnt = DEBOUNCE_MS;
|
||||
}
|
||||
break;
|
||||
|
||||
case DB_RELEASE_DEBOUNCE: //释放防抖
|
||||
if(s1_debounce_cnt > 0) s1_debounce_cnt--;
|
||||
case DB_PRESS_DEBOUNCE:
|
||||
if(s1_debounce_cnt > 0)
|
||||
{
|
||||
s1_debounce_cnt--;
|
||||
}
|
||||
|
||||
if(s1_debounce_cnt == 0)
|
||||
{
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 1) // 确认释放
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 0)
|
||||
{
|
||||
s1_state = DB_IDLE; // 回到空闲
|
||||
trig1_timeout = TRIGGER_TIMEOUT_MS;
|
||||
|
||||
switch1_RELEASE_flag=1;
|
||||
if(s1_first_press_flag==1)
|
||||
{
|
||||
s1_first_press_flag=2;
|
||||
|
||||
}
|
||||
|
||||
s1_state = DB_PRESSED;
|
||||
|
||||
s1_press_cnt = 0;
|
||||
s1_long_press_done = 0;
|
||||
|
||||
/*
|
||||
* 连续触发计数
|
||||
*/
|
||||
if(trig1_wait == 0)
|
||||
{
|
||||
trig1_cnt = 1;
|
||||
trig1_timeout = TRIGGER_TIMEOUT_MS;
|
||||
trig1_wait = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(trig1_timeout > 0)
|
||||
{
|
||||
trig1_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* 如果等待标志还在,但超时已经为 0,
|
||||
* 说明旧状态异常,重新作为第一次点击。
|
||||
*/
|
||||
trig1_cnt = 1;
|
||||
}
|
||||
|
||||
trig1_timeout = TRIGGER_TIMEOUT_MS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 再等20ms
|
||||
s1_debounce_cnt = DEBOUNCE_MS; // 30ms
|
||||
s1_state = DB_IDLE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// switch(s2_state)
|
||||
// {
|
||||
// case DB_IDLE: //空闲状态
|
||||
// break;
|
||||
//
|
||||
// case DB_PRESS_DEBOUNCE: //按下防抖
|
||||
// if(s2_debounce_cnt>0) s2_debounce_cnt--;
|
||||
// if(s2_debounce_cnt==0)
|
||||
// {
|
||||
// //防抖时间到,采样当前电平是否是低电平
|
||||
// if(xc_gpio_read_pin(SWITCH_S2_PIN)==0)
|
||||
// {
|
||||
// s2_state = DB_PRESSED; //进入按下状态,不响应中断
|
||||
// if(trig2_wait == 0)
|
||||
// {
|
||||
// trig2_cnt = 1;
|
||||
// trig2_timeout = TRIGGER_TIMEOUT_MS;
|
||||
// trig2_wait = 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if(trig2_timeout>0)
|
||||
// {
|
||||
// trig2_cnt++;
|
||||
// }
|
||||
//
|
||||
// trig2_timeout = TRIGGER_TIMEOUT_MS;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 杂波导致误触,回到空闲
|
||||
// s2_state = DB_IDLE;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
//
|
||||
// case DB_PRESSED: //确认按下
|
||||
// // 等待引脚回高电平
|
||||
// if(xc_gpio_read_pin(SWITCH_S2_PIN) == 1)
|
||||
// {
|
||||
// s2_state = DB_RELEASE_DEBOUNCE;
|
||||
// s2_debounce_cnt = DEBOUNCE_MS; // 释放30ms防抖
|
||||
// }
|
||||
// break;
|
||||
case DB_PRESSED:
|
||||
/*
|
||||
* 按下超过 200ms:
|
||||
* 认为是普通不回弹墙壁开关,打开 GPIO5。
|
||||
*/
|
||||
if(s1_long_press_done == 0)
|
||||
{
|
||||
if(s1_press_cnt < RETURN_SWITCH_CNT)
|
||||
{
|
||||
s1_press_cnt++;
|
||||
}
|
||||
|
||||
// case DB_RELEASE_DEBOUNCE: //释放防抖
|
||||
// if(s2_debounce_cnt > 0) s2_debounce_cnt--;
|
||||
// if(s2_debounce_cnt == 0)
|
||||
// {
|
||||
// if(xc_gpio_read_pin(SWITCH_S2_PIN) == 1) // 确认释放
|
||||
// {
|
||||
// s2_state = DB_IDLE; // 回到空闲
|
||||
// trig2_timeout = TRIGGER_TIMEOUT_MS;
|
||||
// switch2_RELEASE_flag=1;
|
||||
// if(s2_first_press_flag==1)
|
||||
// {
|
||||
// s2_first_press_flag=2;
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 再等20ms
|
||||
// s2_debounce_cnt = DEBOUNCE_MS; // 30ms
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// S1 超时处理
|
||||
if(s1_press_cnt >= RETURN_SWITCH_CNT)
|
||||
{
|
||||
s1_long_press_done = 1;
|
||||
|
||||
/*
|
||||
* 普通不回弹开关只处理第一次有效按下。
|
||||
*
|
||||
* 注意:
|
||||
* 这里仍然要求 trig1_cnt == 1,
|
||||
* 避免快速多次点击被误判成长按开关打开。
|
||||
*/
|
||||
if(trig1_cnt == 1 && trig1_wait == 1)
|
||||
{
|
||||
trig1_cnt = 0;
|
||||
trig1_timeout = 0;
|
||||
trig1_wait = 0;
|
||||
|
||||
s1_return_click_flag = 0;
|
||||
switch1_RELEASE_flag = 0;
|
||||
|
||||
s1_first_press_flag = 1;
|
||||
|
||||
switch_s1_output_on();
|
||||
}
|
||||
else if(trig1_cnt >= TRIGGER_CONTINUE_CNT)
|
||||
{
|
||||
/*
|
||||
* ====================================================
|
||||
* 关键新增修复
|
||||
* ====================================================
|
||||
*
|
||||
* 如果已经快速拨动到了 5 次或以上,
|
||||
* 但是最后一次保持在打开状态超过 200ms,
|
||||
* 那么这一次对码序列作废。
|
||||
*
|
||||
* 后面即使再关闭,也不能进入对码。
|
||||
*/
|
||||
s1_pair_invalid_flag = 1;
|
||||
|
||||
/*
|
||||
* 防止旧的回弹点击标志残留。
|
||||
*/
|
||||
s1_return_click_flag = 0;
|
||||
switch1_RELEASE_flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 检测释放
|
||||
*/
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 1)
|
||||
{
|
||||
s1_state = DB_RELEASE_DEBOUNCE;
|
||||
s1_debounce_cnt = DEBOUNCE_MS;
|
||||
}
|
||||
break;
|
||||
|
||||
case DB_RELEASE_DEBOUNCE:
|
||||
if(s1_debounce_cnt > 0)
|
||||
{
|
||||
s1_debounce_cnt--;
|
||||
}
|
||||
|
||||
if(s1_debounce_cnt == 0)
|
||||
{
|
||||
if(xc_gpio_read_pin(SWITCH_S1_PIN) == 1)
|
||||
{
|
||||
s1_state = DB_IDLE;
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* 关键新增修复
|
||||
* ====================================================
|
||||
*
|
||||
* 如果前面已经判定:
|
||||
* 快速拨动 5 次后,最后一次停留打开超过 200ms,
|
||||
* 那么这次释放只是无效释放。
|
||||
*
|
||||
* 直接清理状态,不再进入后面的 5 次对码处理。
|
||||
*/
|
||||
if(s1_pair_invalid_flag == 1)
|
||||
{
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* 释放后重新给连击窗口计时。
|
||||
*/
|
||||
trig1_timeout = TRIGGER_TIMEOUT_MS;
|
||||
switch1_RELEASE_flag = 1;
|
||||
|
||||
if(s1_long_press_done == 0)
|
||||
{
|
||||
/*
|
||||
* 200ms 内释放:
|
||||
* 回弹点击。
|
||||
*/
|
||||
s1_return_click_flag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* 普通不回弹开关释放。
|
||||
*/
|
||||
if(s1_first_press_flag == 1)
|
||||
{
|
||||
s1_first_press_flag = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s1_debounce_cnt = DEBOUNCE_MS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
s1_state = DB_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* S1 连击超时处理
|
||||
* ========================================================
|
||||
*/
|
||||
if(trig1_timeout > 0)
|
||||
{
|
||||
trig1_timeout--;
|
||||
}
|
||||
else if(trig1_timeout==0 && switch1_RELEASE_flag==1 )
|
||||
{
|
||||
switch1_RELEASE_flag=2;
|
||||
}
|
||||
|
||||
|
||||
// 600ms倒计时结束,且有计数
|
||||
if(trig1_timeout == 0 && trig1_cnt == 1 && trig1_wait == 1 && s1_state == DB_PRESSED) //确定按下1次
|
||||
{
|
||||
//printf("按下一次 trig1_cnt %d\r\n",trig1_cnt);
|
||||
trig1_cnt = 0;
|
||||
trig1_wait = 0;
|
||||
s1_first_press_flag=1;
|
||||
xc_gpio_write_pin(GPIO_5,GPIO_PIN_SET);
|
||||
flash_ch1_state=xc_gpio_read_pin(GPIO_5);
|
||||
flash_run();
|
||||
|
||||
}
|
||||
|
||||
else if(trig1_timeout == 0 && (trig1_cnt > 1 && trig1_cnt < TRIGGER_CONTINUE_CNT))
|
||||
{
|
||||
// printf("乱按 trig1_cnt %d\r\n",trig1_cnt);
|
||||
trig1_cnt = 0;
|
||||
trig1_wait = 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if(trig1_timeout == 0 && trig1_cnt >= TRIGGER_CONTINUE_CNT)
|
||||
{
|
||||
//printf("对码 trig1_cnt %d\r\n",trig1_cnt);
|
||||
if( s1_state == DB_IDLE)
|
||||
{
|
||||
rf433_sw_flag = 2; // HPW421: S1/GPIO5 is the single relay L2 pairing key
|
||||
trig1_cnt = 0;
|
||||
trig1_wait = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
trig1_cnt = 0;
|
||||
trig1_wait = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else if(trig1_timeout == 0 && switch1_RELEASE_flag==2 && s1_state == DB_IDLE && s1_first_press_flag==2 )
|
||||
{
|
||||
// printf("低电平 trig2_cnt %d\r\n",trig2_cnt);
|
||||
s1_state = DB_IDLE;
|
||||
switch1_RELEASE_flag=0;
|
||||
s1_first_press_flag=0;
|
||||
xc_gpio_write_pin(GPIO_5,GPIO_PIN_RESET);
|
||||
flash_ch1_state=xc_gpio_read_pin(GPIO_5);
|
||||
flash_run();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // S2 超时处理
|
||||
// if(trig2_timeout > 0)
|
||||
// {
|
||||
// trig2_timeout--;
|
||||
// }
|
||||
// else if(trig2_timeout==0 && switch2_RELEASE_flag==1 )
|
||||
// {
|
||||
// switch2_RELEASE_flag=2;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // 600ms倒计时结束,且有计数
|
||||
// if(trig2_timeout == 0 && trig2_cnt == 1 && trig2_wait == 1 && s2_state == DB_PRESSED) //确定按下1次
|
||||
// {
|
||||
//
|
||||
// trig2_cnt = 0;
|
||||
// trig2_wait = 0;
|
||||
// s2_first_press_flag=1;
|
||||
//
|
||||
// xc_gpio_write_pin(GPIO_2,GPIO_PIN_SET);
|
||||
//
|
||||
// flash_ch2_state=xc_gpio_read_pin(GPIO_2);
|
||||
// flash_run();
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// else if(trig2_timeout == 0 && (trig2_cnt > 1 && trig2_cnt < TRIGGER_CONTINUE_CNT))
|
||||
// {
|
||||
//
|
||||
// trig2_cnt = 0;
|
||||
// trig2_wait = 0;
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
// else if(trig2_timeout == 0 && trig2_cnt >= TRIGGER_CONTINUE_CNT)
|
||||
// {
|
||||
//
|
||||
//
|
||||
// if( s2_state == DB_IDLE)
|
||||
// {
|
||||
// rf433_sw_flag = 2;
|
||||
// trig2_cnt = 0;
|
||||
// trig2_wait = 0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// trig2_cnt = 0;
|
||||
// trig2_wait = 0;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// else if(trig2_timeout == 0 && switch2_RELEASE_flag==2 && s2_state == DB_IDLE && s2_first_press_flag==2 )
|
||||
// {
|
||||
//
|
||||
//
|
||||
//
|
||||
// s2_state = DB_IDLE;
|
||||
// switch2_RELEASE_flag=0;
|
||||
// s2_first_press_flag=0;
|
||||
//
|
||||
// xc_gpio_write_pin(GPIO_2,GPIO_PIN_RESET);
|
||||
// flash_ch2_state=xc_gpio_read_pin(GPIO_2);
|
||||
// flash_run();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if(trig1_timeout == 0 && switch1_RELEASE_flag == 1)
|
||||
{
|
||||
switch1_RELEASE_flag = 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* S1 回弹开关处理
|
||||
* ========================================================
|
||||
*/
|
||||
if(trig1_timeout == 0 &&
|
||||
switch1_RELEASE_flag == 2 &&
|
||||
s1_state == DB_IDLE &&
|
||||
s1_return_click_flag == 1)
|
||||
{
|
||||
if(trig1_cnt == 1 && trig1_wait == 1)
|
||||
{
|
||||
/*
|
||||
* 单击:
|
||||
* GPIO5 翻转。
|
||||
*/
|
||||
switch_s1_clear_action_state();
|
||||
switch_s1_output_toggle();
|
||||
}
|
||||
else if(trig1_cnt > 1 && trig1_cnt < TRIGGER_CONTINUE_CNT)
|
||||
{
|
||||
/*
|
||||
* 2~4 次:
|
||||
* 不动作,但必须彻底清状态。
|
||||
*/
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
else if(trig1_cnt >= TRIGGER_CONTINUE_CNT)
|
||||
{
|
||||
/*
|
||||
* 5 次及以上:
|
||||
* 进入对码。
|
||||
*
|
||||
* 这里增加 s1_pair_invalid_flag 判断。
|
||||
* 正常快速拨动 5 次并最终关闭:进入对码。
|
||||
* 拨动 5 次后停留打开一段时间再关闭:不进入对码。
|
||||
*/
|
||||
if(s1_pair_invalid_flag == 0)
|
||||
{
|
||||
rf433_sw_flag = 2;
|
||||
}
|
||||
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* 异常兜底清理。
|
||||
*/
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ========================================================
|
||||
* 普通不回弹开关释放后关闭 GPIO5
|
||||
* ========================================================
|
||||
*/
|
||||
else if(trig1_timeout == 0 &&
|
||||
switch1_RELEASE_flag == 2 &&
|
||||
s1_state == DB_IDLE &&
|
||||
s1_first_press_flag == 2)
|
||||
{
|
||||
/*
|
||||
* 普通不回弹开关释放后关闭 GPIO5。
|
||||
*/
|
||||
switch_s1_clear_action_state();
|
||||
switch_s1_output_off();
|
||||
}
|
||||
/*
|
||||
* ========================================================
|
||||
* 兜底:2~4 次超时
|
||||
* ========================================================
|
||||
*/
|
||||
else if(trig1_timeout == 0 &&
|
||||
trig1_cnt > 1 &&
|
||||
trig1_cnt < TRIGGER_CONTINUE_CNT)
|
||||
{
|
||||
/*
|
||||
* 2~4 次:
|
||||
* 不动作,但是必须清理全部状态。
|
||||
*/
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
/*
|
||||
* ========================================================
|
||||
* 兜底:5 次及以上超时
|
||||
* ========================================================
|
||||
*/
|
||||
else if(trig1_timeout == 0 &&
|
||||
trig1_cnt >= TRIGGER_CONTINUE_CNT &&
|
||||
s1_state == DB_IDLE)
|
||||
{
|
||||
/*
|
||||
* 5 次及以上:
|
||||
*
|
||||
* 这里必须保留对码。
|
||||
* 因为正常快速拨动 5 次后,经常就是走这个兜底分支进入对码。
|
||||
*
|
||||
* 但是增加 s1_pair_invalid_flag 判断:
|
||||
* 如果是“5次后停留打开超过200ms再关闭”,则不允许对码。
|
||||
*/
|
||||
if(s1_pair_invalid_flag == 0)
|
||||
{
|
||||
rf433_sw_flag = 2;
|
||||
}
|
||||
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
/*
|
||||
* ========================================================
|
||||
* 兜底:异常释放状态
|
||||
* ========================================================
|
||||
*/
|
||||
else if(trig1_timeout == 0 &&
|
||||
switch1_RELEASE_flag == 2 &&
|
||||
s1_state == DB_IDLE &&
|
||||
trig1_cnt == 0 &&
|
||||
trig1_wait == 0)
|
||||
{
|
||||
/*
|
||||
* 防止残留 switch1_RELEASE_flag == 2。
|
||||
*/
|
||||
switch_s1_clear_action_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* GPIO 中断回调
|
||||
* ============================================================
|
||||
*/
|
||||
void gpio_intr_callback(uint64_t intr_sta)
|
||||
{
|
||||
if((intr_sta & ((uint64_t)1 << SWITCH_S1_PIN)) != 0) //如果是GPIO_1的中断
|
||||
{
|
||||
if(s1_state == DB_IDLE && S1_first_on_state==0) // 只有空闲才响应
|
||||
/*
|
||||
* GPIO1 下降沿中断
|
||||
*/
|
||||
if((intr_sta & ((uint64_t)1 << SWITCH_S1_PIN)) != 0)
|
||||
{
|
||||
if(s1_state == DB_IDLE && S1_first_on_state == 0)
|
||||
{
|
||||
s1_state = DB_PRESS_DEBOUNCE;
|
||||
s1_debounce_cnt = DEBOUNCE_MS; // 40ms防抖
|
||||
s1_debounce_cnt = DEBOUNCE_MS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if((intr_sta & ((uint64_t)1 << SWITCH_S2_PIN)) != 0) //如果是GPIO_19的中断
|
||||
// {
|
||||
// if(s2_state == DB_IDLE && S2_first_on_state==0)
|
||||
// {
|
||||
// s2_state = DB_PRESS_DEBOUNCE;
|
||||
// s2_debounce_cnt = DEBOUNCE_MS;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,75 @@
|
||||
#ifndef __SWITCH_S_H__
|
||||
#define __SWITCH_S_H__
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xc_drv_gpio.h"
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* 开关检测说明
|
||||
* ============================================================
|
||||
*
|
||||
* 当前版本只保留 S1:
|
||||
*
|
||||
* 输入:
|
||||
* GPIO1
|
||||
*
|
||||
* 输出:
|
||||
* GPIO5
|
||||
*
|
||||
* 功能:
|
||||
*
|
||||
* 1. 普通不回弹墙壁开关:
|
||||
* - GPIO1 按下超过 200ms 不松手:
|
||||
* GPIO5 打开。
|
||||
* - GPIO1 释放后:
|
||||
* GPIO5 关闭。
|
||||
*
|
||||
* 2. 回弹开关:
|
||||
* - GPIO1 200ms 内按下松开:
|
||||
* 认为是一次回弹点击。
|
||||
* - 单击 1 次:
|
||||
* GPIO5 翻转,开变关,关变开。
|
||||
* - 快速点击 2~4 次:
|
||||
* 不动作。
|
||||
* - 快速点击 5 次及以上,并且最终释放为关:
|
||||
* rf433_sw_flag = 2,进入对码。
|
||||
*
|
||||
* 3. 修复点:
|
||||
* - 对码后彻底清理所有开关状态,避免后续只能开不能关。
|
||||
* - DB_IDLE 状态增加 GPIO1 低电平补检,避免漏中断。
|
||||
* - 快速拨动 5 次后如果最后停在打开状态,等一段时间再关,
|
||||
* 不再进入对码。
|
||||
*/
|
||||
|
||||
// 400ms 超时
|
||||
#define TRIGGER_TIMEOUT_MS 20
|
||||
// 连续触发次数
|
||||
#define TRIGGER_CONTINUE_CNT 5
|
||||
// trigger_check_process() 实际调用周期,单位 ms
|
||||
#define SWITCH_SCAN_PERIOD_MS 10
|
||||
|
||||
#define SWITCH_S1_PIN GPIO_1
|
||||
#define SWITCH_S2_PIN GPIO_19
|
||||
// 连击超时时间:20 * 10ms = 200ms
|
||||
#define TRIGGER_TIMEOUT_MS 20
|
||||
|
||||
// 连续触发次数,达到 5 次进入对码
|
||||
#define TRIGGER_CONTINUE_CNT 5
|
||||
|
||||
// 回弹开关判断时间:200ms 内松手,认为是回弹开关
|
||||
#define RETURN_SWITCH_TIME_MS 200
|
||||
#define RETURN_SWITCH_CNT (RETURN_SWITCH_TIME_MS / SWITCH_SCAN_PERIOD_MS)
|
||||
|
||||
// S1 输入引脚
|
||||
#define SWITCH_S1_PIN GPIO_1
|
||||
|
||||
// 防抖状态机
|
||||
typedef enum {
|
||||
DB_IDLE = 0, // 空闲,等待下降沿
|
||||
DB_PRESS_DEBOUNCE, // 按下防抖中
|
||||
DB_PRESSED, // 确认按下,等待释放
|
||||
DB_RELEASE_DEBOUNCE // 释放防抖
|
||||
DB_IDLE = 0,
|
||||
DB_PRESS_DEBOUNCE,
|
||||
DB_PRESSED,
|
||||
DB_RELEASE_DEBOUNCE
|
||||
} debounce_state_t;
|
||||
|
||||
extern uint8_t rf433_sw_flag;
|
||||
|
||||
extern uint8_t S1_first_on_state;
|
||||
extern uint8_t S2_first_on_state;
|
||||
|
||||
void switch_init(void);
|
||||
|
||||
void trigger_check_process(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user