/****************** ******* 函数名称: KEY_IN() ******* 函数功能: 电梯按键检测函数 ******* 返回值 : INT8U 0 1 2 ******************/ INT8U KEY_IN(void) { if(Key0 == 0) { Delay_nms(2); if(Key0 == 0){ LED0 = 1; send_string_uart("按下0层按键\r\n"); return 0; } } else if(Key1 == 0) { Delay_nms(2); if(Key1 == 0){ LED1 = 1; send_string_uart("按下1层按键\r\n"); return 1; } } else if(Key2 == 0) { Delay_nms(2); if(Key2 == 0){ LED2 = 1; send_string_uart("按下2层按键\r\n"); return 2; } } return 3; }
void LCD_init(void) { LCD_write_com(0x30); //选择基本指令集 LCD_write_com(0x0c); //开显示,无游标,不反白 LCD_write_com(0x01); //清除显示屏幕,把DDRAM位址计数器调整为00H Delay_nms(5); //清屏操作时间较长1.6ms 因此加此延时 LCD_write_com(0x02); //清DDRAM位址归位,此处貌似与清屏重复 LCD_write_com(0x06); //设定光标右移,整体显示不移动 }
void LCD_write_dat(uchar dat) { LCD_CS=1; LCD_sendbyte(0xfa); //送入5个连续的“1“,启动一个周期,11111,RW(0),RS(1),0 LCD_sendbyte(0xf0&dat); //取高四位,数据分两次传送, //每个字节的内容被送入两个字节 //高四位放在第一个字节的高四位 LCD_sendbyte(0xf0&(dat<<4)); //低四位放在第二个字节 LCD_CS=0; Delay_nms(10); }
void LCD_write_com(uchar com) { LCD_CS=1; LCD_sendbyte(0xf8); //送入5个连续的“1“,启动一个周期,11111,RW(0),RS(0),0 LCD_sendbyte(0xf0&com); //取高四位,数据分两次传送, //每个字节的内容被送入两个字节 //高四位放在第一个字节的高四位 LCD_sendbyte(0xf0&(com<<4)); //低四位放在第二个字节的高四位 LCD_CS=0; Delay_nms(10); //串行不支持读操作,不可检测忙操作,这里用延时替代 }
/****************** ******* 函数名称: Key_INIT() ******* 函数功能: 电梯上升检测函数 ******* 返回值 : NULL ******************/ void Key_INIT() { if(Key0_UP == 0) { Delay_nms(2); if(Key0_UP == 0){ LED0_UP = 1; UP_Flag = 0; send_string_uart("按下0层上键\r\n"); } } if(Key1_UP == 0) { Delay_nms(2); if(Key1_UP == 0){ LED1_UP = 1; UP_Flag = 1; send_string_uart("按下1层上键\r\n"); } } if(Key1_DOWN == 0) { Delay_nms(2); if(Key1_DOWN == 0){ LED1_DOWN = 1; Down_Flag = 1; send_string_uart("按下1层下键\r\n"); } } if(Key2_DOWN == 0) { Delay_nms(2); if(Key2_DOWN == 0){ LED2_DOWN = 1; Down_Flag = 2; send_string_uart("按下2层下键\r\n"); } } }
BYTE read_key(u8* pKeyValue) { static u8 s_u8keyState=0; //未按,普通短按,长按,连发 static u16 s_u16keyTimeCounts=0; //未在计时状态的计数器 static u8 s_u8LastKey = key_up ; //历史数据 u8 keyTemp=0; //键对应io的电平 u8 key_return=0; //函数返回值 keyTemp=Key_Scan(); //提取所有key对应的io口 Delay_nms(1); switch(s_u8keyState) //这里检测到的是先前的状态,即无动作 { case state_keyUp: //如果先前是初始态 { if(keyTemp!=key_up) //如果键被按下 { s_u8keyState=state_keyDown; //更新键的状态,普通被按下 } } break; case state_keyDown: //如果先前是被按着的 { if(key_up!=keyTemp) //如果现在还是被按着 { s_u8keyState=state_keyTime; //转换到计时态 s_u16keyTimeCounts=0; s_u8LastKey = keyTemp; //保存键值 } else { s_u8keyState=state_keyUp; //键没被按着,回到初始态,说明是干扰 } } break; case state_keyTime: //如果先前已经转换到计时态 { //如果真是手动按键,必然进入到本代码块,并且会多次进入 if(key_up==keyTemp) //如果未按键 { s_u8keyState=state_keyUp; key_return=return_keyPressed; //返回2,一次完整的普通按键 //程序进入这个语句块,说明已经有2次以上10MS的中断,等于已经消抖 //那么此时检测到按键被释放,说明是一次普通的短按 } else //在计时状态,检测到键还被按着 { if(++s_u16keyTimeCounts>key_longTimes) //时间达到2秒 { s_u8keyState=state_keyLong; //进入产按键状态 s_u16keyTimeCounts=0; //技术器清零,便于进入连发重新计数 key_return=return_keyLong; //返回state_keyLong } } } break; case state_keyLong: //在长安状态检测连发 ,每0.2秒发一次 { if(key_up==keyTemp) { s_u8keyState=state_keyUp; } else //按键时间超过2秒时 { if(++s_u16keyTimeCounts>key_autoTimes)//10*key_autoTimes { s_u16keyTimeCounts=0; key_return=return_keyAuto; //每0.2秒返回值的第二位置位 }//连发的时候伴随着长按 } key_return |= return_keyLong; //0x02????,0x04|0x02???? } break; default: break; } *pKeyValue = s_u8LastKey ; //返回键值 return key_return; }