先前根据以为前辈的程序理解了一段时间,之后自己写了一份控制led灯的简单按键程序
单片机源程序如下:
#include #include #define key_state_0 0 #define key_state_1 1 #define key_state_2 2 #define key_state_3 3 #define key_no 0 #define key_click 1 #define key_double 2 #define key_long 3 sbit KEY = P3^3; sbit LED_E1P = P3^1; sbit LED_G1 = P3^2; sbit LED2 = P5^5; //W2OUT sbit LED3 = P5^4; unsigned char flag; unsigned char cnt = 0; static unsigned char key_driver(void) { static unsigned char key_state_buffer1 = key_state_0; static unsigned char key_timer_cnt1 = 0; unsigned char key_return = key_no; unsigned char key; key = KEY; //read the I/O states switch(key_state_buffer1) { case key_state_0: if(key == 0) key_state_buffer1 = key_state_1; //按键被按下,状态转换到按键消抖和确认状态// break; case key_state_1: if(key == 0) { key_timer_cnt1 = 0; key_state_buffer1 = key_state_2; //按键仍然处于按下状态 //消抖完成,key_timer开始准备计时 //状态切换到按下时间计时状态 } else key_state_buffer1 = key_state_0; //按键已经抬起,回到按键初始状态 break; //完成软件消抖 case key_state_2: if(key == 1) { key_return = key_click; //按键抬起,产生一次click操作 key_state_buffer1 = key_state_0; //转换到按键初始状态 } else if(++key_timer_cnt1 >= 100) //按键继续按下,计时超过1000ms { key_return = key_long; //送回长按事件 key_state_buffer1 = key_state_3; //转换到等待按键释放状态 } break; case key_state_3: //等待按键释放 if(key == 1) //按键释放 key_state_buffer1 = key_state_0; //切回按键初始状态 break; } return key_return; } unsigned char key_read(void) { static unsigned char key_state_buffer2 = key_state_0; static unsigned char key_timer_cnt2 = 0; unsigned char key_return = key_no; unsigned char key; key = key_driver(); switch(key_state_buffer2) { case key_state_0: if(key == key_click) { key_timer_cnt2 = 0; //第一次单击,不返回,到下个状态判断是否会出现双击 key_state_buffer2 = key_state_1; } else key_return = key; //对于无键、长按,返回原事件 break; case key_state_1: if(key == key_click) //又一次单击,时间间隔小于500ms { key_return = key_double; //返回双击事件,回到初始状态 key_state_buffer2 = key_state_0; } else if(++key_timer_cnt2 >= 50) { //这里在下一次的按键来临之前,并且时间是小于500ms的时候,就会一直执行的是这个key_timer_cnt2++.直到下一次的按键到来,再判断看是双击还是单击。 //这里500ms内肯定读到的都是无键事件,因为长按大于1000ms //在1s前底层返回的都是无键 key_return = key_click; //500ms内没有再次出现单击事件,返回单击事件 key_state_buffer2 = key_state_0; //返回初始状态 } break; } return key_return; } void Timer0Init(void) //1毫秒@11.0592MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0xCD; //设置定时初值 TH0 = 0xD4; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; } void IO_init() { P3M0 = 0x01; P3M1 = 0x01; P5M0 = 0x00; P5M1 = 0x00; } void main(void) { unsigned char key = 1; Timer0Init(); IO_init(); LED_E1P = 1; LED_G1 = 1; LED2 = 1; LED3 = 0;
上一篇:51单片机是如何产生串口中断的
下一篇:HX1838红外无线遥控模块51单片机程序
推荐阅读最新更新时间:2024-11-11 22:14
- 热门资源推荐
- 热门放大器推荐
设计资源 培训 开发板 精华推荐
- 具有最大功率点跟踪功能的 LTC4162IUFD-FFSM 太阳能供电 3 节 3.2A 充电器的典型应用
- 使用 Semtech 的 SC1633 的参考设计
- x123
- 使用 FAN9673 85 至 264 VAC 输入、5kW CCM PFC 控制器的 3 通道交错 CCM PFC
- 使用 Analog Devices 的 LTC1650ACN 的参考设计
- 适用于STM32L4P5ZGT6U MCU的STM32 Nucleo-144开发板,支持Arduino,ST Zio和morpho连接
- 使用 Analog Devices 的 REF194 的参考设计
- LT6654AHLS8-2.5、16 位 ADC 电压基准的典型应用
- DER-957 - 使用基于 PowiGaN 的 InnoSwitch4-CZ、ClampZero 和 HiperPFS-5 的 130 W USB PD 3.1 扩展功率范围充电器
- LT3091ER 重合跟踪电源的典型应用