我用keil c51编了一个流水灯程序,编译无误却只有第一和第二个灯亮了,最后停在第一个灯处不动
请知道的朋友帮我分析下原因,改了好几次都那样:#include<reg51.h>#defineucharunsignedcharuchara=0;uchartt=1;vo...
请知道的朋友帮我分析下原因,改了好几次都那样:
#include<reg51.h>
#define uchar unsigned char
uchar a=0;
uchar tt=1;
void main()
{
TMOD=0x10;
TH1=0xd8;
TL1=0xf0;
EA=1;
ET1=1;
TR1=1;
while(1);
}
void time1() interrupt 3
{ P1=0xfe;
tt++;
if(tt==10)
{for(a=0;a<8;a++)
{ P1=(P1<<1)+1;
};
if(a==8)
P1=0xfe;
};
} 展开
#include<reg51.h>
#define uchar unsigned char
uchar a=0;
uchar tt=1;
void main()
{
TMOD=0x10;
TH1=0xd8;
TL1=0xf0;
EA=1;
ET1=1;
TR1=1;
while(1);
}
void time1() interrupt 3
{ P1=0xfe;
tt++;
if(tt==10)
{for(a=0;a<8;a++)
{ P1=(P1<<1)+1;
};
if(a==8)
P1=0xfe;
};
} 展开
3个回答
展开全部
你有几个错误:
1 你的定时器没有重装,导致第一次中断和后面的中断时间不一样,第一次时间短,后面的时间一直是以65536个周期中断的.
2 你在中断函数里用了 for 循环,for循环是一下子就执行完了的,而不是你想象的每中断一次才执行一次.
for(a=0;a<8;a++)
{
P1=(P1<<1)+1; //----这一句,使得你的第二个灯亮,其实第三,四,五个都亮了,但是因为你的
//----For循环太快了,你看不出来
};
if(a==8) //---执行完for之后,a肯定等于8,所以执行下面的,结果就是第一个灯亮
P1=0xfe;
3 我给你改正的,程序:功能是先是第一个灯亮,再是第一个灯灭,亮2,然后2灭,亮3.....
void time1() interrupt 3
{
tt++;
if(tt==10)
{
tt = 0; //---这句表示中断10次换一个灯,不可少
//----如果没有这句tt = 0,则成了中断256次才换一个灯
P1 =~(1<<aa); //---下面这三句,你好好想想是为什么,如果不明白再问我
//---最好要自己思考,想明白
aa++;
aa &= 0x07;
}
//----别忘记装入初值,你这个应该是10ms中断,然后是100ms换一次灯
//-----如果你不装初值,就成了 65.536ms中断一次,再加上你前面不加上 tt = 0;
//------就成了16秒才换一次灯
TH1=0xd8;
TL1=0xf0;
}
1 你的定时器没有重装,导致第一次中断和后面的中断时间不一样,第一次时间短,后面的时间一直是以65536个周期中断的.
2 你在中断函数里用了 for 循环,for循环是一下子就执行完了的,而不是你想象的每中断一次才执行一次.
for(a=0;a<8;a++)
{
P1=(P1<<1)+1; //----这一句,使得你的第二个灯亮,其实第三,四,五个都亮了,但是因为你的
//----For循环太快了,你看不出来
};
if(a==8) //---执行完for之后,a肯定等于8,所以执行下面的,结果就是第一个灯亮
P1=0xfe;
3 我给你改正的,程序:功能是先是第一个灯亮,再是第一个灯灭,亮2,然后2灭,亮3.....
void time1() interrupt 3
{
tt++;
if(tt==10)
{
tt = 0; //---这句表示中断10次换一个灯,不可少
//----如果没有这句tt = 0,则成了中断256次才换一个灯
P1 =~(1<<aa); //---下面这三句,你好好想想是为什么,如果不明白再问我
//---最好要自己思考,想明白
aa++;
aa &= 0x07;
}
//----别忘记装入初值,你这个应该是10ms中断,然后是100ms换一次灯
//-----如果你不装初值,就成了 65.536ms中断一次,再加上你前面不加上 tt = 0;
//------就成了16秒才换一次灯
TH1=0xd8;
TL1=0xf0;
}
追问
对 P1 =~(1<<aa),我不知道aa<<1和1<<aa是不是一回事。然后你说先开第一个灯再灭第一个,aa应该是0xff,但是第一个灯左移再取反是不是除了第一个灯灭了,其他灯都亮了,感觉不能达到你说的一个亮一个灭的效果。aa &= 0x07是不是跟移位次数有关,恕我新手没太看懂。
追答
哦,不懂没关系,我也从新人过来的,我给你讲一下:
我们先来看1的二进制是多少 1 = 0000 0001,那么看下面的左右移:
(1<<0)= 0000 0001 ; ~(1<<0)= 1111 1110
(1<<1)= 0000 0010 ; ~(1<<1)= 1111 1101
(1<<2)= 0000 0100 ; ~(1<<2)= 1111 1011
(1<<3)= 0000 1000 ; ~(1<<3)= 1111 0111
(1<<4)= 0001 0000 ; ~(1<<4)= 1110 1111
(1<<5)= 0010 0000 ; ~(1<<5)= 1101 1111
(1<<6)= 0100 0000 ; ~(1<<6)= 1011 1111
(1<<7)= 1000 0000 ; ~(1<<7)= 0111 1111
现在你知道 P1 = ~(1<<aa);是怎么实现来旧灯亮新灯的吧?
aa &= 0x07 把aa的数值限制在了 0-7之间,相当于 aa %= 0x08; 是一样的,
只是单片机的 % 运算太复杂,效率不高,所以,我一般用 & 运算
展开全部
你不是工作在自动重装模式下的,所以定时器中断中要装初值
灯要有延时程序的
灯要有延时程序的
追问
不是 我是T1初始化工作在方式一的
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
程序的逻辑有问题,不知道程序想干嘛。tt是干什么用的?为什么一直自加没有清零?
你看这样是不是可以:
定义一个全局变量数组
uchar led[]={0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
中断函数中改成:
{
P1=led[a];
a++;
if(a>=8) a=0;
}
如果tt是想增加延时的长度,也可以加到程序中。自加到想要的值后记得清零。
你看这样是不是可以:
定义一个全局变量数组
uchar led[]={0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
中断函数中改成:
{
P1=led[a];
a++;
if(a>=8) a=0;
}
如果tt是想增加延时的长度,也可以加到程序中。自加到想要的值后记得清零。
追问
tt是用来延长延时时间的,我再试试,先给你个好评
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询