C语言关于单片机单键控制灯三种状态问题

我写了个单键控制单灯三种状态的程序,就是不知道为什么按键效果不行,我的程序也没有错,就是运行后按第一次是快闪,按第二次是慢闪,按第三次是长亮,按第四次是关闭,然后再循环,可是我按键却不是这效果,请高手指点一下!#include<reg52.h>sbit light5=P1^4; sbit key1=P3^4;void scankey1(void);void delay(unsigned long int us){while(us--);}void main(){while(1){ scankey1(); } } void scankey1(){ unsigned char num1;if(key1==0){delay(50); if(key1==0){ num1++;if(num1==5)num1=0; } } switch(num1){ case 1: light5=0;delay(20000);light5=1;delay(20000);break; case 2: light5=0;delay(80000);light5=1;delay(80000);break; case 3: light5=0;break; case 4: light5=1;break; } }

//主要是延时防抖做得不好,按键在压下的头几毫秒都是不稳定的
//我写了个延时防抖的程序发上来
#include<stdio.h>
#include<reg52.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define FOSC 24000000 //晶振 设定24M 依实际定,常见的外部晶振有16M 24M 32M 40M等 这里定错了也没关系,顶多就是下面的时间单位不是预计的值罢了
#define TIME0_OUT 200
#define _TICT (uint)(FOSC/12/1000/(TIME0_OUT-1)) //T0每毫秒溢出次数
#define KEYON 0 //假定按下键后稳定为的低电平0 (依电路设计有可能是1为按下)
#define LIGHTON 0 //假定LED灯低电平时亮起 (实际有可能是高电平1亮起)
bit TICK_FLAG;
bit DIR;
uchar j;
uchar itime;
uchar idata RUN_MODE;
uint idata TIMESCONTS;
uint idata KEYTIME;
sbit light5 = P1^4;
sbit key1 = P3^4;
void init()
{
TMOD= 0x22;//计数/定时器0工作方式2 计数/定时器1工作方式2
TH0 = 256-TIME0_OUT;
TL0 = 256-TIME0_OUT;
ET0 = 1; //计数/定时器0允许发生中断
TF0 = 0; //清除中断标记
TR0 = 1; //T0开始计时
RUN_MODE = 4; //初始状态为关
//light5 = 1; //高电平关灯 初始时本来就是1,所以省了,如果是0为关灯,则这行与上 light5 = 0;
EA = 1; //开总中断
}
void delay(uint ms)
{//毫秒级延时函数 误差小于等于(1/_TICT)毫秒
uchar i;
while(ms-- > 0)
{
for(i=0; i<_TICT; i++)
{
TICK_FLAG = 0;
while(!TICK_FLAG);
}
}
}
void timer0() interrupt 1 using 1 //T0 中断1 模式2 自动装载
{
static uchar si = _TICT;
static uchar switchTmp,switchTmp1;
static bit tmpb;
si--;
TICK_FLAG = 1; // 时间信号 (1/TICK_FLAG) 毫秒/次
if(si==0) // 1毫秒处理一次
{
si = _TICT;
if(KEYTIME) //如果不等于0的话,每毫秒自减1直到0
KEYTIME--;
if(TIMESCONTS) //如果不等于0的话,每毫秒自减1直到0
TIMESCONTS--;
tmpb = ~tmpb;
if(tmpb)
{
if(DIR)//反向
{
if(itime) //每2毫秒自减1直到0
itime--;
}
else//正向
{
if(itime!=0xFF) //每2毫秒自加1直到255
itime++;
}
}
//软件防抖延时处理 移位法
if(key1==KEYON)
{
switchTmp = switchTmp<<1|0x01;
if(switchTmp==0xFF) //连继8个1认为是1
{
if(switchTmp1) //从按下开关到电平稳定只处理一次,需要松开后再按才会处理下一次
{
RUN_MODE++; // 1 - 4 循环
if(RUN_MODE>5)
RUN_MODE = 1;
switchTmp1 = 0;
}
KEYTIME = 60000; //按键松开后这个值会每毫秒衰减1直到0
}
}else{
switchTmp = switchTmp<<1; //连继8次0即认为是0
if( switchTmp == 0x00)
switchTmp1 = 1;
}
}
}
void main()
{
init();
BEGIN: //这里 定义一个自走节目:刚开机或超过1分钟无按键动作时 进行自走
DIR = 0; //正向
itime = 50; //从0开始
while(KEYTIME==0)
{
for(j=0xFF; j; j--) //模似PWM 亮度渐变
{
if(j>=itime)
light5 = (1-LIGHTON); //熄灯
else
light5 = LIGHTON; //开灯
}
if(itime==0xFF)
{
delay(10);//保持最亮10毫秒
DIR = 1; //开始减亮度
}
else if(itime==0)
{
delay(10); //保持熄灭10毫秒
DIR = 0; //开始增加亮度
itime = 50; //起始亮度(占空比太小时,其实都是没亮度的)
}
}
while(1)
{
if(RUN_MODE==1)
{
if(TIMESCONTS==0)
{
light5 = ~light5;
TIMESCONTS = 100;//100毫秒翻转一次也就是1秒闪了5次
}
}
if(RUN_MODE==2)
{
if(TIMESCONTS==0)
{
light5 = ~light5;
TIMESCONTS = 500;//半秒翻转一次,也就是1秒闪1次
}
}
if(RUN_MODE==3)
{
light5 = LIGHTON;
}
if(RUN_MODE==4)
{
light5 = (1-LIGHTON);
}
if(KEYTIME==0) //超过1分钟没有按键了,就跳到自走节目中
goto BEGIN;
}
}
//这个程序应当可以在你的电路上跑起来
温馨提示:答案为网友推荐,仅供参考
相似回答