按键控制流水灯
你不会是要我们帮你整个程序都写出来吧
你不是这样吧,这样伸手,随便搜索一下都有吧
这话说的,就只要那个开关控制的那段程序,我现在写出来了
所以不用找了
肯定不是啊,就主要实现的那一点啊,再说了又不是很多好吧
想问一下你的按键检测程序是不是这种模式:if(key == 0)
{
delay_ms(20);
while(!key);
}
这个由于引入了延时,延时期间,单片机什么事情都没做,浪费CPU,你应该要让单片机实现延时功能,确又能在延时期间做一些其他事情,再一个是实现按键短按与长按。
楼上为什么不选择定时呢?
利用定时器怎么说?如果说利用外部中断,让按键成为脉冲触发,这个确实应该是可以的,但是我现在问题是线路固定好了,只能用单片机的P0口来完成,没想到好的触发,我现在想到的一个程序是
void main()
{ P2=0xfe;
num=P2;
while(1)
{
while(P0==0xff);
btn=P0;
if(btn==0xfe)
{
num=_crol_(num,1);
delay(300);
P2=num;
}
if(btn==0xfd)
{
num=_cror_(num,1);
delay(300);
P2=num;
}
}
}
这段程序能实现效果,靠的延时,但是总感觉不好一样
按键是弹性按键,按下后弹起,不分长按还是短按,楼下有我想到的一些程序,也是靠延时,能实现效果,但是感觉不咋好,这里有个更好的给你看看,我看的不清楚#include <reg51.h>#include <intrins.h>
unsigned char scan_key();
void proc_key(unsigned char key_v);
void delayms(unsigned char ms);
sbit K1 = P0^0; //对应按钮K1
sbit K2 = P0^1; //对应按钮K2
main()
{
unsigned char key_s,key_v;
key_v = 0x03;
P2 = 0xfe;
while(1)
{
key_s = scan_key();
if(key_s != key_v)
{
delayms(10);
key_s = scan_key();
if(key_s != key_v)
{
key_v = key_s;
proc_key(key_v);
}
}
}
}
unsigned char scan_key()
{
unsigned char key_s;
key_s = 0x00;
key_s |= K2;
key_s <<= 1;
key_s |= K1;
return key_s;
}
void proc_key(unsigned char key_v)
{
if((key_v & 0x01) == 0)
{
P2 = _cror_(P2,1);
}
else if((key_v & 0x02) == 0)
{
P2 = _crol_(P2, 1);
}
}
void delayms(unsigned char ms) // 延时子程序
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
下面是我写的程序,你参考一下,你那个程序感觉可读性不是很强
#include <reg52.h>
/*按键程序,不采用任何空循环延时*/
sbit K1 = P0^0;
sbit K2 = P0^1;
unsigned char KeyValue = 0; //按键键值
unsigned char KeyShortDown = 0; //按键短按
unsigned char KeyLongDown = 0; //按键长按
unsigned char KeyUpFlag = 0;
unsigned int KeyDownTime=0; //按键按下时间
void Time0Init(void); //定时器0初始化
unsigned char GetKeyValue(void);
unsigned char IsKeyUp(void); //有按键松手
void main(void)
{
Time0Init();
P0 = 0xff;
while(1)
{
if(KeyUpFlag == 1)//有按键松手
{
KeyUpFlag = 0;
KeyDownTime=0;
switch (KeyValue)
{
case 1:
if(KeyShortDown == 1) P1 ^= 0x01;
if(KeyLongDown == 1) P1 ^= 0x02;
KeyShortDown = 0;
KeyLongDown = 0;
break;
case 2:
if(KeyShortDown == 1) P1 ^= 0x04;
if(KeyLongDown == 1) P1 ^= 0x08;
KeyShortDown = 0;
KeyLongDown = 0;
break;
default:break;
}
}
}
}
void Time0Init(void)
{
TMOD |= 0x01; //定时器0方式1
TH0 = 0x8A;
TL0 =0xCF; //定时器0定时30ms
ET0 = 1;
TR0 = 1;
EA = 1;
}
unsigned char GetKeyValue(void)
{
if(0 == K1)return 1;
if(0 == K2)return 2;
return 0; //若没有按键按下则返回0
}
unsigned char IsKeyUp(void)
{
if((K1 == 1)&&(K2 == 1))return 1;
else return 0;
}
void Time0(void) interrupt 1
{
unsigned char TempValue;
TH0 = 0x8A;
TL0 = 0xCF; //定时器0定时30ms
TempValue = GetKeyValue(); //这里引入TempValue变量是因为松开手时GetKeyValue返回0,
//若直接KeyValue=GetKeyValue那么松手时KeyValue=0了
if(TempValue != 0)
{
KeyValue = TempValue;
KeyDownTime++;
}
if(KeyDownTime > 1) //30ms 去抖动
{
if(0 != IsKeyUp()) //有按键松手
{
KeyUpFlag = 1;
if(KeyDownTime < 20) KeyShortDown = 1; //按键短按
if(KeyDownTime >= 20) KeyLongDown = 1; //按键长按
}
}
}
你可以参考一下我写的程序,也可以对比一下吧。在你的程序中执行一次按键检测程序总时间有20ms左右吧,20ms中有90%的时间是空出来什么都没做的,这个时间我指的是执行这些语句所需要的时间。再看看我的程序吧,执行定时器中断中所有程序算200us左右吧,在主函数中也算200us左右吧,执行一次按键程序所需语句时间为400us左右吧,其他时间CPU自由扩展,按键一直按下对其他程序没什么影响,因为中断程序时间太短了
首先非常感谢你这么认真为我回答问题,你写的很不错,但是我感觉有点繁琐点了,我主要就是用一个按键直接控制一个灯的亮灭,按键连到P0^0,LED接在P2^0,如果说用到外部中断,那就非常简答,现在不能用这个,你说的我的程序可读性不高,那应该是8楼的吧,但是9楼的程序可读性应该是很好的,你不妨看下九楼的程序。非常感谢你的回答
e ,不好意思,我可能看错了点,是控制流水灯的实现,用两个开关
不用谢啊,写程序要多积累点东西,到网上多找点好资料,c语言方面看一下《c与指针》《c缺陷与陷阱》,还有一点是程序风格很重要,我所说的可读性是指变量名和函数名的命名规则,比如不能用aa,bb,cc,dd这样的方式来命名,几个月后可能自己都看不到自己的程序了,另外一个我推荐的是不要使用延时是因为在大的项目中不方便,会带来很多的麻烦。另外推荐使用状态机编程,这样程序执行会更加好,可读性和可靠性高,调试非常方便
这个貌似很简单的
觉得简单就写出来撒
恩,多谢,受教了
加头文件<intrins.h>,用里面的函数_crol_(,)或者_crol_( , )就行了
不好意思还有一个是_cror_( , )