目的
按下K1键LED流水向左移动
按下K2键LED流水向右移动
按下K3键LED流水停止(原位闪烁)
一,STC单片机模块
二,独立按键
2.1 独立按键位置
2.2 独立按键电路图
这里要注意一个设计的bug
P3_1 引脚对应是K1
P3_0 引脚对应是K2
要实现按一下点亮、再按一下熄灭,我们就需要分析按键上的电压变化。
对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会立即断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动 。如上图。
具体在程序上我们就需要按照这个图做相应的处理。
if(P3_1==0) //如果K1按键按下
{
Delay(15); //延时消抖
while(P3_1==0); //松手检测
Delay(15); //延时消抖
P2_0=~P2_0; //LED1取反
}
要实现左右移动分别控制, 我们定义变量左移就自减1右移就自加1.
if(P3_1==0) //如果K1按键按下
{
Delay_ms(15); //延时消抖
while(P3_1==0); //松手检测 一直按着没松手
Delay_ms(15); //延时消抖
LED_Num--; //变量减1
if(LED_Num<0)
{
LED_Num=7; //当最左边一个灯亮后,下一个是最右边一个灯亮
}
}
if(P3_0==0) //如果K2按键按下
{
Delay_ms(15); //延时消抖
while(P3_0==0); //松手检测 一直按着没松手
Delay_ms(15); //延时消抖
LED_Num++; //变量加1
if(LED_Num==8)
{
LED_Num=0; //当最右边一个灯亮后,下一个是最左边一个灯亮
}
}
当在两头时我们要分别判定下,并重新从头开始。
我们这里要记录方向的三种模式,向左、向右、暂停。以及暂停时LED所处的位置。
unsigned int Dire=1; //流水灯方向2-向左(K1), 1-向右(K2),0-暂停(K3),默认向右
unsigned int PaseLED=0xff; //按下暂停键保存当前P2的值
方向判定
//方向判定
if(Dire==0) //暂停
{
if(P2==0xff){
P2=PaseLED;
}
else {
P2=0xff;
}
}
if(Dire==1) //向右
{
if(P2==0xff){
P2=PaseLED;
}
P2=_crol_(P2,1); //灯右移
PaseLED=P2;
}
if(Dire==2) //向右
{
if(P2==0xff){
P2=PaseLED;
}
P2=_cror_(P2,1); //灯左移
PaseLED=P2;
}
我这里用到了 _cror_ 和 _crol_ 移位运算的函数,所以需要引入 NTRINS.h
#include <INTRINS.h>
三,创建Keil项目
详细参考:51单片机STC89C52RC——创建Keil项目-CSDN博客
四,代码
#include <REGX52.H>
#include <INTRINS.h>
/**
* 函 数:延时函数 毫秒
* 参 数:ms 延时多少毫秒
* 返 回 值:无
*/
void Delay_ms(int ms) //@12.000MHz
{
unsigned char data i, j;
while(ms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
/**
* 函 数:主函数
* 参 数:无
* 返 回 值:无
*/
void main()
{
unsigned int Dire=1; //流水灯方向2-向左(K1), 1-向右(K2),0-暂停(K3),默认向右
unsigned int PaseLED=0xff; //按下暂停键保存当前P2的值
P2=0xFE; //上电默认D1 亮
while(1)
{
Delay_ms(500); //延时500毫秒
if(P3_1==0) //K1被按下
{
Delay_ms(15); //延时消抖
while(P3_1==0); //松手检测 一直按着没松手
Delay_ms(15); //延时消抖
Dire=2; //0-向左
}
if(P3_0==0) //K2被按下
{
Delay_ms(15); //延时消抖
while(P3_0==0); //松手检测 一直按着没松手
Delay_ms(15); //延时消抖
Dire=1; //1-向右
}
if(P3_2==0) //K2被按下
{
Delay_ms(15); //延时消抖
while(P3_2==0); //松手检测 一直按着没松手
Delay_ms(15); //延时消抖
Dire=0; //暂停
}
//方向判定
if(Dire==0) //暂停
{
if(P2==0xff){
P2=PaseLED;
}
else {
P2=0xff;
}
}
if(Dire==1) //向右
{
if(P2==0xff){
P2=PaseLED;
}
P2=_crol_(P2,1); //灯右移
PaseLED=P2;
}
if(Dire==2) //向右
{
if(P2==0xff){
P2=PaseLED;
}
P2=_cror_(P2,1); //灯左移
PaseLED=P2;
}
}
}
五,代码编译、下载到51单片机
代码编译请参考
《51单片机STC89C52RC——代码编译-CSDN博客》
代码下载请参考
《51单片机STC89C52RC——STCAI-ISP代码下载-CSDN博客》