1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/bg4uvr-ds3231

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
button.c 8.2 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
bg4uvr Отправлено 5 лет назад 375fac1
/************************************************************
* @brief 按键驱动
* @param NULL
* @return NULL
* @author jiejie
* @github https://github.com/jiejieTop
* @date 2018-xx-xx
* @version v1.0
* @note button.c
***********************************************************/
#include "button.h"
#include "string.h"
//声明链表指针
static struct button* Head_Button = NULL; //这是一个指针,先声明成空的
//追加按键指针地址到链表中
static void Add_Button(Button_t* btn)
{
struct button *pass_btn = Head_Button; //读取链表头到一个静态指针
while(pass_btn) //如果指针非空
{
pass_btn = pass_btn->Next; //
}
btn->Next = Head_Button; //按键的下一按键指针,指向上原链表头
Head_Button = btn; //把本次按键结构体的地址装入链表头
}
/************************************************************
* @brief 按键创建
* @param name : 按键名称
* @param btn : 按键结构体
* @param read_btn_level : 按键电平读取函数,需要用户自己实现返回uint8_t类型的电平
* @param btn_trigger_level : 按键触发电平
* @return NULL
* @author jiejie
* @github https://github.com/jiejieTop
* @date 2018-xx-xx
* @version v1.0
* @note NULL
***********************************************************/
void Button_Create(const char *name,
Button_t *btn,
uint8_t(*read_btn_level)(void),
uint8_t btn_trigger_level)
{
memset(btn, 0, sizeof(struct button)); //清除结构体信息,建议用户在之前清除
btn->Button_State = NONE_TRIGGER; //按键状态
btn->Button_Last_State = NONE_TRIGGER; //按键上一次状态
btn->Button_Trigger_Event = NONE_TRIGGER; //按键触发事件
btn->Read_Button_Level = read_btn_level; //按键读电平函数
btn->Button_Trigger_Level = btn_trigger_level; //按键触发电平
btn->Button_Last_Level = btn->Read_Button_Level(); //按键当前电平
btn->Debounce_Time = 0;
Add_Button(btn); //创建的时候添加到单链表中
}
/************************************************************
* @brief 按键触发事件与回调函数映射链接起来
* @param btn : 按键结构体
* @param btn_event : 按键触发事件
* @param btn_callback : 按键触发之后的回调处理函数。需要用户实现
* @return NULL
* @author jiejie
* @github https://github.com/jiejieTop
* @date 2018-xx-xx
* @version v1.0
***********************************************************/
void Button_Attach(Button_t *btn,Button_Event btn_event,Button_CallBack btn_callback)
{
if(BUTTON_ALL_RIGGER == btn_event) //如果触发了全部事件
{
for(uint8_t i = 0 ; i < number_of_event-1 ; i++)
btn->CallBack_Function[i] = btn_callback; //按键事件触发的回调函数,用于处理按键事件
}
else
{
btn->CallBack_Function[btn_event] = btn_callback; //按键事件触发的回调函数,用于处理按键事件
}
}
/************************************************************
* @brief 删除一个已经创建的按键
* @param NULL
* @return NULL
* @author jiejie
* @github https://github.com/jiejieTop
* @date 2018-xx-xx
* @version v1.0
* @note NULL
***********************************************************/
void Button_Delete(Button_t *btn)
{
struct button** curr;
for(curr = &Head_Button; *curr;)
{
struct button* entry = *curr;
if (entry == btn)
{
*curr = entry->Next;
}
else
{
curr = &entry->Next;
}
}
}
/************************************************************
* @brief 按键周期处理函数
* @param btn:处理的按键
* @return NULL
* @author jiejie
* @github https://github.com/jiejieTop
* @date 2018-xx-xx
* @version v1.0
* @note 必须以一定周期调用此函数,建议周期为20~50ms
***********************************************************/
void Button_Cycle_Process(Button_t *btn)
{
uint8_t current_level = (uint8_t)btn->Read_Button_Level();//获取当前按键电平
//按键电平发生变化,消抖
if((current_level != btn->Button_Last_Level)&&(++(btn->Debounce_Time) >= BUTTON_DEBOUNCE_TIME))
{
btn->Button_Last_Level = current_level; //更新当前按键电平
btn->Debounce_Time = 0; //确定了是按下
//如果按键是没被按下的,改变按键状态为按下(首次按下/双击按下)
if((btn->Button_State == NONE_TRIGGER)||(btn->Button_State == BUTTON_DOUBLE))
{
btn->Button_State = BUTTON_DOWM; //按键状态改为按下
}
//释放按键
else if(btn->Button_State == BUTTON_DOWM)//如果状态是已按下
{
btn->Button_State = BUTTON_UP; //状态更改为已释放
//PRINT_DEBUG("释放了按键");
}
}
//按键状态处理
switch(btn->Button_State)
{
case BUTTON_DOWM : //按下状态
{
if(btn->Button_Last_Level == btn->Button_Trigger_Level) //如果当前电平和有效状态相同
{
#if CONTINUOS_TRIGGER //支持连续触发
if(++(btn->Button_Cycle) >= BUTTON_CONTINUOS_CYCLE)
{
btn->Button_Cycle = 0;
btn->Button_Trigger_Event = BUTTON_CONTINUOS;
TRIGGER_CB(BUTTON_CONTINUOS); //连按
//PRINT_DEBUG("连按");
}
#else
btn->Button_Trigger_Event = BUTTON_DOWM; //产生按下事件
if(++(btn->Long_Time) >= BUTTON_LONG_TIME) //释放按键前更新触发事件为长按
{
#if LONG_FREE_TRIGGER
btn->Button_Trigger_Event = BUTTON_LONG;
#else
if(++(btn->Button_Cycle) >= BUTTON_LONG_CYCLE) //连续触发长按的周期
{
btn->Button_Cycle = 0;
btn->Button_Trigger_Event = BUTTON_LONG; //触发长按事件
TRIGGER_CB(BUTTON_LONG); //执行长按事件触发的对象
}
#endif
if(btn->Long_Time == 0xFF) //更新时间溢出
{
btn->Long_Time = BUTTON_LONG_TIME; //重设为长按最小判断时间
}
//PRINT_DEBUG("长按");
}
#endif
}
break;
}
case BUTTON_UP : // 弹起状态
{
if(btn->Button_Trigger_Event == BUTTON_DOWM) //触发单击
{
if((btn->Timer_Count <= BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State == BUTTON_DOUBLE)) // 双击
{
btn->Button_Trigger_Event = BUTTON_DOUBLE;
TRIGGER_CB(BUTTON_DOUBLE);
//PRINT_DEBUG("双击");
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = NONE_TRIGGER;
}
else
{
btn->Timer_Count=0;
btn->Long_Time = 0; //检测长按失败,清0
#if (SINGLE_AND_DOUBLE_TRIGGER == 0)
TRIGGER_CB(BUTTON_DOWM); //执行单击事件触发对象
#endif
btn->Button_State = BUTTON_DOUBLE;
btn->Button_Last_State = BUTTON_DOUBLE;
}
}
else if(btn->Button_Trigger_Event == BUTTON_LONG)
{
#if LONG_FREE_TRIGGER
TRIGGER_CB(BUTTON_LONG); //长按
#else
TRIGGER_CB(BUTTON_LONG_FREE); //长按释放
#endif
btn->Long_Time = 0;
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = BUTTON_LONG;
}
#if CONTINUOS_TRIGGER
else if(btn->Button_Trigger_Event == BUTTON_CONTINUOS) //连按
{
btn->Long_Time = 0;
TRIGGER_CB(BUTTON_CONTINUOS_FREE); //连发释放
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = BUTTON_CONTINUOS;
}
#endif
break;
}
case BUTTON_DOUBLE :
{
btn->Timer_Count++; //时间记录
if(btn->Timer_Count>=BUTTON_DOUBLE_TIME)
{
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = NONE_TRIGGER;
}
#if SINGLE_AND_DOUBLE_TRIGGER
if((btn->Timer_Count>=BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State != BUTTON_DOWM))
{
btn->Timer_Count=0;
TRIGGER_CB(BUTTON_DOWM); //单击
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = BUTTON_DOWM;
}
#endif
break;
}
default :
break;
}
}
/************************************************************
* @brief 遍历的方式扫描按键,不会丢失每个按键
* @param NULL
* @return NULL
* @author jiejie
* @github https://github.com/jiejieTop
* @date 2018-xx-xx
* @version v1.0
* @note 此函数要周期调用,建议20-50ms调用一次
***********************************************************/
void Button_Process(void)
{
struct button* pass_btn;
for(pass_btn = Head_Button; pass_btn != NULL; pass_btn = pass_btn->Next)
{
Button_Cycle_Process(pass_btn);
}
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/bg4uvr-ds3231.git
git@gitlife.ru:oschina-mirror/bg4uvr-ds3231.git
oschina-mirror
bg4uvr-ds3231
bg4uvr-ds3231
master