网站建设 南昌动漫设计与制作工资
网站建设 南昌,动漫设计与制作工资,佛山茂名网站建设,做平台网站怎么赚钱目录
一 背景说明
二 参考资料
三 MultiButton开源库移植
四 设计实现--驱动按键
五 设计实现--界面处理 一 背景说明 需要做一个通过不同按键控制多级界面切换以及界面动作的程序。 查阅相关资料#xff0c;发现网上大多数的应用都比较繁琐#xff0c;且对于多级界面的…目录
一 背景说明
二 参考资料
三 MultiButton开源库移植
四 设计实现--驱动按键
五 设计实现--界面处理 一 背景说明 需要做一个通过不同按键控制多级界面切换以及界面动作的程序。 查阅相关资料发现网上大多数的应用都比较繁琐且对于多级界面的切换逻辑可读性较差。所幸找到一篇使用开源库 MultiButton 来驱动按键并控制多级界面切换的博文。按图索骥实现了预期的需求。 开源库 MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块作者 0x1abin。这个项目非常精简只有两个文件可无限量扩展按键按键事件的回调异步处理方式可以简化程序结构去除冗余的按键处理硬编码让你的按键业务逻辑更清晰。 MultiButton 支持如下的按钮事件 MultiButton的状态机如下 二 参考资料 【1】MultiButton开源库mirrors / 0x1abin / MultiButton · GitCode 【2】MultiButton博文MultiButton | 一个小巧简单易用的事件驱动型按键驱动模块-CSDN博客 【3】MultiTimer开源库mirrors / 0x1abin / MultiTimer · GitCode 【4】MultiTimer博文【嵌入式开源库】MultiTimer 的使用一款可无限扩展的软件定时器_multi_timer-CSDN博客 【5】MultiButtonMultiTimer菜单操作博文开源按键组件MultiButton支持菜单操作(事件驱动型)-阿里云开发者社区 【注】我下面的实现没有用到MultiTimer仅单列出来备查。 三 MultiButton开源库移植 从上面的开源库或者github下载该开源库主要用到就两个文件 multi_button.c/multi_button.h 。将这两个文件直接添加到自己的工程中并关联头文件。 到这边编译应该没有问题。 四 设计实现--驱动按键 【1】首先初始化自己用到的几个按键GPIO口
void KNOB_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin KNOB_1_PIN | KNOB_2_PIN | KNOB_3_PIN | KNOB_4_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; //设置成上拉输入GPIO_Init(KNOB_PORT, GPIO_InitStructure);
} 【2】由于这边用到了四个按键申请四个按键结构
struct Button knob_1;
struct Button knob_2;
struct Button knob_3;
struct Button knob_4; 【3】编写回调函数绑定按键的GPIO电平读取接口
u8 knobRead(u8 button_id)
{switch(button_id){case 0:return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_1_PIN);case 1:return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_2_PIN);case 2:return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_3_PIN);case 3:return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_4_PIN);default:return 0;}
} 【4】关联 MultiButton 使用上面的按键结构以及回调函数初始化按键对象
button_init(knob_1, knobRead, 0, 0);
button_init(knob_2, knobRead, 0, 1);
button_init(knob_3, knobRead, 0, 2);
button_init(knob_4, knobRead, 0, 3); 【5】注册按键事件根据实际需要注册按键事件不必一次性全注册我这边只用到点按和长按所以只注册了 SINGLE_CLICK 和 LONG_PRESS_START 两个事件。 其中的回调函数 knobCallback_1/2/3/4 先空着后面需要结合界面切换来实现
button_attach(knob_1, SINGLE_CLICK, knobCallback_1);
button_attach(knob_1, LONG_PRESS_START, knobCallback_1);
button_attach(knob_2, SINGLE_CLICK, knobCallback_2);
button_attach(knob_2, LONG_PRESS_START, knobCallback_2);
button_attach(knob_3, SINGLE_CLICK, knobCallback_3);
button_attach(knob_3, LONG_PRESS_START, knobCallback_3);
button_attach(knob_4, SINGLE_CLICK, knobCallback_4);
button_attach(knob_4, LONG_PRESS_START, knobCallback_4); 【6】启动按键
button_start(knob_1);
button_start(knob_2);
button_start(knob_3);
button_start(knob_4); 【7】将上面【4】【5】【6】的三个步骤整个成一个按键注册接口
void KNOB_Reg(void)
{button_init(knob_1, knobRead, 0, 0);button_init(knob_2, knobRead, 0, 1);button_init(knob_3, knobRead, 0, 2);button_init(knob_4, knobRead, 0, 3);button_attach(knob_1, SINGLE_CLICK, knobCallback_1);button_attach(knob_1, LONG_PRESS_START, knobCallback_1);button_attach(knob_2, SINGLE_CLICK, knobCallback_2);button_attach(knob_2, LONG_PRESS_START, knobCallback_2);button_attach(knob_3, SINGLE_CLICK, knobCallback_3);button_attach(knob_3, LONG_PRESS_START, knobCallback_3);button_attach(knob_4, SINGLE_CLICK, knobCallback_4);button_attach(knob_4, LONG_PRESS_START, knobCallback_4);button_start(knob_1);button_start(knob_2);button_start(knob_3);button_start(knob_4);
} 【8】至此按键驱动还不能生效还需要添加一个心跳一般采用5ms间隔定时器来循环调用这个心跳函数定时器相关函数如下
//Timer14 5ms定时器
#define TIMER14_ARR (500-1)
#define TIMER14_PSC (960-1)void Timer14_Config(void)
{TIM_TimeBaseInitTypeDef TIM_StructInit;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM14, ENABLE);//使能定时器时钟//定时器基础配置TIM_StructInit.TIM_Period TIMER14_ARR; //自动重装值TIM_StructInit.TIM_Prescaler TIMER14_PSC; //预分频系数TIM_StructInit.TIM_ClockDivision TIM_CKD_DIV1; //时钟分频TIM_StructInit.TIM_CounterMode TIM_CounterMode_Up;//向上计数TIM_StructInit.TIM_RepetitionCounter 0; //不重复计数TIM_TimeBaseInit(TIM14, TIM_StructInit);//NVIC中断配置NVIC_InitStructure.NVIC_IRQChannel TIM14_IRQn;NVIC_InitStructure.NVIC_IRQChannelPriority 3; //数字越小优先级越高NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStructure);TIM_ClearFlag(TIM14, TIM_FLAG_Update);TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE); //使能更新中断TIM_Cmd(TIM14, ENABLE);
}extern void button_ticks(void);
void TIM14_IRQHandler(void)
{if(TIM_GetITStatus(TIM14, TIM_IT_Update) ! RESET){button_ticks(); //旋钮驱动心跳TIM_ClearITPendingBit(TIM14, TIM_IT_Update);}
} 【9】在主函数的初始化中加上上面几个接口
void main(void)
{//定时器初始化Timer14_Config();//旋钮初始化/注册KNOB_Init();KNOB_Reg();while(1){//...}
}至此MultiButton 开源库移植完毕并将所用的四个按钮关联到 MultiButton 按键事件待扩展。 五 设计实现--界面处理 【1】新建头文件新增界面相关的结构体定义等
typedef enum tagMenuTree //菜单树
{MENU_MAIN 0,MEUN_LOG
}MENU_TREE;typedef enum tagEventCode //事件值
{NULL_EVENT 0,KNOB_1_SHORT 1,KNOB_1_LONG 2,KNOB_2_SHORT 3,KNOB_2_LONG 4,KNOB_3_SHORT 5,KNOB_3_LONG 6,KNOB_4_SHORT 7,KNOB_4_LONG 8
}EVENT_CODE;typedef struct tagMenuInfo //界面信息
{u8 cur_page; //正在执行的界面u8 knb_evnt; //当前触发的事件
}MENU_INFO;
extern MENU_INFO menu;extern void Menu_Init(MENU_INFO *handle, u8 p_page, u8 p_evnt);
extern void Set_Menu(MENU_INFO *handle, u8 p_page);
extern u8 Get_Menu(MENU_INFO *handle);
extern void Set_Event_Code(MENU_INFO *handle, u8 p_evnt);
extern int Get_Event_Code(MENU_INFO *handle);
extern void Menu_Handler(MENU_INFO *handle); 【2】新建源文件新增界面相关的接口函数等
/**************************************************************************
* 函数名称 Menu_Init
* 功能描述 菜单初始化
**************************************************************************/
void Menu_Init(MENU_INFO *handle, u8 p_page, u8 p_evnt)
{memset(handle, 0, sizeof(MENU_INFO));handle-cur_page p_page;handle-knb_evnt p_evnt;
}/**************************************************************************
* 函数名称 Set_Menu/Get_Menu
* 功能描述 菜单跳转/获取当前菜单
**************************************************************************/
void Set_Menu(MENU_INFO *handle, u8 p_page)
{handle-cur_page p_page;
}u8 Get_Menu(MENU_INFO *handle)
{return handle-cur_page;
}/**************************************************************************
* 函数名称 Set_Event_Code/Get_Event_Code
* 功能描述 设置当前事件值/获取当前事件值
**************************************************************************/
void Set_Event_Code(MENU_INFO *handle, u8 p_evnt)
{handle-knb_evnt p_evnt;
}int Get_Event_Code(MENU_INFO *handle)
{return handle-knb_evnt;
} 【3】结合上述菜单处理函数关联“设计实现--驱动按键”中的【5】完善 knobCallback_1/2/3/4 的实现。 主要逻辑就是将按键的动作通过回调传递给菜单结构 menu 单列出knobCallback_1其他按钮的回调一样实现
void knobCallback_1(void *p_btn)
{u8 btn_event_val; btn_event_val get_button_event((struct Button *)p_btn); switch(btn_event_val){case SINGLE_CLICK:Set_Event_Code(menu, KNOB_1_SHORT);break ;case LONG_PRESS_START:Set_Event_Code(menu, KNOB_1_LONG);break ;default:break ;}
} 【4】菜单处理函数 Menu_Handler 的实现
void Menu_Handler(MENU_INFO *handle)
{switch(handle-cur_page){case MENU_MAIN:menuMainHandle(handle-knb_evnt);break ;case MEUN_LOG:menuLogHandle(handle-knb_evnt);break ;default:break ;}Set_Event_Code(handle, NULL_EVENT); //及时将事件清除防止重复触发
} 其中menuMainHandle/menuLogHandle 就是每个界面的具体实现了
void menuMainHandle(u8 p_evnt)
{cleanAll(); //清屏//主界面显示switch(p_evnt){case KNOB_1_SHORT:break ;case KNOB_1_LONG:Set_Menu(menu, MEUN_LOG); //进入登录界面break ;default:break;}
}
void menuLogHandle(u8 p_evnt)
{cleanAll(); //清屏//登录界面的显示switch(p_evnt){case KNOB_2_SHORT:break ;case KNOB_2_LONG:Set_Menu(menu, MENU_MAIN); //返回主界面break ;default:break;}
} 【5】在主函数的初始化中加上上面界面初始化接口同时界面处理函数置于主循环中执行
void main(void)
{//定时器初始化Timer14_Config();//旋钮初始化/注册KNOB_Init();KNOB_Reg();//界面初始化Menu_Init(menu, MENU_MAIN, NULL_EVENT);while(1){Menu_Handler(menu); //界面处理函数LCD_Update(); //用缓存刷新屏幕//...}
}至此完成了通过 MultiButton 开源库驱动按键并控制多级界面切换的工作。 上述DEMO中上电默认进入主界面可以通过长按 knob_1 进入登陆界面。在登陆界面中通过长按 knob_2 返回主界面长按的时间可以在 multi_button.h 中设置。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88304.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!