做服装找工作网站农产品网站建设及优化项目

当前位置: 首页 > news >正文

做服装找工作网站,农产品网站建设及优化项目,可以自己做主题的软件,重庆网站建设重庆按键收集单击,双击和长按 引言 在我们生活中, 按键是必不可少的, 不同的电器, 有不同的按键, 但是按键总有不够用的时候, 那么给与一个按键赋予不同的功能,就必不可少了. 一个按键可以通过按下的时间长短和频次, 来定义其类型。 一次按键收集#xff0c; 都是在一个按键收集周…按键收集单击,双击和长按 引言 在我们生活中, 按键是必不可少的, 不同的电器, 有不同的按键, 但是按键总有不够用的时候, 那么给与一个按键赋予不同的功能,就必不可少了. 一个按键可以通过按下的时间长短和频次, 来定义其类型。 一次按键收集 都是在一个按键收集周期的 比如500毫秒内 我要收集一个按键类型 在500毫秒内按键按下一次按键 那么到达500毫秒后 我们就宣布答案 此次按键是单击。 同理 在500毫秒内 如果我们按下了 两次按键那么就是双击 以此类推。 那长按呢 长按就是 在500毫秒内 我们按下了按键并且500ms时间到时, 按键还未松开, 就代表着长按。 本博客最终修改项目链接下载: 点击下载 https://wwyz.lanzoul.com/itXC327v9dra 按键收集模型 单片机实现方法 因为按键, 需要每时每刻的去检测, 是否按下, 如果使用while阻塞循环, 则会大大影响程序效率, 所以我们使用外部中断去检测中断。 按键事件触发检测 按键按下的瞬间 单片机的io口, 就会被从高电平拉到低电平, 然后单片机io口就会检测到, 从而触发下降沿中断。 此时就代表着按键事件已经触发了。 按键类型判断 ​ 按键事件触发仅仅代表着我们按下了按键 但是我们想区分单击双击和长按 那么我们就得从按键按下开始计算直到按键计算周期结束这一段时间我们定义成 500毫秒。 所以 我们在按键事件触发后我们需要启动定时器计时500ms, 然后500ms时间到后, 判断按键按下的次数, 还有按键此时是否仍然被按下. 在这 500毫秒内, 我们重复按下按键, 就需要重复的检测按键按下的事件, 然后计入按键次数内. 所以我们的处理模型是 代码实现 按键中断 按键中断初始化 我们初始化io端口PB1配置下降沿中断 void Key_Init(void) {GPIO_InitTypeDef gpio_initstruct;EXTI_InitTypeDef exti_initstruct; NVIC_InitTypeDef nvic_initstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //打开复用时钟gpio_initstruct.GPIO_Mode GPIO_Mode_IPU; //设置为输出gpio_initstruct.GPIO_Pin GPIO_Pin_1; //将初始化的Pin脚gpio_initstruct.GPIO_Speed GPIO_Speed_50MHz; //可承载的最大频率GPIO_Init(GPIOB, gpio_initstruct); //初始化GPIOGPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);exti_initstruct.EXTI_Line EXTI_Line1;exti_initstruct.EXTI_Mode EXTI_Mode_Interrupt;exti_initstruct.EXTI_Trigger EXTI_Trigger_Falling;exti_initstruct.EXTI_LineCmd ENABLE;EXTI_Init(exti_initstruct);nvic_initstruct.NVIC_IRQChannel EXTI1_IRQn;nvic_initstruct.NVIC_IRQChannelPreemptionPriority 2;nvic_initstruct.NVIC_IRQChannelSubPriority 2;nvic_initstruct.NVIC_IRQChannelCmd ENABLE;NVIC_Init(nvic_initstruct);}触发中断,按键标志位赋1 extern _Bool key_down; void EXTI1_IRQHandler(void) {if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) 0){//代表按键按下(按键标志清除–一次时间处理完成)key_down 1;}EXTI_ClearITPendingBit(EXTI_Line1); } 定时器中断扫描判断按键是否按下 当触发中断后,我们把key_down置成1后, 就会被定时器扫描,检测到, 我们就 把按键次数加1, 并且启动 500ms的计时, count 1, 然后if(count 0), 就会启动 count计时, 因为我们定时器是1ms运行一次,所以当count 500的时候进行按键类型检测 按键类型判断 当到达500ms后, 我们就可以通过判断按键次数, 区分单双击, 单击的情况下通过判断500ms时io口的状态从而判断单击还是长按。 单击和长按区分 单击和长按, 按键次数 button_count 都是1, 不同的是,500毫秒之后,单击按键类型, 已经松开, 长按,则是按下状态, 所以我们通过读取检测500ms时间到时, io的状态, 就可以区分长按和单击了。 长按 io口是低电平, 单击,io是高电平, (我们是下降沿触发, 按键一端连io口,一端连 地, io口输出状态是, 推挽输出) button_mode 1代表 单击 , button_mode 3代表 长按 uint8_t key_scan(void) {uint8_t value;value 0; //默认是不是一直低电平//检测是否长按if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) 0)// 判断按键是否仍然在按下{//这时候还是按下状态, 不一定是真正的按键按下, 有可能是抖动造成的,接下来延时消抖//再次判断按键是否按下, 如果按下, 代表真正的按键仍然在按下if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) 0){//那就等抬起了再做事value 1;//这时候才可以判断是 长按下}}return value; }双击区分 通过判断, 按键的次数, 就可以得知双击, 记得按键类型判断完毕后, 要把按键次数置0, 为下次判断做准备。 button_mode 2, 代表按键双击 定时器扫描函数代码 void TIM4_IRQHandler(void) {if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update))//一毫秒运行一次{//当 button_atom的时候,才能进行读取按键信息if(key_down 1){ key_down 0;button_count;count 1; //开始计时}if(count 0){count;if(count 500){count 0;if(button_count 1){button_count 0;if(key_scan() 0) //短按button_mode 1;else if(key_scan() 1) //长按button_mode 3; }else if(button_count 2){button_count 0;button_mode 2; }else{button_count 0;//判断完,到时间照样得button_count 清零,为后面做准备}}} TIM_ClearFlag(TIM4,TIM_FLAG_Update);} } 现象调试 判断按键类型方式 我们通过代码实操 ,已经可以得知我们按下的按键是单击,双击还是长按了,通过判断 button_mode 的数值。 调用相关现象 我们选用PA0, PA1, PA2, 来分别代表 单击,双击和长按的小灯。 我们在检测到 button_mode 的数值改变的时候, 就赋值对应的小灯亮灭,这样我们就可以看到现象了 初始化PA0,PA1,PA2 设置这三个io口分别为推挽输出模式 void Led_Init(void) {/开启时钟/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟//使用各个外设前必须开启时钟否则对外设的操作无效/GPIO初始化/GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //GPIO模式赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; //GPIO引脚赋值为第0号引脚GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //GPIO速度赋值为50MHzGPIO_Init(GPIOA, GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//实现GPIOA的初始化GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //GPIO模式赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; //GPIO引脚赋值为第0号引脚GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //GPIO速度赋值为50MHzGPIO_Init(GPIOA, GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//实现GPIOA的初始化GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //GPIO模式赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin GPIO_Pin_2; //GPIO引脚赋值为第0号引脚GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //GPIO速度赋值为50MHzGPIO_Init(GPIOA, GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//引脚初始化led_go(0,0);led_go(1,0);led_go(2,0); } 单独设置对应的小灯亮灭 void led_go(uint8_t led,_Bool go)比如我们控制 PA0 io口, 我们传入 0, 代表我们要控制位序为0的小灯, 第二个参数 go 1, 代表着让灯两, go 0, 代表着让灯灭。这样我们就可以灵活的控制小灯亮灭了。 void led_go(uint8_t led,_Bool go) {if(led 0){if(go 1){GPIO_SetBits(GPIOA, GPIO_Pin_0); //亮}else{GPIO_ResetBits(GPIOA, GPIO_Pin_0); //灭}}elseif(led 1){if(go 1){GPIO_SetBits(GPIOA, GPIO_Pin_1); //亮}else{GPIO_ResetBits(GPIOA, GPIO_Pin_1); //灭} } elseif(led 2){if(go 1){GPIO_SetBits(GPIOA, GPIO_Pin_2); //亮}else{GPIO_ResetBits(GPIOA, GPIO_Pin_2); //灭} } } 根据 button_mode亮灭小灯 还是那个图, 我们有了底层构建, 我们根据单双击,然后会有不同的butoon_mode 按键模式, 所以我们根据这个数值, 赋值对应的小灯亮灭, 这样我们就可以看到现象了. led控制图(ctrl 加鼠标左键,快速跳转) void chose_led(void) {if(button_mode 0){led_go(0,0);led_go(1,0);led_go(2,0);}else if(button_mode 1){led_go(0,1);led_go(1,0);led_go(2,0);}else if(button_mode 2){led_go(0,0);led_go(1,1);led_go(2,0);}else if(button_mode 3){led_go(0,0);led_go(1,0);led_go(2,1);} } main.c主函数调用 初始化,按键和定时器, 还有调试的小灯, 我们根据按键模式, 控制对应的小灯亮灭, 观察现象 _Bool key_down 0; //按键是否按下 uint16_t count; //定时器计数毫秒数(按键按下时长) uint8_t button_count 0; uint8_t button_mode 0; //按键模式:无-0 , 单击- 1, 双击 - 2, 长按 - 3 int main(void) {Key_Init();TIM4_Init();Led_Init();while(1){chose_led();} } 工程代码构建 我们上面, 代码的逻辑思路, 已经构建完毕, 同时我们也提供构建完成的工程, 我们这里带领大家, 复制黏贴 1.基本工程构建方法 创建stm32f103c8t6基本工程_stm32f103c8启动文件配置-CSDN博客 2.我们工程名字叫做 Key_detection_model点击品字,然后修改工程名字 3.我们用到main函数, 所以有User用户文件夹 我们用到按键检测, 所以用到 Key_model按键模型 我们用到系统的延时函数, 所以用到System系统文件夹 我们用到定时器,所以用到Time定时器文件夹 UserKey_modelSystemTime4.具体文件添加方式, 看最小例程构建,从第九步开始 我们User文件夹下, 添加 main.cled.cled.hKey_model文件夹下添加 key.ckey.hSystem文件夹下添加 delay.cdelay.hsys.hTime文件夹下添加 TIM4.cTIM4.h5.记得包含对应的文件夹路径 6.按键收集模型代码快速复制 各文件对应的代码 跳转复制 构建完成如图 8.编译运行,烧录 烧录方法 9.小灯辨别正负极方法 灯芯放在光下看, 大头是负极,小头是正极, 我们正极插在io口, 负极插在地, io口分别是 PA0, PA1, PA2 10.按键演示视频 按键演示视频_哔哩哔哩_bilibili