51单片机,单个按键按下弹起后,控制LED状态
ledmod==0 长灭
ledmod==1常亮
ledmod==2 呼吸灯
代码,如下,当到mod2的时候,呼吸灯亮了,但再按下键的时候,无法切换模式,
各位学霸帮说一说具体问题,修改下代码能正常执行
#include
#include "Timer0.h"
void breath();
void Br_dy(unsigned int t)
{
while(t--);
}
unsigned char Time,Speed;
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
unsigned char ledmod=0,ledcount;
void main()
{
Timer0Init();
while(1)
{
if(P3_1==0)
{
Delay(50);
while(P3_1==0);
Delay(50);
ledmod++;
}
if(ledmod>=3)
{
ledmod=0;
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18;
TH0 = 0xFC;
T0Count++;
if(ledmod==0)
{
P2_0=1;
}
if(ledmod==1)
{
P2_0=0;
}
if(ledmod==2)
{
//ºôÎüµÆÄ£Ê½
unsigned char Time,Speed;
for(Time=0;Time<100;Time++)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Br_dy(Time);
P2_0=1;
Br_dy(100-Time);
}
}
for(Time=100;Time>0;Time--)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Br_dy(Time);
P2_0=1;
Br_dy(100-Time);
}
}
}
}
问题如下:
1、在 main 函数中缺少一个对ledmod的判断,导致ledmod会超过3后不会回到0
2、在main函数中缺少 while(1) 死循环,所以程序会在 main 函数执行完后结束
3、Timer0Init() 函数没有定义,需要补充这个函数的实现
4、在 Timer0_Routine 函数中缺少中断标志的清除
5、Br_dy(unsigned int t) 函数的实现不够优秀
修改后的代码如下:
#include <REGX52.H>
unsigned char ledmod=0,ledcount;
void Timer0Init()
{
TMOD |= 0x01;
TH0 = 0xFC;
TL0 = 0x18;
TR0 = 1;
ET0 = 1;
}
void Delay(unsigned int xms)
{
unsigned int i, j;
for(i = xms; i > 0; i--)
{
for(j = 110; j > 0; j--);
}
}
void main()
{
Timer0Init();
while(1)
{
if(P3_1==0)
{
Delay(50);
while(P3_1==0);
Delay(50);
ledmod++;
}
if(ledmod>=3)
{
ledmod=0;
}
}
}
void Timer0_Routine() interrupt 1
{
TH0 = 0xFC;
TL0 = 0x18;
if(ledmod==0)
{
P2_0=1;
}
if(ledmod==1)
{
P2_0=0;
}
if(ledmod==2)
{
//ºôÎüµÆÄ£Ê½
unsigned char Time,Speed;
for(Time=0;Time<100;Time++)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Delay(Time);
P2_0=1;
Delay(100-Time);
}
}
for(Time=100;Time>0;Time--)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Delay(Time);
P2_0=1;
Delay(100-Time);
}
}
}
TF0 = 0;
}
修改后就能正常运行了,你试一试。欢迎点赞
望采纳!!!点击回答右侧采纳即可!!
这段代码中,当按键按下时,ledmod变量的值会加1。当ledmod的值大于等于3时,将其重置为0。在Timer0_Routine中,根据ledmod的值来控制LED的状态。问题在于当ledmod的值等于2时,会进入呼吸灯的模式,但是在呼吸灯模式中,按键按下时并没有进行切换模式的操作,所以ledmod始终等于2。
解决方法:在进入呼吸灯模式时,需要设置一个标记位或计数器,当按键按下时,判断标记位或计数器的值,如果为0则跳出呼吸灯模式,更新ledmod的值。
如:
unsigned char ledmod = 0,ledcount=0;
void main(){
......
if(ledmod == 2){
ledcount = 1; //设置标记位
......
}
......
if(P3_1==0)
{
Delay(50);
while(P3_1==0);
Delay(50);
if(ledcount == 1){ //如果标记位为1则跳出呼吸灯模式
ledcount = 0;
continue;
}
ledmod++;
if(ledmod>=3)
{
ledmod=0;
}
}
}
这样,当进入呼吸灯模式时,设置标记位ledcount为1,按键按下时如果标记位为1则跳出呼吸灯模式并更新ledmod的值。这样就可以正常切换模式了。
我找到几篇相关的内容文章,希望能对你有所帮助
1.51单片机】独立按键控制LED灯(四种形式)
2.51单片机按键控制LED灯状态
3.51单片机独立按键控制led实验_51单片机独立按键控制led实验
这个问题是由于在呼吸灯模式下,按键事件被呼吸灯循环操作占用了,导致按键检测不到。可以在呼吸灯循环里加入一个按键检测,如果按键被按下就退出呼吸灯循环并切换模式。
请修改如下:
if(ledmod==2)
{
//ºôÎüµÆÄ£Ê½
unsigned char Time,Speed;
for(Time=0;Time<100;Time++)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Br_dy(Time);
P2_0=1;
Br_dy(100-Time);
if(P3_1==0)
{
Delay(50);
while(P3_1==0);
Delay(50);
ledmod++;
break;
}
}
if(ledmod>=3)
{
ledmod=0;
break;
}
}
for(Time=100;Time>0;Time--)
在time中断里面加循环不太好,中断程序应该尽量简洁,短小精悍
在呼吸灯模式下,按键按下事件应该修改ledmod的值,使其切换到下一个模式。
例如在按键按下事件中加入如下代码:
ledmod = (ledmod + 1) % 3;
这样每次按下按键就可以切换到下一个模式了。
另外,如果ledmod==2的时候,呼吸灯的代码不能被打断,需要用定时器实现呼吸灯的效果。
这段代码中,当按键按下时,会改变ledmod的值,分别为0,1,2三种状态。在定时器中断中根据ledmod的值来控制LED。
但是,代码中有一个问题就是在ledmod==2的情况下,会进入一个循环,控制LED呼吸灯效果。但是循环中没有检测按键状态,所以无法切换模式。
修改方法如下:
1.在循环中加入按键检测,如果按键按下,跳出循环。
2.将循环放到main函数中,在定时器中断中调用。
3.在main函数中添加一个ledcount变量,每次按键按下时ledcount++,在定时器中断中判断ledcount是否大于100,若大于100,ledcount=0,ledmod++。
参考代码如下:
#include <REGX52.H>
#include "Timer0.h"
unsigned char ledmod=0,ledcount;
void main()
{
Timer0Init();
while(1)
{
if(P3_1==0)
{
Delay(50);
while(P3_1==0);
Delay(50);
ledmod++;
ledcount=0;
if(ledmod>=3)
{
ledmod=0;
}
}
if(ledmod==2)
{
unsigned char Time,Speed;
for(Time=0;Time<100;Time++)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Br_dy(Time);
P2_0=1;
Br_dy(100-Time);
}
}
for(Time=100;Time>0;Time--)
{
for(Speed=0;Speed<20;Speed++)
{
P2_0=0;
Br_dy(Time);
P2_0=1;
Br_dy(100-Time);
}
如果您还是不能解决问题,可以试试以下方法:
使用调试工具查看代码执行过程
尝试使用其他类似的代码来检查是否问题出在硬件上
检查按键连接是否正确,是否有杂音
检查定时器配置是否正确
检查中断服务程序是否正确。
望采纳。