完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
基于蓝桥杯的单片机模块练习——矩阵键盘算法
功能概述 通过矩阵键盘控制8个数码管同时显示一个字符。 C代码 #include "stc15f2k60s2.h" //行 ***it R1 = P3^0; ***it R2 = P3^1; ***it R3 = P3^2; ***it R4 = P3^3; //列 ***it C1 = P4^4; ***it C2 = P4^2; ***it C3 = P3^5; ***it C4 = P3^4; unsigned char code SMG_duanma[] = {0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xc6,0xa1,0x86,0x8e, 0xbf,0x7f}; void ScanKey(); void DisplayAll(unsigned char num); void SystemInit(); void SelectHC573(unsigned channel); void Timer0_Init(); void KeyAction(unsigned char KeyCode); void main() { SystemInit(); Timer0_Init(); while(1) { ScanKey(); } } void SelectHC573(unsigned channel) { switch(channel) { case 0 : P2 = (P2 & 0X1F) | 0X00;break; case 4 : P2 = (P2 & 0X1F) | 0X80;break; case 5 : P2 = (P2 & 0X1F) | 0XA0;break; case 6 : P2 = (P2 & 0X1F) | 0XC0;break; case 7 : P2 = (P2 & 0X1F) | 0XE0;break; } } void SystemInit() { SelectHC573(5); P0 = 0x00; SelectHC573(0); P0 = 0xff; } void DisplayAll(unsigned char num) { SelectHC573(6); P0 = 0xff; SelectHC573(7); P0 = SMG_duanma[num]; } unsigned char KeyStat[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};//经消抖之后的键值 //矩阵按键编号的映射表,按照键盘标号映射.比如S7就映射0x07 unsigned char code KeyCodeMap[4][4] = {{0x07,0x11,0x15,0x19}, {0x06,0x10,0x14,0x18}, {0x05,0x09,0x13,0x17}, {0x04,0x08,0x12,0x16} }; void KeyAction(unsigned char KeyCode)//对照着映射表完成相应按键的动作 { switch(KeyCode) { case 0x04 : DisplayAll(4);break; case 0x05 : DisplayAll(5);break; case 0x06 : DisplayAll(6);break; case 0x07 : DisplayAll(7);break; case 0x08 : DisplayAll(8);break; case 0x09 : DisplayAll(9);break; case 0x10 : DisplayAll(10);break; case 0x11 : DisplayAll(11);break; case 0x12 : DisplayAll(12);break; case 0x13 : DisplayAll(13);break; case 0x14 : DisplayAll(14);break; case 0x15 : DisplayAll(15);break; case 0x16 : DisplayAll(16);break; case 0x17 : DisplayAll(17);break; case 0x18 : DisplayAll(17);break; case 0x19 : DisplayAll(17);break; } } void ScanKey() { unsigned char i,j; static unsigned char backup[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};储存上一次的键值 for(i = 0; i<4; i++) { for(j = 0; j<4;j++) { if(backup[j] != KeyStat[j]) { if(backup[j] == 0)//松手检测,松开按键后动作 { KeyAction(KeyCodeMap[j]); } backup[j] = KeyStat[j]; } } } } void Timer0_Init() { TMOD = 0X00; TH0 = (65536 - 1000) / 256; TL0 = (65536 - 1000) % 256; EA = 1; ET0 = 1; TR0 = 1; } void Timer0_Service() interrupt 1 { unsigned char i; static unsigned char keyout = 0; //矩阵按键扫描输出索引 static unsigned char Keybuf[4][4] = { //矩阵按键扫描缓冲区 {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF} }; //将一行的4个按键值移入缓冲区 Keybuf[keyout][0] = (Keybuf[keyout][0] << 1) | C1; Keybuf[keyout][1] = (Keybuf[keyout][1] << 1) | C2; Keybuf[keyout][2] = (Keybuf[keyout][2] << 1) | C3; Keybuf[keyout][3] = (Keybuf[keyout][3] << 1) | C4; //消抖后更新按键状态 for (i=0; i<4; i++) //每行4个按键,所以循环4次 { if ((Keybuf[keyout] & 0x0F) == 0x00) { //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下 KeyStat[keyout] = 0; } else if (( Keybuf[keyout] & 0x0F) == 0x0F) { //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起 KeyStat[keyout] = 1; } } //执行下一次的扫描输出 keyout++; //输出索引递增 keyout = keyout & 0x03; //索引值加到4即归零 switch (keyout) //根据索引,释放当前输出引脚,拉低下次的输出引脚 { case 0: R4 = 1; R1 = 0; break;//因为总共有四行,所以同一行是间隔4ms检测一下状态 case 1: R1 = 1; R2 = 0; break; case 2: R2 = 1; R3 = 0; break; case 3: R3 = 1; R4 = 0; break; } } 相关知识点 keyout = keyout & 0x03; //加到4即归零 keyout = keyout & 0x01; //加到2即归零 keyout = keyout & 0x07; //加到8即归零 keyout = keyout & 0x0f; //加到16即归零 拓展功能 长、短按键的算法 void KeyScan() { unsigned char i,j; static unsigned char backup[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; for(i=0; i<4; i++) { for(j=0; j<4; j++) { if(backup[j] != KeySta[j]) { lkey_flag = 0; count_key = 0; while(KeySta[j]==0); if(backup[j] == 1) { if(lkey_flag) KeyAction(KeyCodemap[j]);//长按键 else KeyAction(255 - KeyCodemap[j]);//短按键 } backup[j] = KeySta[j]; } } } } //****************在中断里的计时判断********** //count_key每1ms自加一 if(count_key == 1000) { lkey_flag = 1; count_key = 0; } //******************************************* 哪位大佬有没有更高级的长短按键判断的算法,告诉兄弟一下。抱拳了!!! switch (keyout) //根据索引,释放当前输出引脚,拉低下次的输出引脚 { case 0: R4 = 1; R1 = 0; break;//因为总共有四行,所以同一行是间隔4ms检测一下状态 case 1: R1 = 1; R2 = 0; break; case 2: R2 = 1; R3 = 0; break; case 3: R3 = 1; R4 = 0; break; } 这部分代码在用到串口通讯时需要修改,不能再对R1和R2进行操作。 |
|
|
|
只有小组成员才能发言,加入小组>>
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
3363 浏览 0 评论
3370 浏览 9 评论
3061 浏览 16 评论
3551 浏览 1 评论
9182 浏览 16 评论
1304浏览 3评论
669浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
663浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2411浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1978浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-2-24 01:35 , Processed in 1.188580 second(s), Total 78, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191