单片机——独立按键控制系统
程序员文章站
2022-06-08 21:34:53
...
注意:要加上延时消抖功能(我对这个的理解:消抖是消除键盘的抖动,即假性按下键盘;延时是对键长按时,要延时等待键释放,再进行下一步处理)
电路设计
- P1口高四位分别控制左列LED灯上移、左列LED灯下移、右列LED灯上移、右列LED灯下移
- P0口接左列LED灯
- P2口接右列LED灯
编写思路
- 首先将P0,P2初始化为工作状态,即让每列的第一个灯亮起来
- 进入工作循环状态:
-> 判断是否有键按下:
(有键按下 -> 消抖,延时20ms -> 再判断是否真的有键按下:
(有键按下 -> 查找对应操作,进行处理 -> 处理完毕后,判断键是否释放:
(释放 -> 继续循环;
未释放 -> 等待释放,再回到判断是否有键按下)
无键真的按下 -> 回到判断是否有键按下)
无键按下 -> 回到判断是否有键按下)
汇编语言
ORG 0000H
LJMP START
ORG 0030H
START:MOV P0,#0FEH
MOV P2,#0FEH
START0:MOV P1,#0FFH ;读P1口:首先向P1口送1,为读P1口做准备
MOV A,P1
CJNE A,#0FFH,START1 ;判断是否有键按下
AJMP NEXT
START1:ACALL DELAY0 ;延时20ms消抖
MOV P1,#0FFH
MOV A,P1
CJNE A,#0FFH,JP1 ;再次确认是否真的有键按下
AJMP NEXT
JP1:JNB ACC.4,LP1
JNB ACC.5,LP2
JNB ACC.6,LP3
JNB ACC.7,LP4
SJMP NEXT
LP1:MOV A,P0
RR A
MOV P0,A
SJMP NEXT
LP2:MOV A,P0
RL A
MOV P0,A
SJMP NEXT
LP3:MOV A,P2
RR A
MOV P2,A
SJMP NEXT
LP4:MOV A,P2
RL A
MOV P2,A
NEXT:MOV P1,#0FFH
MOV A,P1 ;再读P1的引脚
CJNE A,#0FFH,NEXT ;确认键是否释放,若没释放,则等待键释放
SJMP START0
DELAY0:MOV R2,#70 ;20ms消抖子程序
D01: MOV R3,#100
D02: DJNZ R3,D02
DJNZ R2,D01
RET
END
C语言
#include <reg51.h> //定义特殊功能寄存器和位寄存器
#include <intrins.h> //定义本征库函数,需要使用库中循环左右移位的函数
#define uchar unsigned char
#define uint unsigned int
sbit L_UP = P1^4; //定义按键
sbit L_DOWN = P1^5;
sbit R_UP = P1^6;
sbit R_DOWN = P1^7;
void delay(uint x) //定义延时xms函数
{
uchar i;
while(x--)
{
for(i = 0; i < 120; i++);
}
}
int judge_ac() //定义判断按键是否按下函数
{
if(P1 != 0xFF) return 1; //有键按下
else return 0; //无键按下或者键已释放
}
void main()
{
P0 = 0xFE;P2 = 0xFE; //初始化P0和P2,让第一个灯亮起来
while(1)
{
if(judge_ac()) //有键按下
{
delay(20); //延时20ms消抖
if(judge_ac()) //判断是否真的有键按下
{
if(!L_UP) P0 = _cror_(P0,1);
else if(!L_DOWN) P0 = _crol_(P0,1);
else if(!R_UP) P2 = _cror_(P2,1);
else if(!R_DOWN) P2 = _crol_(P2,1);
while(judge_ac()); //等待键释放
}
}
}
}
注意:在C中用循环位移函数的话,必须要声明本征库函数intrins;且循环位移函数应该使用char型,不是int型
上一篇: UEFI实战——UART的初始化
下一篇: PHP检测用户语言的方法_PHP教程