如何用ps制作网站,网站代理建设,临沂网站建,wordpress 导航下拉菜单显示5条目录
1#xff0c;独立按键
2#xff0c;矩阵按键 #xff08;注意#xff1a;文章中的代码仅供参考学习#xff0c;实际使用时要根据需要修改#xff09;
1#xff0c;独立按键
按键管脚两端距离长的表示默认是导通状态#xff0c;距离短的默认是断开状态#xf…目录
1独立按键
2矩阵按键 注意文章中的代码仅供参考学习实际使用时要根据需要修改
1独立按键
按键管脚两端距离长的表示默认是导通状态距离短的默认是断开状态 如果按键按下初始导通状态变为断开初始断开状态变为导通。
由于机械点的弹性作用按键开关在闭合时不会马上稳定的接通在断开时也不会一下子断开因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的一般为5ms 到10ms。按键稳定闭合时间的长短则由操作人员的按键动作决定的一般为零点几秒至数秒。按键抖动会引起按键被误读多次。为了确保CPU 对按键的一次闭合仅作一次处理必须进行消抖。
按键消抖有两种方式一种是硬件消抖另一种是软件消抖。为了使电路更加简单通常采用软件消抖。我们开发板也是采用软件消抖一般来说一个简单的按键消抖就是先读取按键的状态如果得到按键按下之后延时10ms再次读取按键的状态如果按键还是按下状态那么说明按键已经按下。
单片机常用的软件去抖动方法
1先设置IO 口为高电平由于开发板IO 都有上拉电阻所以默认IO 为高电平。
2读取IO 口电平确认是否有按键按下。
3如有IO 电平为低电平后延时几个毫秒。
4再读取该IO 电平如果仍然为低电平说明按键按下。
5执行按键控制程序。 独立按键电路构成是由各个按键的一个管脚连接在一起接地按键其他引脚分别接到单片机IO 口。
我们知道单片机的IO 口既可作为输出也可作为输入使用当检测按键时用的是它的输入功能独立按键的一端接地 另一端与单片机的I/O 口相连开始时先给该IO 口赋一高电平然后让单片机不断地检测该I/O 口是否变为低电平当按键闭合时即相当于该I/O 口通过按键与地相连变成低电平程序一旦检测到I/O 口变为低电平则说明按键被按下然后执行相应的指令。 CPU如何处理按键 (1)轮询式。所谓轮询式就是CPU不断的隔很小时间去查看有没有按键被按下如果按下就处理按键如果没按下就过一会再来查看。按键什么时候被按下CPU是无法预知的 (2)中断式
轮询式处理按键代码
#include reg51.h// 当前要处理的是K1对应P1.0IO口操控的LED是LED1对应P0.0/*********************变量定义************************************/
sbit key1 P1^0;
sbit key2 P1^1;
sbit key8 P1^7;// 独立数码管的段码表
unsigned char val[16] {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};/*********************************** 函数声明 ***********************/
void AddDisplay(void);
void delay(void);
void delay10ms(void);/******************************全局变量定义*************************/
unsigned char dnum 0;void main(void)
{unsigned char flag 0; // 默认状态等于0while (1){if (key1 0){// 发现1次低电平有可能是按键按下也有可能是抖动软件消抖delay10ms();if (key1 0){// 10ms后还是低电平说明真的是按键按下了不是抖动// 这里说明发现了一个按下事件//flag 1;if (flag 0){AddDisplay();flag 1;}}}else{// 电平 1delay10ms();if (key1 1){// 说明弹起了if (flag 1){//AddDisplay();flag 0;}}}delay(); }
}// 该函数将num数字送到独立数码管去显示
void AddDisplay(void)
{dnum dnum 1;if (dnum 15){dnum 0;}P0 val[dnum];
}// 延时函数
void delay(void)
{unsigned char i, j;for (i0; i100; i)for (j0; j200; j);
}void delay10ms(void) //误差 0us
{unsigned char a,b,c;for(c5;c0;c--)for(b4;b0;b--)for(a248;a0;a--);
}
中断式处理按键源代码
#include reg51.h// 当前要处理的是K1对应P1.0IO口操控的LED是LED1对应P0.0/*********************变量定义************************************/
sbit key1 P1^0;
sbit key2 P1^1;sbit key4 P3^4;sbit led1 P2^7;
sbit led2 P2^6;// 独立数码管的段码表
unsigned char val[16] {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};/*********************************** 函数声明 ***********************/
void delay10ms(void);/*************中断处理程序*************/void Eint0Isr() interrupt 0
{// 任务2按键监测及led控制// 进入中断后LED状态转换。原来亮则灭原来灭就亮if (led1 1)led1 0;elseled1 1;
}void main(void)
{unsigned char i 0;// 中断初始化IT0 1;EX0 1;EA 1;// 主线任务while (1){// 任务1数码管显示for (i0; i16; i){P0 val[i];delay10ms();}}
}// 延时函数
void delay10ms(void) //误差 0us
{unsigned char a,b,c;for(c5;c0;c--)for(b4;b0;b--)for(a248;a0;a--);
}
上述代码中主线任务是使用数码显示0-F利用中断功能去检测按键是否按下当检测到按键按下时中断主线任务去执行中断程序点亮或熄灭LED灯。
中断的思路 (1)“主线任务”为常规任务默认运行 (2)中断发生后CPU暂停主线任务转去处理中断任务完成后再回来接着执行主线任务
中断的意义 (1)中断处理能力让CPU可以全力处理主线任务而不用担心会错过中断任务举例看电影和收快递 (2)中断式比轮询式更适合处理异步事件效率更高 (3)中断中处理的事件的特点是无法预料、处理时间短、响应要求急。
中断任务的处理时间要远远小于主线程序的处理时间才能通过中断来处理。
IT0这一位用来设置中断的触发模式下降沿触发Falling或者低电平触发low level EX0这一位是INT0的开关。如果EX0等于0则外部中断在单片机内部被关闭此时CPU无法收到INT0的中断信息所以不会处理INT0如果需要使用INT0就一定要设置为1。 EA是全局的中断开关。EA如果关掉则整个CPU不能响应中断所有中断都被关了。光EA打开也不一定能响应中断还得具体的中断开关打开才行。
总结 (1)中断能力是CPU本身设计时支持的并不是编程制造出来的 (2)程序员只要负责2件事即可主程序中初始化中断、定义中断处理程序 (3)当中断条件发生时硬件会自动检测到并且通知CPUCPU会自动去执行中断处理程序这一切都是CPU设计时定下的不需要编程干预。
2矩阵按键 电路中的ARRAY_H1表示矩阵键盘第1 行ARRAY_L1 表示矩阵键盘第1 列。
需要注意的是按键两端如果分别接单片机的两个端口一个端口置高电平一个端口置低电平按下按键时会把高电平的端口拉低端口置低可以认为是在单片机内部将这个端口接地。
矩阵按键实验程序按下矩阵按键显示对应的0-F
第一种方法
/********************************************************************
******************
实验名称矩阵按键实验
接线说明
实验现象下载程序后按下“矩阵按键”模块中S1-S16 键对应静态数码管显示0-F
注意事项
*********************************************************************
******************/
#include reg52.h
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
//共阴极数码管显示0~F 的段码数据
u8 gsmg_code[17]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
/********************************************************************
***********
* 函数名: delay_10us
* 函数功能: 延时函数ten_us1 时大约延时10us
* 输入: ten_us
* 输出: 无
*********************************************************************
**********/
void delay_10us(u16 ten_us)
{while(ten_us--);
}
/********************************************************************
***********
* 函数名: key_matrix_ranks_scan
* 函数功能: 使用行列式扫描方法检测矩阵按键是否按下按下则返回对应键值
* 输入: 无
* 输出: key_value1-16对应S1-S16 键0按键未按下
*********************************************************************
**********/
u8 key_matrix_ranks_scan(void)
{u8 key_value0;KEY_MATRIX_PORT0xf7;//给第一列赋值0其余全为1if(KEY_MATRIX_PORT!0xf7)//判断第一列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值{case 0x77: key_value1;break;case 0xb7: key_value5;break;case 0xd7: key_value9;break;case 0xe7: key_value13;break;}}while(KEY_MATRIX_PORT!0xf7);//等待按键松开KEY_MATRIX_PORT0xfb;//给第二列赋值0其余全为1if(KEY_MATRIX_PORT!0xfb)//判断第二列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值{case 0x7b: key_value2;break;case 0xbb: key_value6;break;case 0xdb: key_value10;break;case 0xeb: key_value14;break;}}while(KEY_MATRIX_PORT!0xfb);//等待按键松开KEY_MATRIX_PORT0xfd;//给第三列赋值0其余全为1if(KEY_MATRIX_PORT!0xfd)//判断第三列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值{case 0x7d: key_value3;break;case 0xbd: key_value7;break;case 0xdd: key_value11;break;case 0xed: key_value15;break;}}while(KEY_MATRIX_PORT!0xfd);//等待按键松开KEY_MATRIX_PORT0xfe;//给第四列赋值0其余全为1if(KEY_MATRIX_PORT!0xfe)//判断第四列按键是否按下{delay_10us(1000);//消抖switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值{case 0x7e: key_value4;break;case 0xbe: key_value8;break;case 0xde: key_value12;break;case 0xee: key_value16;break;}}while(KEY_MATRIX_PORT!0xfe);//等待按键松开return key_value;
}void main()
{u8 key0;while(1){keykey_matrix_ranks_scan();if(key!0)SMG_A_DP_PORT~gsmg_code[key-1];//得到的按键值减1 换算成数组下标对应0-F 段码}
}
第二种方法
#include reg51.htypedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;#define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口//共阳极数码管显示0~F 的段码数据
u8 gsmg_code[16]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void delay_10us(u16 ten_us)
{while(ten_us--);
}u8 key_matrix_flip_scan(void)
{static u8 key_value0;KEY_MATRIX_PORT0xf0;//给所有行赋值0列全为1if(KEY_MATRIX_PORT ! 0xf0){delay_10us(1000);if(KEY_MATRIX_PORT ! 0xf0){switch(KEY_MATRIX_PORT){case 0xe0: key_value 1;break;case 0xd0: key_value 2;break;case 0xb0: key_value 3;break;case 0x70: key_value 4;break;}}KEY_MATRIX_PORT0x0f;//给所有行赋值1列全为0if(KEY_MATRIX_PORT ! 0x0f){delay_10us(1000);if(KEY_MATRIX_PORT ! 0x0f){switch(KEY_MATRIX_PORT){case 0x0e: key_value key_value;break; //代表第一行的按键case 0x0d: key_value key_value4;break; //代表第二行的按键case 0x0b: key_value key_value8;break; //代表第三行的按键case 0x07: key_value key_value12;break; //代表第四行的按键 }}while(KEY_MATRIX_PORT!0x0f);//等待按键松开}else{key_value 0; }}return key_value;}void main()
{u8 key 0;while(1){key key_matrix_flip_scan();if (key ! 0){SMG_A_DP_PORT gsmg_code[key-1];}}}