六、独立按键和矩阵键盘

六、独立按键和矩阵键盘 文章目录一、独立按键1、按键KEY1控制小灯D11.1效果图1.2代码块2、按键KEY1、KEY2、KEY3、KEY4控制D1、D3、D5、D72.1效果图2.2代码块思考与回答二、矩阵键盘1、第一行矩阵键盘点亮4个LED小灯1.1效果图1.2代码块2、4x4矩阵键盘检测8个LED小灯2.1效果图2.2代码块3、4x4矩阵键盘显示0-9 A-F3.1效果图3.2代码块一、独立按键1、按键KEY1控制小灯D11.1效果图1.2代码块#includeREGX51.Hsbit KEY1P3^4;// 原理图按键1接P3.4不是P2^4sbit LED1P0^0;// LED连接P0.0低电平点亮// 延时函数voiddelay_ms(unsignedintms){unsignedinti,j;for(i0;ims;i)for(j0;j123;j);}voidmain(){P00xFF;// 初始所有LED熄灭因低电平点亮while(1){if(KEY10)// 按键按下接地低电平{delay_ms(10);// 消抖延时10msif(KEY10)// 再次确认按下{while(KEY10);// 等待按键松开防止连发LED1~LED1;// 翻转小灯亮灭状态}}}}2、按键KEY1、KEY2、KEY3、KEY4控制D1、D3、D5、D7KEY1控制D1小灯的开关KEY2控制D3小灯的开关KEY3控制D5小灯的开关KEY4控制D7小灯的开关2.1效果图2.2代码块#includeREGX51.H// 按键定义sbit KEY1P3^4;// 按键1sbit KEY2P3^5;// 按键2sbit KEY3P3^6;// 按键3sbit KEY4P3^7;// 按键4// LED定义低电平点亮sbit LED1P0^0;// D1小灯sbit LED2P0^2;// D3小灯P0.2对应D3sbit LED3P0^4;// D5小灯P0.4对应D5sbit LED4P0^6;// D7小灯P0.6对应D7// 延时函数11.0592MHz晶振约1msvoiddelay_ms(unsignedintms){unsignedinti,j;for(i0;ims;i)for(j0;j123;j);}// 按键扫描函数带消抖和等待释放voidkey_scan(void){// 按键1控制D1if(KEY10){delay_ms(10);if(KEY10){while(!KEY1);// 等待按键释放LED1~LED1;// 翻转状态}}// 按键2控制D3if(KEY20){delay_ms(10);if(KEY20){while(!KEY2);LED2~LED2;}}// 按键3控制D5if(KEY30){delay_ms(10);if(KEY30){while(!KEY3);LED3~LED3;}}// 按键4控制D7if(KEY40){delay_ms(10);if(KEY40){while(!KEY4);LED4~LED4;}}}voidmain(){// 初始化所有LED熄灭低电平点亮所以先给高电平LED11;LED21;LED31;LED41;while(1){key_scan();// 持续扫描按键}}思考与回答问题程序中(P0 0xFF);的作用是什么为什么if(KEY1 0)后要加delay_ms(20)while(KEY1 0);有什么作用如果将LED1 ~LED1;替换为LED1 0;LED状态会如何变化程序中哪个部分实现了“单次按键触发”请简要说明原理。回答程序中(P0 0xFF);的作用是将P0口的8个引脚全部设置为高电平1可以确保所有LED处于熄灭状态避免上电瞬间灯乱亮。if(KEY1 0)后要加delay_ms(20)是为了按键消抖防止一次按下被误判为多次触发。while(KEY1 0);的作用是等待按键释放也叫“松手检测”。如果将LED1 ~LED1;替换为LED1 0;按键按一次LED会点亮然后一直保持常亮无法再关闭。LED1 0 是绝对赋值无论之前状态是什么都强制设为0点亮。实现“单次按键触发”的核心是 “等待按键释放” 机制程序如下if(KEY10)// 检测按键按下{delay_ms(10);// 消抖延时if(KEY10)// 确认真正按下{while(!KEY1);// 等待按键释放 ← 关键LED1~LED1;// 释放后才执行动作}}二、矩阵键盘1、第一行矩阵键盘点亮4个LED小灯点击开关S0D1灯亮点击开关S1D2灯亮点击开关S2D3灯亮点击开关S3D4灯亮1.1效果图1.2代码块#includereg52.h// 引入51单片机寄存器定义头文件#defineucharunsignedchar// 宏定义uchar unsigned char8位无符号// 将P0口的第0~7位分别定义为8个LED灯低电平点亮sbit led1P0^0;sbit led2P0^1;sbit led3P0^2;sbit led4P0^3;// 延时函数x控制延时时间voiddelay(uchar x){uchar a,b;for(ax;a0;a--)for(b200;b0;b--);}// 主函数入口voidmain(){// 初始化所有LED熄灭高电平led11;led21;led31;led41;while(1)// 无限循环运行{// **********扫描第一行按键*********************P20xfe;// 选中第一行1111 1110P2.00if(P2!0xfe)// 判断是否有按键按下{delay(50);// 消抖处理if(P2!0xfe)// 再次确认按键状态{switch(P2)// 根据P2值判断按键{case0xee:led10;break;// 1110 1110 → S0按下 → D1亮case0xde:led20;break;// 1101 1110 → S1按下 → D2亮case0xbe:led30;break;// 1011 1110 → S2按下 → D3亮case0x7e:led40;break;// 0111 1110 → S3按下 → D4亮}}}}}2、4x4矩阵键盘检测8个LED小灯2.1效果图2.2代码块#includereg52.h// 引入51单片机寄存器定义头文件#defineucharunsignedchar// 宏定义uchar unsigned char8位无符号// 将P0口的第0~7位分别定义为8个LED灯低电平点亮sbit D1P0^0;// S0控制亮S8控制灭sbit D2P0^1;// S1控制亮S9控制灭sbit D3P0^2;// S2控制亮S10控制灭sbit D4P0^3;// S3控制亮S11控制灭sbit D5P0^4;// S4控制亮S12控制灭sbit D6P0^5;// S5控制亮S13控制灭sbit D7P0^6;// S6控制亮S14控制灭sbit D8P0^7;// S7控制亮S15控制灭// 延时函数x控制延时时间voiddelay(uchar x){uchar a,b;for(ax;a0;a--)for(b200;b0;b--);}// 关闭所有LEDvoidAllLedOff(){D11;D21;D31;D41;D51;D61;D71;D81;}// 主函数入口voidmain(){// 初始化所有LED熄灭AllLedOff();while(1)// 无限循环运行{// **********扫描第一行按键S0, S1, S2, S3点亮LED*********************P20xfe;// 选中第一行1111 1110P2.00if(P2!0xfe)// 判断是否有按键按下{delay(50);// 消抖处理if(P2!0xfe)// 再次确认按键状态{switch(P2)// 根据P2值判断按键{case0xEE:D10;break;// S0按下 → D1亮case0xDE:D20;break;// S1按下 → D2亮case0xBE:D30;break;// S2按下 → D3亮case0x7E:D40;break;// S3按下 → D4亮}while(P2!0xfe);// 等待按键释放}}// **********扫描第二行按键S4, S5, S6, S7点亮LED*********************P20xfd;// 选中第二行1111 1101P2.10if(P2!0xfd)// 判断是否有按键按下{delay(50);// 消抖处理if(P2!0xfd)// 再次确认按键状态{switch(P2)// 根据P2值判断按键{case0xED:D50;break;// S4按下 → D5亮case0xDD:D60;break;// S5按下 → D6亮case0xBD:D70;break;// S6按下 → D7亮case0x7D:D80;break;// S7按下 → D8亮}while(P2!0xfd);// 等待按键释放}}// **********扫描第三行按键S8, S9, S10, S11熄灭LED*********************P20xfb;// 选中第三行1111 1011P2.20if(P2!0xfb)// 判断是否有按键按下{delay(50);// 消抖处理if(P2!0xfb)// 再次确认按键状态{switch(P2)// 根据P2值判断按键{case0xEB:D11;break;// S8按下 → D1灭case0xDB:D21;break;// S9按下 → D2灭case0xBB:D31;break;// S10按下 → D3灭case0x7B:D41;break;// S11按下 → D4灭}while(P2!0xfb);// 等待按键释放}}// **********扫描第四行按键S12, S13, S14, S15熄灭LED*********************P20xf7;// 选中第四行1111 0111P2.30if(P2!0xf7)// 判断是否有按键按下{delay(50);// 消抖处理if(P2!0xf7)// 再次确认按键状态{switch(P2)// 根据P2值判断按键{case0xE7:D51;break;// S12按下 → D5灭case0xD7:D61;break;// S13按下 → D6灭case0xB7:D71;break;// S14按下 → D7灭case0x77:D81;break;// S15按下 → D8灭}while(P2!0xf7);// 等待按键释放}}}}3、4x4矩阵键盘显示0-9 A-F要求第一排按键显示0 1 2 3第二排按键显示4 5 6 7第三排按键显示8 9 A b第四排按键显示C d E F3.1效果图3.2代码块#includereg52.h// 52单片机头文件#defineucharunsignedchar#defineuintunsignedintsbit dulaP1^6;// 段选锁存控制数码管显示内容sbit welaP3^4;// 位选锁存控制哪一位亮uchar num0;// 当前显示的数值uchar temp;// 保存按键扫描值// 段码表共阴极数码管uchar code table[]{0x3F,// 00x06,// 10x5B,// 20x4F,// 30x66,// 40x6D,// 50x7D,// 60x07,// 70x7F,// 80x6F,// 90x77,// A0x7C,// b0x39,// C0x5E,// d0x79,// E0x71// F};// 延时函数用于消抖voiddelay(uchar x){uchar a,b;for(ax;a0;a--)for(b200;b0;b--);}// 数码管显示函数voiddisplay(uchar x){P0table[x];// 输出段码dula1;// 锁存段选dula0;P00xc0;// 1100 0000 - 选中第1位数码管wela1;// 锁存位选wela0;}// 4x4键盘扫描函数ucharkeyscan(){uchar key_value;// 扫描第1行 P20xfe;// 1111 1110if(P2!0xfe){delay(50);if(P2!0xfe){tempP2;switch(temp){case0xee:key_value0;break;// 第1行第1列 - 0case0xde:key_value1;break;// 第1行第2列 - 1case0xbe:key_value2;break;// 第1行第3列 - 2case0x7e:key_value3;break;// 第1行第4列 - 3}while(P2!0xfe);// 等待松手returnkey_value;}}// 扫描第2行 P20xfd;// 1111 1101if(P2!0xfd){delay(50);if(P2!0xfd){tempP2;switch(temp){case0xed:key_value4;break;// 第2行第1列 - 4case0xdd:key_value5;break;// 第2行第2列 - 5case0xbd:key_value6;break;// 第2行第3列 - 6case0x7d:key_value7;break;// 第2行第4列 - 7}while(P2!0xfd);returnkey_value;}}// 扫描第3行 P20xfb;// 1111 1011if(P2!0xfb){delay(50);if(P2!0xfb){tempP2;switch(temp){case0xeb:key_value8;break;// 第3行第1列 - 8case0xdb:key_value9;break;// 第3行第2列 - 9case0xbb:key_value10;break;// 第3行第3列 - Acase0x7b:key_value11;break;// 第3行第4列 - b}while(P2!0xfb);returnkey_value;}}// 扫描第4行 P20xf7;// 1111 0111if(P2!0xf7){delay(50);if(P2!0xf7){tempP2;switch(temp){case0xe7:key_value12;break;// 第4行第1列 - Ccase0xd7:key_value13;break;// 第4行第2列 - dcase0xb7:key_value14;break;// 第4行第3列 - Ecase0x77:key_value15;break;// 第4行第4列 - F}while(P2!0xf7);returnkey_value;}}return16;// 无按键按下返回16}// 主程序voidmain(){uchar key;while(1){keykeyscan();// 扫描键盘if(key16)// 有效按键0-15{numkey;// 更新显示值}display(num);// 显示结果delay(5);// 短暂延时避免显示闪烁}}