完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
矩阵按键控制数码管显示
矩阵按键和独立按键很不一样,独立按键一段直接与I/O口连接,因此原本为高电平,另一端接地,因此只要检测I/O口是否为低电平就可以检测按键是否被按下。 但是矩阵按键两端同时连接I/O口,因此检测较为复杂。 原理如下: 图中S16按键同时连接P10和P14,因此检测的时候只要先人为给P10一个高电平,P14一个低电平,之后再重复检测P10是否变为低电平就可以检测到S16是否被按下。其他按键原理相同,I/O口高低电平位置可以互换,但是要保证一个是高一个是低。 实验源代码:
#include #define uchar unsigned char #define uint unsigned int ***it jz_key1 = P1^0; //矩阵按键位定义 ***it jz_key2 = P1^1; ***it jz_key3 = P1^2; ***it jz_key4 = P1^3; ***it jz_key5 = P1^4; ***it jz_key6 = P1^5; ***it jz_key7 = P1^6; ***it jz_key8 = P1^7; ***it led2 = P2^2; //数码管显示位选控制 ***it led3 = P2^3; ***it led4 = P2^4; uchar code duanxuan[] = {0x3f,0x06,0x5b,0x4f, //0,1,2,3 0x66,0x6d,0x7d,0x07, //4,5,6,7 0x7f,0x6f,0x77,0x7c, //8,9,A,B 0x39,0x5e,0x79,0x71}; //C,D,E,F 段选 uchar code juzhen[] = {0xf7,0xfb,0xfd,0xfe}; //矩阵按键检测时,一列输入低电平 void delay_xms(uint m) //延时操作 { int i; for(;m>0;m--) for(i=110;i>0;i--); } void display(int i) //数码管显示函数 { switch(i) { case(0):led2=1,led3=1,led4=1;break; case(1):led2=0,led3=1,led4=1;break; case(2):led2=1,led3=0,led4=1;break; case(3):led2=0,led3=0,led4=1;break; case(4):led2=1,led3=1,led4=0;break; case(5):led2=0,led3=1,led4=0;break; case(6):led2=1,led3=0,led4=0;break; case(7):led2=0,led3=0,led4=0;break; } } void keyscan(int n) //按键检测 { int m; //用于计算P0段选 while(n<4) //n小于4,重复四次检测(共4列) { m = n; //m与n相等,可以调整P0段选随着n的变化而变化,m作为间接变量 P1 = juzhen[n]; //给矩阵键盘的一列输入低电平,不同的n对应不同的低电平列 if(jz_key5==0) //行检测 { delay_xms(10); //去除抖动 if(jz_key5==0) { P0 = duanxuan[12+m]; //对于不同n情况下,P0段选做出不同反应,m用于调整 } while(!jz_key5); } if(jz_key6==0) { delay_xms(10); if(jz_key6==0) { P0 = duanxuan[8+m]; } while(!jz_key6); } if(jz_key7==0) { delay_xms(10); if(jz_key7==0) { P0 = duanxuan[4+m]; } while(!jz_key7); } if(jz_key8==0) { delay_xms(10); if(jz_key8==0) { P0 = duanxuan[0+m]; } while(!jz_key8); } n++; } } void Init() //初始化操作 { TMOD = 0X01; //定时器模式 TH0 = (65536-1000)/256;//计数器高八位赋初值 TL0 = (65536-1000)%256;//计数器低八位赋初值 EA = 1; //中断总开关 ET0 = 1; //T0定时器中断开关 } int i=0; //全局变量i,同时在main和中断函数起作用 void main() { P0 = 0X0; //没按按键前,数码管不显示任何数字 Init(); while(1) { TR0 = 1; keyscan(0); } } void time_T0() interrupt 1 { TH0 = (65536-1000)/256;//计数器高八位赋初值 TL0 = (65536-1000)%256;//计数器低八位赋初值 display(i); //数码管独立开主程序显示 i = (i+1)%8; //数码管显示位置控制 } 这个实验中,采用了数码管显示和主程序独立开来的方式,这样在按键检测时按下按键不会影响到数码管的显示。如果不这样,按下按键时,数码管display(i)中的i在那一瞬间是固定的,因而数码管的动态显示会在那一瞬间卡住,如果将显示独立成很短时间的中断来显示,那样就独立开了显示和按键检测,互不影响。 第二是在keyscan函数中使用了while循环和引入了一个间接变量m,这样不同的P1对应不同列的低电平就可以做出不同的按键检测,同时用m对应不同的n情况,对P0的段选做出不同的反应,大大优化了代码。 |
|
|
|
只有小组成员才能发言,加入小组>>
3308 浏览 9 评论
2988 浏览 16 评论
3490 浏览 1 评论
9049 浏览 16 评论
4083 浏览 18 评论
1167浏览 3评论
601浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
592浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2329浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1892浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 12:11 , Processed in 1.152386 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号