修改长按逻辑为延时关闭,且不提供复位和清零配置

This commit is contained in:
WangQiang 2016-04-22 08:57:27 +00:00
parent 5de32c89e3
commit 6fc7930c40
2 changed files with 152 additions and 67 deletions

View File

@ -6,34 +6,32 @@
#define BTN_DEBUG DEBUG #define BTN_DEBUG DEBUG
//#define BTN_DEBUG 0 //#define BTN_DEBUG 0
#if BTN_DEBUG #if BTN_DEBUG
#define btn_printf debug_printf #define btn_printf debug_printf
#else #else
#define btn_printf(format, ...) #define btn_printf(format, ...)
#endif #endif
InputPort* Button_GrayLevel::ACZero = nullptr; InputPort* Button_GrayLevel::ACZero = nullptr;
byte Button_GrayLevel::OnGrayLevel = 0xFF; // 开灯时 led 灰度 byte Button_GrayLevel::OnGrayLevel = 0xFF; // 开灯时 led 灰度
byte Button_GrayLevel::OffGrayLevel = 0x00; // 关灯时 led 灰度 byte Button_GrayLevel::OffGrayLevel = 0x00; // 关灯时 led 灰度
int Button_GrayLevel::ACZeroAdjTime=2300; int Button_GrayLevel::ACZeroAdjTime = 2300;
Button_GrayLevel::Button_GrayLevel() : ByteDataPort() Button_GrayLevel::Button_GrayLevel() : ByteDataPort()
{ {
#if DEBUG #if DEBUG
Name = nullptr; Name = nullptr;
#endif #endif
Index = 0; Index = 0;
_Value = false; _Value = false;
_Pwm = nullptr; _Pwm = nullptr;
_Channel = 0; _Channel = 0;
_Handler = nullptr; _Handler = nullptr;
_Param = nullptr; _Param = nullptr;
_tid = 0; _tid = 0;
Next = 0xFF; Next = 0xFF;
OnPress = nullptr;
} }
void Button_GrayLevel::Set(Pin key, Pin relay, bool relayInvert) void Button_GrayLevel::Set(Pin key, Pin relay, bool relayInvert)
@ -41,22 +39,21 @@ void Button_GrayLevel::Set(Pin key, Pin relay, bool relayInvert)
Key.Set(key); Key.Set(key);
// 中断过滤模式 // 中断过滤模式
if(!OnPress) Key.Mode = InputPort::Both;
Key.Mode = InputPort::Rising;
Key.ShakeTime = 40; Key.ShakeTime = 40;
Key.Register(OnKeyPress, this); Key.Register(OnKeyPress, this);
Key.Open(); Key.Open();
if(relay != P0) Relay.Init(relay, relayInvert).Open(); if (relay != P0) Relay.Init(relay, relayInvert).Open();
} }
void Button_GrayLevel::Set(PWM* drive, byte pulseIndex) void Button_GrayLevel::Set(PWM* drive, byte pulseIndex)
{ {
if(drive && pulseIndex < 4) if (drive && pulseIndex < 4)
{ {
_Pwm = drive; _Pwm = drive;
_Channel = pulseIndex; _Channel = pulseIndex;
// 刷新输出 // 刷新输出
RenewGrayLevel(); RenewGrayLevel();
} }
@ -64,9 +61,27 @@ void Button_GrayLevel::Set(PWM* drive, byte pulseIndex)
void Button_GrayLevel::RenewGrayLevel() void Button_GrayLevel::RenewGrayLevel()
{ {
if(_Pwm) if (_Pwm)
{ {
_Pwm->Pulse[_Channel] = _Value? (0xFF - OnGrayLevel) : (0xFF - OffGrayLevel); _Pwm->Pulse[_Channel] = _Value ? (0xFF - OnGrayLevel) : (0xFF - OffGrayLevel);
_Pwm->Config();
}
}
void Button_GrayLevel::GrayLevelUp()
{
if (_Pwm)
{
_Pwm->Pulse[_Channel] = (0xFF - OnGrayLevel);
_Pwm->Config();
}
}
void Button_GrayLevel::GrayLevelDown()
{
if (_Pwm)
{
_Pwm->Pulse[_Channel] = (0xFF - OnGrayLevel);
_Pwm->Config(); _Pwm->Config();
} }
} }
@ -74,26 +89,77 @@ void Button_GrayLevel::RenewGrayLevel()
void Button_GrayLevel::OnKeyPress(InputPort* port, bool down, void* param) void Button_GrayLevel::OnKeyPress(InputPort* port, bool down, void* param)
{ {
Button_GrayLevel* btn = (Button_GrayLevel*)param; Button_GrayLevel* btn = (Button_GrayLevel*)param;
if(btn) btn->OnKeyPress(port, down); if (btn) btn->OnKeyPress(port, down);
} }
void Button_GrayLevel::OnKeyPress(InputPort* port, bool down) void Button_GrayLevel::OnKeyPress(InputPort* port, bool down)
{ {
// 每次按下弹起,都取反状态 // 每次按下弹起,都取反状态
if(down) /*if(down)
{ {
SetValue(!_Value); SetValue(!_Value);
if(_Handler) _Handler(this, _Param); if(_Handler) _Handler(this, _Param);
} }
else*/
if (!down) // 要处理长按而不动作 所以必须是弹起响应
{
switch (Stat)
{
case normal:
// 常规模式,长按进入设置模式,并且不动作。否则执行动作
if (_Value == true)
{
if (port->PressTime > 1500)
{
if (port->PressTime > 3000)
DelayClose2(10 * 60 * 1000);
else
DelayClose2(2 * 60 * 1000);
return;
}
}
SetValue(!_Value);
if (_Handler) _Handler(this, _Param);
break;
case set:
Stat = normal;
Next = 0xff;
SetValue(!_Value);
if (_Handler) _Handler(this, _Param);
break;
}
}
}
void Close2Task(void * param)
{
auto bt = (Button_GrayLevel *)param;
bt->GrayLevelUp();
if (bt->delaytime > 1000)
{
bt->delaytime = bt->delaytime - 1000;
Sys.SetTask(bt->_task2, true, 1000);
}
else else
{ {
if(OnPress) OnPress(port, down, this); bt->delaytime = 0;
Sys.SetTask(bt->_task2, false);
bt->SetValue(false);
} }
Sys.Sleep(100);
bt->GrayLevelDown();
}
void Button_GrayLevel::DelayClose2(int ms)
{
if (_task2)Sys.AddTask(Close2Task, this, -1, 1000, "button close");
Sys.SetTask(_task2, true, 1000);
delaytime = ms;
} }
void Button_GrayLevel::Register(EventHandler handler, void* param) void Button_GrayLevel::Register(EventHandler handler, void* param)
{ {
if(handler) if (handler)
{ {
_Handler = handler; _Handler = handler;
_Param = param; _Param = param;
@ -122,30 +188,30 @@ bool Button_GrayLevel::GetValue() { return _Value; }
bool CheckZero(InputPort* port) bool CheckZero(InputPort* port)
{ {
int retry = 200; int retry = 200;
while(*port == false && retry-- > 0) Time.Delay(100); // 检测下降沿 先去掉低电平 whileio==false while (*port == false && retry-- > 0) Time.Delay(100); // 检测下降沿 先去掉低电平 whileio==false
if(retry <= 0) return false; if (retry <= 0) return false;
retry = 200; retry = 200;
while(*port == true && retry-- > 0) Time.Delay(100); // 当检测到 高电平结束 就是下降沿的到来 while (*port == true && retry-- > 0) Time.Delay(100); // 当检测到 高电平结束 就是下降沿的到来
if(retry <= 0) return false; if (retry <= 0) return false;
return true; return true;
} }
void Button_GrayLevel::SetValue(bool value) void Button_GrayLevel::SetValue(bool value)
{ {
_Value = value; _Value = value;
if(ACZero && ACZero->Opened) if (ACZero && ACZero->Opened)
{ {
if(CheckZero(ACZero)) Time.Delay(ACZeroAdjTime); if (CheckZero(ACZero)) Time.Delay(ACZeroAdjTime);
// 经检测 过零检测电路的信号是 高电平12ms 低电平7ms 即下降沿后8.5ms 是下一个过零点 // 经检测 过零检测电路的信号是 高电平12ms 低电平7ms 即下降沿后8.5ms 是下一个过零点
// 从给出信号到继电器吸合 测量得到的时间是 6.4ms 继电器抖动 1ms左右 即 平均在7ms上下 // 从给出信号到继电器吸合 测量得到的时间是 6.4ms 继电器抖动 1ms左右 即 平均在7ms上下
// 故这里添加1ms延时 // 故这里添加1ms延时
// 这里有个不是问题的问题 一旦过零检测电路烧了 开关将不能正常工作 // 这里有个不是问题的问题 一旦过零检测电路烧了 开关将不能正常工作
} }
Relay = value; Relay = value;
RenewGrayLevel(); RenewGrayLevel();
} }
@ -153,10 +219,10 @@ void Button_GrayLevel::SetValue(bool value)
bool Button_GrayLevel::SetACZeroPin(Pin aczero) bool Button_GrayLevel::SetACZeroPin(Pin aczero)
{ {
// 该方法需要检查并释放旧的,避免内存泄漏 // 该方法需要检查并释放旧的,避免内存泄漏
if(!ACZero) ACZero = new InputPort(aczero); if (!ACZero) ACZero = new InputPort(aczero);
// 需要检测是否有交流电,否则关闭 // 需要检测是否有交流电,否则关闭
if(CheckZero(ACZero)) return true; if (CheckZero(ACZero)) return true;
ACZero->Close(); ACZero->Close();
@ -171,15 +237,15 @@ void Button_GrayLevel::Init(TIMER tim, byte count, Button_GrayLevel* btns, Event
// 配置PWM来源 // 配置PWM来源
static PWM LedPWM(tim); static PWM LedPWM(tim);
// 设置分频 尽量不要改 Prescaler * Period 就是 PWM 周期 // 设置分频 尽量不要改 Prescaler * Period 就是 PWM 周期
LedPWM.Prescaler = 0x04; // 随便改 只要肉眼看不到都没问题 LedPWM.Prescaler = 0x04; // 随便改 只要肉眼看不到都没问题
LedPWM.Period = 0xFF; // 对应灰度调节范围 LedPWM.Period = 0xFF; // 对应灰度调节范围
LedPWM.Polarity = true; // 极性。默认true高电平。如有必要将来根据Led引脚自动检测初始状态 LedPWM.Polarity = true; // 极性。默认true高电平。如有必要将来根据Led引脚自动检测初始状态
LedPWM.Open(); LedPWM.Open();
// 配置 LED 引脚 // 配置 LED 引脚
static AlternatePort Leds[4]; static AlternatePort Leds[4];
for(int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
Leds[i].Set(pins[i].Led); Leds[i].Set(pins[i].Led);
Leds[i].Open(); Leds[i].Open();
@ -187,30 +253,30 @@ void Button_GrayLevel::Init(TIMER tim, byte count, Button_GrayLevel* btns, Event
} }
// 设置默认灰度 // 设置默认灰度
if(level[0] == 0x00) if (level[0] == 0x00)
{ {
level[0] = 250; level[0] = 250;
level[1] = 20; level[1] = 20;
} }
// 使用 Data 记录的灰度 // 使用 Data 记录的灰度
OnGrayLevel = level[0]; OnGrayLevel = level[0];
OffGrayLevel = level[1]; OffGrayLevel = level[1];
// 配置 Button 主体 // 配置 Button 主体
for(int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
btns[i].Set(pins[i].Key, pins[i].Relay, pins[i].Invert); btns[i].Set(pins[i].Key, pins[i].Relay, pins[i].Invert);
} }
#if DEBUG #if DEBUG
const char* names[] = {"一号", "二号", "三号", "四号"}; const char* names[] = { "一号", "二号", "三号", "四号" };
#endif #endif
for(int i=0; i < count; i++) for (int i = 0; i < count; i++)
{ {
btns[i].Index = i; btns[i].Index = i;
#if DEBUG #if DEBUG
btns[i].Name = names[i]; btns[i].Name = names[i];
#endif #endif
btns[i].Register(onpress); btns[i].Register(onpress);
@ -218,20 +284,20 @@ void Button_GrayLevel::Init(TIMER tim, byte count, Button_GrayLevel* btns, Event
btns[i].Set(&LedPWM, pins[i].PwmIndex); btns[i].Set(&LedPWM, pins[i].PwmIndex);
// 如果是热启动,恢复开关状态数据 // 如果是热启动,恢复开关状态数据
if(state && state[i]) btns[i].SetValue(true); if (state && state[i]) btns[i].SetValue(true);
} }
} }
void ACZeroReset(void *param) void ACZeroReset(void *param)
{ {
InputPort* port = Button_GrayLevel::ACZero; InputPort* port = Button_GrayLevel::ACZero;
if(port) if (port)
{ {
//Sys.Reset(); //Sys.Reset();
debug_printf("定时检查过零检测\r\n"); debug_printf("定时检查过零检测\r\n");
// 需要检测是否有交流电,否则关闭 // 需要检测是否有交流电,否则关闭
if(CheckZero(port)) return; if (CheckZero(port)) return;
port->Close(); port->Close();
} }
@ -239,12 +305,12 @@ void ACZeroReset(void *param)
void Button_GrayLevel::InitZero(Pin zero, int us) void Button_GrayLevel::InitZero(Pin zero, int us)
{ {
if(zero == P0) return; if (zero == P0) return;
debug_printf("\r\n过零检测引脚PB12探测\r\n"); debug_printf("\r\n过零检测引脚PB12探测\r\n");
Button_GrayLevel::SetACZeroAdjTime(us); Button_GrayLevel::SetACZeroAdjTime(us);
if(Button_GrayLevel::SetACZeroPin(zero)) if (Button_GrayLevel::SetACZeroPin(zero))
debug_printf("已连接交流电!\r\n"); debug_printf("已连接交流电!\r\n");
else else
debug_printf("未连接交流电或没有使用过零检测电路\r\n"); debug_printf("未连接交流电或没有使用过零检测电路\r\n");
@ -257,20 +323,20 @@ void Button_GrayLevel::InitZero(Pin zero, int us)
bool Button_GrayLevel::UpdateLevel(byte* level, Button_GrayLevel* btns, byte count) bool Button_GrayLevel::UpdateLevel(byte* level, Button_GrayLevel* btns, byte count)
{ {
bool rs = false; bool rs = false;
if(OnGrayLevel != level[0]) if (OnGrayLevel != level[0])
{ {
OnGrayLevel = level[0]; OnGrayLevel = level[0];
rs = true; rs = true;
} }
if(OnGrayLevel != level[1]) if (OnGrayLevel != level[1])
{ {
OnGrayLevel = level[1]; OnGrayLevel = level[1];
rs = true; rs = true;
} }
if(rs) if (rs)
{ {
debug_printf("指示灯灰度调整\r\n"); debug_printf("指示灯灰度调整\r\n");
for(int i = 0; i < count; i++) for (int i = 0; i < count; i++)
btns[i].RenewGrayLevel(); btns[i].RenewGrayLevel();
} }
return rs; return rs;

View File

@ -15,6 +15,14 @@ struct ButtonPin
byte PwmIndex; byte PwmIndex;
}; };
enum ButtonStat :byte
{
normal = 0, // 正常
set = 1, // 设置
externSet = 2, // 外部设置
execution = 3, // 执行设置
};
// 面板按钮 // 面板按钮
// 这里必须使用_packed关键字生成对齐的代码否则_Value只占一个字节导致后面的成员进行内存操作时错乱 // 这里必须使用_packed关键字生成对齐的代码否则_Value只占一个字节导致后面的成员进行内存操作时错乱
//__packed class Button //__packed class Button
@ -22,16 +30,19 @@ struct ButtonPin
class Button_GrayLevel : public ByteDataPort class Button_GrayLevel : public ByteDataPort
{ {
public: public:
int Index; // 索引号,方便在众多按钮中标识按钮 int Index; // 索引号,方便在众多按钮中标识按钮
#if DEBUG #if DEBUG
const char* Name; // 按钮名称 const char* Name; // 按钮名称
#endif #endif
InputPort Key; // 输入按键 InputPort Key; // 输入按键
OutputPort Relay; // 继电器 OutputPort Relay; // 继电器
enum ButtonStat Stat = normal; // 状态
// 长按事件。 // 外部设置模式调用
InputPort::IOReadHandler OnPress; typedef bool(*IOHandler)(Button_GrayLevel* bt, bool down, void * param);
IOHandler ExterSet = nullptr;
void * ExterSetParam = nullptr;
public: public:
// 构造函数。指示灯和继电器一般开漏输出,需要倒置 // 构造函数。指示灯和继电器一般开漏输出,需要倒置
@ -45,6 +56,9 @@ public:
void RenewGrayLevel(); void RenewGrayLevel();
void Register(EventHandler handler, void* param = nullptr); void Register(EventHandler handler, void* param = nullptr);
virtual int Write(byte* pcmd); // 重载 ByteDataPort 的函数 自定义 Delay Flush Open Close
//virtual int Read(byte* cmd);
virtual int OnWrite(byte data); virtual int OnWrite(byte data);
virtual byte OnRead(); virtual byte OnRead();
@ -70,7 +84,12 @@ public:
static void InitZero(Pin zero, int us = 2300); static void InitZero(Pin zero, int us = 2300);
static bool UpdateLevel(byte* level, Button_GrayLevel* btns, byte count); static bool UpdateLevel(byte* level, Button_GrayLevel* btns, byte count);
// 过零检测 void GrayLevelDown();
void GrayLevelUp();
void DelayClose2(int ms); // 自定义延时关闭
int delaytime = 0;
int _task2 = 0;
// 过零检测
private: private:
static int ACZeroAdjTime; // 过零检测时间补偿 默认 2300us static int ACZeroAdjTime; // 过零检测时间补偿 默认 2300us
@ -78,7 +97,7 @@ public:
static InputPort* ACZero; // 交流过零检测引脚 static InputPort* ACZero; // 交流过零检测引脚
static bool SetACZeroPin(Pin aczero); // 设置过零检测引脚 static bool SetACZeroPin(Pin aczero); // 设置过零检测引脚
static void SetACZeroAdjTime(int us){ ACZeroAdjTime = us; }; // 设置 过零检测补偿时间 static void SetACZeroAdjTime(int us) { ACZeroAdjTime = us; }; // 设置 过零检测补偿时间
}; };
#endif #endif