这篇涵盖51单片机按键消抖函数,用独立按键控制LED。
项目:用2个按键控制一个灯左右移动
新建工程:打开软件
基础操作完成,现在想想怎么写代码
再回顾一下要求:用2个按键控制一个灯左右移动
2个按键,一个左移,一个右移
共有8个灯,同时操作,故选择P2这种寄存器操作而不是P2_0这种单个引脚操作
我们设想一开机,最右边灯亮
按左移按键一下,灯左移一下,
按右移按键一下,灯右移一下,
移到最左边,再按一下左键,灯又跑到最右边
移到最右边,再按一下右键,灯又跑到最左边
一开机,最右边灯亮,P2=0xFE——1111 1110
按左键,1111 1110
1111 1101
1111 1011
1111 0111
1110 1111
1101 1111
1011 1111
0111 1111
1111 1110
我想实现比如先按右键按到第4个灯,再按左键,灯又可以往zuo移,简而言之:灯可在任意位置通过按键左右移动
可以这样操作:定义一个整数,每识别右键按一下,这个整数加一,每识别左键按一下,这个整数减一,用这个整数来控制灯移动。
那么:
按左键,1111 1110这个可以设定为开机初始状态
1111 1101这个0是1111 1110左移一位
1111 1011这个0是1111 1110左移两位
1111 0111这个0是1111 1110左移三位
1110 1111这个0是1111 1110左移四位
1101 1111这个0是1111 1110左移五位
1011 1111这个0是1111 1110左移六位
0111 1111这个0是1111 1110左移七位
1111 1110这个0是1111 1110左移零位,那如何从七跳到零呢?我们可以加个if,else判断语句,一旦检测到这个整数到7,那就给它赋值为0;
那如何实现移位呢?
目前我只知道:
按位左移:<<:所有位左移进行覆盖操作,最低位空出来补零
0110 1101<<2——1011 0100
按位右移:>>所有位右移进行覆盖操作,最高位空出来补零
0100 1010>>1——0010 0101
我们所需要的移位是补1,而这个移位是补零,所以需要进行取反操作
那么:
按左键,1111 1110
1111 1101
1111 1011
1111 0111
1110 1111
1101 1111
1011 1111
0111 1111
1111 1110
相当于,1111 1110开机初始值
0000 0010相当于0000 0001<<1,再取反得到我们需要的1111 1101
0000 0100相当于0000 0001<<2,再取反得到我们需要的1111 1011
0000 1000相当于0000 0001<<3,再取反得到我们需要的1111 0111
0001 0000相当于0000 0001<<4,再取反得到我们需要的1110 1111
0010 0000相当于0000 0001<<5,再取反得到我们需要的1101 1111
0100 0000相当于0000 0001<<6,再取反得到我们需要的1011 1111
1000 0000相当于0000 0001<<7,再取反得到我们需要的0111 1111
0000 0001相当于0000 0001<<0,再取反得到我们需要的1111 1110
那我们可以这样看待这个过程:
假设八个灯依次这样编号排列:
D8 D7 D6 D5 D4 D3 D2 D1
开机:D1亮,key_number=0
key_number为1,0000 0001左移再取反,1111 1101,D2亮
key_number为2,0000 0001左移再取反,1111 1011,D3亮
key_number为3,0000 0001左移再取反,1111 0111,D4亮
key_number为4,0000 0001左移再取反,1110 1111,D5亮
key_number为5,0000 0001左移再取反,1101 1111,D6亮
key_number为6,0000 0001左移再取反,1011 1111,D7亮
key_number为7,0000 0001左移再取反,0111 1111,D8亮
为了使灯在任意位置可左右移动按键,我们可朝着只要key_number为1,则D2亮,使key_number与灯对应,左右移动按键只对key_number进行操作
单片机我还没买,没办法上电检验,目前只是看江科大视频然后自己消化理解的,和江科大的代码有些地方不一样,是我按我想的来的,不确保正确,有错误欢迎大家批评斧正!!!这对我很重要!!!谢谢!!!
#include <REGX52.H>
void delay(unsigned int ms)//延迟1ms函数
{
unsigned char i,j;
while(ms--)
{
i=2;
j=239;
do
{
while(--j);
}while(--i);
}
}
void main()
{
int key_number=0;
P2=0xFE;//开机初始值1111 1110
while(1)//循环
{
if(P3_2==0)//规定P3_2控制左键
{
delay(10);
if(P3_2==0)
{
while(P3_2==0);
if(key_number==7)
key_number=0;
else
key_number++;
}
}
if(P3_3==0)//规定P3_3控制右键
{
delay(10);
if(P3_3==0)
{
while(P3_3==0);
if(key_number==0)
key_number=7;
else
key_number--;
}
}
P2=~(0x01<<key_number);
}
}
我借到板子了,上电看一下效果:
按键控制LED左右移
板子上灯从左到右是: D1 D2 D3 D4 D5 D6 D7 D8
P3_2是K3,是左键,P3_3是K4,是右键,那程序就得改一下:
#include <REGX52.H>
void delay(unsigned int ms)//延迟1ms函数
{
unsigned char i,j;
while(ms--)
{
i=2;
j=239;
do
{
while(--j);
}while(--i);
}
}
void main()
{
int key_number=0;
P2=0xFE;//开机初始值1111 1110
while(1)//循环
{
if(P3_2==0)//规定P3_2控制左键
{
delay(10);
if(P3_2==0)
{
while(P3_2==0);
if(key_number==0)//到最左边,D1点亮,key_number=0
key_number=7;//最左边再按一下左键,应该跳到最右边,D8亮,key_number=7
else
key_number--;//灯从左到右是D1到D8,key_number从左到右是逐级递增,那往左就是key_number减小
}
}
if(P3_3==0)//规定P3_3控制右键
{
delay(10);
if(P3_3==0)
{
while(P3_3==0);
if(key_number==7)//到最右边,D8点亮,key_number=7
key_number=0;//最右边再按一下右键,应该跳到最左边,D1亮,key_number=0
else
key_number++;//灯从左到右是D1到D8,key_number从左到右是逐级递增,那往右就是key_number增大
}
}
P2=~(0x01<<key_number);
}
}
按键控制LED左右移修改后
大功告成!