//结构体 声明
#include <Wire.h>
typedef struct//按键 按键状态
{
byte val; //当前读取的电平
byte last_val; //上一次的电平
byte change; //标记改变
byte press_tick; //按下时间
byte long_press_flag; //长按标志 用来屏蔽松开的时候检测到
} KEY_T;
typedef struct//按键信息
{
byte id; //按键号
byte press; //是否按下
byte update_flag; //是否最新 和press共用在进入判断后二者同时判断
//判断成功后 最新变为0
byte long_press; //是否长按 正在长按的标记
} KEY_MSG;
//变量声明
unsigned short key_long_press_tick = 0;//按键长按计数
KEY_T key[2] = {0}; //按键对象
KEY_MSG key_msg = {0};//按键消息
///函数
byte get_io_val(byte ch) //获取io的电平
{
if (ch == 0) //通道0 引脚2
{
return digitalRead(18);
}
else
{
return digitalRead(19); //通道1 引脚3
}
}
void key_proc(void)//按键处理 发送倒计时
{
for (int i = 0; i < 2; i++)
{
if (key[i].change == 1) //如果按键改变了 可以认为有按键按下/松开了
{
key[i].change = 0;//清除标志
if (key[i].val == 0)//如果按下
{
key_long_press_tick = 10; //开始长按倒计时 通过试车
}
else //如果松开
{
if (key[i].long_press_flag) //如果长按了
{
key[i].long_press_flag = 0; //清除松开标志
key[i].press_tick = 0;//清掉抬起计数
}
else
{
key[i].press_tick = 1;//如果没长按 则认为是短按 计数
}
}
}
}
}
void key_init(void) //按键初始化
{
for (int i = 0; i < 2; i++)
{
key[i].val = key[i].last_val = get_io_val(i);//将按键初始化成上电时候的状态
}
}//
void key_scan(void)//按键扫描扫描是否按下
{
for (int i = 0; i < 2; i++)
{
key[i].val = get_io_val(i); //获取当前的按键状态
if (key[i].val != key[i].last_val) //如果按键发生改变
{
key[i].last_val = key[i].val; //更新状态
key[i].change = 1; //记录改变
}
}
}
void key_press_cb(void) //按键回调 1ms调用一次 按键正在按下时的处理
{
if (key_long_press_tick != 0)//如果按下 长按计数不为0 即为按下时
{
key_long_press_tick--;//--
if (key_long_press_tick == 0) //如果计时时间结束
{
for (int i = 0; i < 2; i++)
{
if (key[i].val == 0)//遍历按键 如果还有按下的 则证明按键为长按
{
key_msg.id = i;
key_msg.press = 1;
key_msg.update_flag = 1;
key_msg.long_press = 1;
key[i].long_press_flag = 1; //发送长按msg
}
}
}
}
key_down_cb();
}
void key_down_cb(void)//按键松开判断 主要来 判断是否为短按
{
for (int i = 0; i < 2; i++)
{
if (key[i].press_tick) //如果有 短按按键计数
{
key[i].press_tick--; //计数减一
if (!key[i].press_tick) //如果为0
{
key_msg.id = i; //发送短按msg
key_msg.press = 1;
key_msg.update_flag = 1;
key_msg.long_press = 0;
}
}
}
}
void system_tick(void)//系统1ms时钟 在里面放入
{
static unsigned long tick = 0;
if (tick != millis())//millis()函数为程序运行以来 的时间
{
tick = millis(); //基本上为1ms 调用一次
key_scan();//--1ms 一次按键扫描
key_press_cb();//1ms运行一次 按键按下处理
}
}
void setup()
{
// put your setup code here, to run once:
pinMode(18, INPUT_PULLUP);
pinMode(19, INPUT_PULLUP);
pinMode(13, OUTPUT);
pinMode(14, OUTPUT);
pinMode(12, OUTPUT);
pinMode(27, OUTPUT);
key_init();
}
void loop() {
system_tick();
}