前言:
当前看官们对“中断及定时器实验”大致比较关切,小伙伴们都需要分析一些“中断及定时器实验”的相关文章。那么小编在网摘上搜集了一些关于“中断及定时器实验””的相关文章,希望各位老铁们能喜欢,同学们快快来学习一下吧!对于stm32新手,很多学习完一些基础的例程,不知所措,有种似懂非懂的感觉,缺少了对程序的运用和知识的梳理,可以在这方面做一些小实践,以达到灵活运用
分享一个mini板按键KEY0单击、双击、长按和串口实现灯的控制状态,按键KEY1中断,控制灯亮5秒后熄灭
本实验实现的功能mini板按键KEY0单击、双击、长按和串口实现灯的控制状态,
按键KEY1中断,控制灯亮5秒后熄灭
且通过按键KEY0单击亮红灯、双击亮绿灯、长按两灯都熄灭来实现灯的
1)首先说到按键KEY0单击、双击、长按,这个需要了解按键所处的状态
如单击完后,超过多长时间属于长按,以及双击间隔的时间多长
还有TIM3_Int_Init(99,7199);//10ms,按键扫描计时10ms
这个很关键,超过这个10ms会导致按键单击、双击、长按的失灵
下面这段程序可以通过key = key_read()调用;unsigned char key_driver(void){ static unsigned char key_state = key_state_0, key_time = 0; unsigned char key_press, key_return = N_key; key_press = KEY0; // 读按键IO电平 switch (key_state) { case key_state_0: // 按键初始态 if (!key_press) key_state = key_state_1; // 键被按下,状态转换到按键消抖和确认状态 break; case key_state_1: // 按键消抖和确认状态 if (!key_press) //按键仍然处于按下 { key_time = 0; key_state = key_state_2; //,消抖完成,状态转换到按下键时间的计时 } else key_state = key_state_0; //按键已抬起,转换到按键初始态。此处完成和实现软件消抖,此时 break; //按键的按下和释放都在此消抖 case key_state_2: if(key_press) { key_return = S_key; // 此时按键的释放,说明是产生一次短操作,回送S_key key_state = key_state_0; // 转换到按键的初始态 } else if (++key_time >= 100) // 继续按下,计时10ms { key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长按操作 key_state = key_state_3; // 转换到等待按键释放状态 } break; case key_state_3: // 等待按键释放状态,此状态只返回无按键事件 if (key_press) key_state = key_state_0; //按键已释放,已转换到按键初始态 break; } return key_return;} /*============= 时间10ms===============*/unsigned char key_read(void){ static unsigned char key_m = key_state_0, key_time_1 = 0; unsigned char key_return = N_key,key_temp; key_temp = key_driver(); switch(key_m) { case key_state_0: if (key_temp == S_key ) { key_time_1 = 0; // 第一次单击,不返回,到下个转态判断后面是否出现双击 key_m = key_state_1; } else key_return = key_temp; // 对于无键、长按,返回原事件 break; case key_state_1: if (key_temp == S_key) // 又一次单击(间隔时间<500ms) { key_return = D_key; // 返回双击键事件,回初始状态 key_m = key_state_0; } else { // 这里500ms内肯定读到的都是无键事件, if(++key_time_1 >= 50) //因为长按>1000ms,低层返回都是无按键 { key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键 key_m = key_state_0; // 返回初始状态 } } break; } return key_return; }
2)KEY0控制单击、双击、长按和串口控制灯,每10ms执行一次
这里需要用一个if ( time_10_ms) 每10ms执行一次来判断检测按键用的
既可以通过按键来控制也可以通过串口来控制
if ( time_10_ms) //每10ms执行一次 { time_10_ms = 0 ; key = key_read(); if (key == S_key||USART_RX_BUF[0]=='0') { LED0=0; printf("LED0亮\n"); delay_ms(1000); USART_RX_BUF[0]=9; } else if(key == D_key||USART_RX_BUF[0]=='1') { LED1=0; printf("LED1亮\n"); delay_ms(1000); USART_RX_BUF[0]=9; } else if(key == L_key||USART_RX_BUF[0]=='2') { LED0=1; LED1=1; printf("LED0和LED1都灭\n"); delay_ms(1000); USART_RX_BUF[0]=9; } }
3)KEY1中断按键,红灯5秒后自动熄灭
这个就需要通过定时器的配合来实现倒计时
if(key1Pressed) { LED0 = 0 ; } if(count > 500) { LED0 = 1 ; count = 0 ; key1Pressed = 0 ; }extern int key1Pressed ;extern int count ;extern int time_10_ms;void TIM3_IRQHandler(void) //TIM3中断{ if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 { time_10_ms = 1; if (LED0 == 0 && key1Pressed == 1 ) count++ ; } TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源 }
4)volatile int time_10_ms = 0 ; //volatile提醒编译器它后面定义的变量随时有可能改变
volatile int count = 0 ; //每次存储或读取变量,直接从变量地址中读取数据
volatile int key1Pressed = 0 ;
希望对初学者有所帮助,也向大神请教一下不足之处,喜欢就赞一个,谢谢!
标签: #中断及定时器实验