单片机流水灯问题

题目:在P1口接8个发光二极管(高电平或低电平亮都可以),完成流水灯功能。设计一个按键(随便哪个口),开始中间朝二边开花,按一次键松开后由上到下亮,再按松开后由下到上亮,... 题目:在P1口接8个发光二极管(高电平或低电平亮都可以),完成流水灯功能。设计一个按键(随便哪个口),开始中间朝二边开花,按一次键松开后由上到下亮,再按松开后由下到上亮,再按松开后朝二边开花,又再按键松开后朝二边开花,如此循环。形成三种状态,如R1开始为0,按以下键松开后R1加一,加到3又回到零,形成0、1、2三种状态,判别零的值程序到不同的分支)。

我编写的程序:#include<at89x52.h>
#define uchar unsigned char
#define uint unsigned int
sbit key=P3^0;
uint data count;

void delay(){
uint i;
for(i=0;i<32000;i++);
}

void led0(void){
uchar temp=0x18,a,b;
uint i;
P1=temp;
delay();
for(i=0;i<4;i++){
a=(temp&0xf0)<<i;
b=(temp&0x0f)>>i;
P1=a|b; delay();
}
}

void led1(void){
uchar cmd=0x01;
while(1){
P1=cmd;
delay();
if((cmd&0x80)==0x80) cmd=(cmd<<1)+1;
else cmd=cmd<<1;
}
}

void led2(void){
uchar cmd=0x80;
while(1){
P1=cmd;
delay();
if((cmd&0x01)==0x01) cmd=(cmd>>1)+0x80;
else cmd=cmd>>1;
}
}

void main(void){
count=0;
led0();
while(1){
if(key==0){
delay();
if(key==0){
count=count+1;
if(count==3) count=0;
}
while(key==0);
}
switch(count){
case 0: led0();break;
case 1: led1();break;
case 2: led2();break;
default:;
}
}
}

问题:仿真按键转换状态时,第一次按,转为第二种状态,再次按键后,就没反应了,不能转为下一状态,请大侠们指点一下,谢谢!!
展开
 我来答
哈尔滨单片机
推荐于2016-02-07 · 超过13用户采纳过TA的回答
知道答主
回答量:72
采纳率:0%
帮助的人:28.2万
展开全部
你的问题在与led1()和led2()中有while(1)死循环,程序是不会出来了,可以根据实际要求设定循环次数,但是如果这样 按下的时间会长,因为要执行完for 才能检测到按键。
键盘最好不用P0口,如果要使用必须接上拉电阻
#include<at89x52.h>
#define uchar unsigned char
#define uint unsigned int
sbit key=P3^0;
uint data count;

void delay(){
uint i;
for(i=0;i<32000;i++);
}

void led0(void){
uchar temp=0x18,a,b;
uint i;
P1=temp;
delay();
for(i=0;i<4;i++){
a=(temp&0xf0)<<i;
b=(temp&0x0f)>>i;
P1=a|b; delay();
}
}

void led1(void){
uchar cmd=0x01;
for( )//这里不能用死循环;就像led0()一样,用FOR控制次数,你自己填写吧,不过这样按按键的时间要长。
{
P1=cmd;
delay();
if((cmd&0x80)==0x80) cmd=(cmd<<1)+1;
else cmd=cmd<<1;
}
}
}
void led2(void){
uchar cmd=0x80;
for( )//这里不能用死循环;就像led0()一样,用FOR控制次数,你自己填写吧,不过这样按按键的时间要长。
{

P1=cmd;
delay();
if((cmd&0x01)==0x01) cmd=(cmd>>1)+0x80;
else cmd=cmd>>1;
}
}
}
void main(void){
count=0;
led0();
while(1){
if(key==0){
delay();
if(key==0){
count=count+1;
if(count==3) count=0;
}
while(key==0);
}
switch(count){
case 0: led0();break;
case 1: led1();break;
case 2: led2();break;
default:;
}
}
}
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
宿兴电子
2024-11-28 广告
联系我们一、有无震荡源 无源这里的“源”不是指电源,而是指震荡源。也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。 二、价格不同 有源蜂鸣器往比无源蜂鸣器贵,就是因为里面多个震荡... 点击进入详情页
本回答由宿兴电子提供
太急工匠
2010-11-09 · 超过22用户采纳过TA的回答
知道答主
回答量:118
采纳率:0%
帮助的人:76万
展开全部
按键是否接有上啦电阻?松开后不能自动上拉吧。另外你的led1、2函数里面都有while(1){},按理说按键根本就不会有作用,但是你的led0()里面又没有while(1){}所以能从第一状态跳出来,第一次按键后进入led1()后,就无法扫描你的按键程序咯。
呵呵!

给分吧!
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
wsxtg
2010-11-09 · TA获得超过3794个赞
知道小有建树答主
回答量:1794
采纳率:0%
帮助的人:1159万
展开全部
把松手检测放到判断函数内部改成如下程序试一下:
void main(void){
count=0;
led0();
while(1){
if(key==0){
delay();
if(key==0){
while(key==0);
count=count+1;
if(count==3) count=0;
}

}
switch(count){
case 0: led0();break;
case 1: led1();break;
case 2: led2();break;
default:;
}
}
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
安迪的快乐时光
2021-04-05
知道答主
回答量:27
采纳率:0%
帮助的人:1.2万
展开全部

花样流水灯的玩法,一个51单片机8位端口轮流输出16颗灯珠,

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式