//------------------------------------------------------------------------------------------------------------------------------ --------------------------------// 名称:智能查询键盘程序设计与单片机测控系统的人机交互(对 AVR 单片机原理及测控 工程应用的一点补充理解,postscript:附程序与仿真图) // 解决问题: // 1,计算机系统执行速度快,一条指令代码的执行时间平均为两个指令大概 2us 的时间左右(大概估计) ,而我们的按键时间持续大概有 200ms 以上, // 我们的主程序主要是死循环,循环扫描按键动态信息,一般执行一个循环总 代码执行时间平均为几百微妙,相对于,一个按键持续时间来讲, // 如果一旦有按键按下,则此按键时间内,主程序周而复始,一个按键会多次 执行相应的按键处理程序,如果按键处理程序,有相应的累加或诸如此类的 // 的情况的话,那么我们原本的意图是,一次按键执行一次对应的按键执行程 序,然而计算机执行结果会是按键执行程序多次执行,具体次数,得依据 // 主程序代码复杂度来参考,所以这是不允许的,这个问题必须解决才能精准 的按照我们的要求执行。
这里就涉及到等待按键问题:通常当我们把按键按下,等待抬起 后, // 再次按下,再执行相应的程序,通常在软件执行的时候,加一个非常大的延 时函数,再向下执行,这样对实时性能造成破坏,有不可预测性 // 2,工业控制设备中,有这样的一种键盘设计方案要求,即如果长时间按下同一 按键,表示重复执行对应的程序处理需求,要求按键超过一定时间 // 执行值能快速增加,即为连击处理这样就可以用很少的键完成多位数的输 入,且能快速输入 // 3,MCU 即单片机在读取按键的时候,由于按键存在机械抖动,所以,通常用 软件去抖动的方法为毫秒级别,对单片机的实时性造成破坏 //------------------------------------------------------------------------------------------------------------------------------ ----------------------------------//改进人: Doreamon //单位: Jxust //时间: 6.11.2016 //------------------------------------------------------------------------------------------------------------------------------ ---------------------------------- #include #define uchar unsigned char #define uint unsigned intuchar code dsy_code[]={0xc0,0xf9,0xa4,0xb0,0xb0,0x99,0x82,0xf8,0x80,0x90};//数码管段码 uchar key_value; //按键的 键值 uchar read_key(void) //读取键 值函数 { //此 处 static 的使用,利用 static 具有全局变量的赋值特性,和局部变量的私有特性// 即 每次执行调用函数时,对应的 static 变量值不会重新赋值,而是会保留上次操作后的值, 但是它// 又属于局部变量,具有私有特性 static uchar last_key=0xff; //初次调 用认为上一次没有按键按下,则上一次按键为 0xff static uint key_count=0; //每次检测到 有按键按下时,该计数器加 1 #define c_wobble_time 120 //去抖动 时间(待定) #define c_keyover_time 20000 //等待进 入连击时间(待定) ,该常数在设计时比按下的常规时间长,防止非目的的进入连击模式 #define c_keyquick_time 2000 //等待按键 抬起的连击时间,即是按键的增长速率 static uint keyover_time=c_keyover_time; //当进入连击状 态后,将按键增长速率赋值给控制按键增长的变量,将变量由控制//控制 是否进入了连击状态转换为连击增长速率 uchar nc; //定义键值 变量 nc=P1 //读取 按键键值 if(nc==0x0f) { //无按键按 下,则返回 0xff key_count=0; //继续初始化, 等待下一次按键 keyover_time=c_keyover_time; return 0xff;}else //如果有键按 下,判断是否为同一次按键的多次执行 { //经过下 面相应的第一次 last_key 的赋值,判断是否为同一次按键时间内 if(nc==last_key) //如果是同一 次按键时间内,则对其进行消抖动, { //此处消 抖动具有实时性,每次 key_count 加 1 后都会再去判断按键的有效性 if(++key_count==c_wobble_time) return nc; //当 key_count 累加 到 c_wobble_time 的时候,刚好等于设置的相应的恰当的 else //消抖时间,则 确认按键已经按下,马上执行相应的按键执行程序 { //当执行一 次按键执行程序后,来到此处判断,按键是否为连击 if(key_count>keyover_time) //如果按键按下 的时间大于设定的连击判断时间则进入连击状态{ //则进行连 击初始化,将 key_count 初始化为 0; key_count=0; //将时间判断变 量改为连击速率判断变量值 keyover_time=c_keyquick_time; //此处应深刻理 解 static 作用 } return 0xff;; } } else {last_key=nc; //当第一次执行时, 在检测到键值变化符合条件时,将此次的按键值赋值给 key_count=0; //last_key 做给下一 次判断做依据 keyover_time=c_keyover_time; //仍然将判断是否进 入长按时间标准赋值给判断变量 return 0xff; //此时第一次判断不 执行按键执行程序,而是单纯的给 last_key 提供判断依据//并且初始化当 前参数 } } }int main()//初始化数码管全亮, 以此检测数码管是否有问题,应和 8 注意区分, { // 读者可自行更 改,以便区分uint a=0,b=0,c=0;//初始化三个变量 while(1) //死循环 {key_value=read_key(); //取键值 if(key_value==0x07) //判断键值 { //将执行次数累加, 如超过 10 ,读者可自行设计多块复用数码管++a;P0=~dsy_code[a%10]; //将执行次数显 示出来 }if(key_value==0x0b) //判断键值 { //将执行次数累 加,如超过 10 ,读者可自行设计多块复用数码管++b; //将执行次数显示出来P2=~dsy_code[b%10]; }if(key_value==0x0d) //判断键值 { //将执行次数累加, 如超过 10 ,读者可自行设计多块复用数码管++c;//将执行次数显 示出来P3=~dsy_code[c%10]; } } }。