找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2312|回复: 9
打印 上一主题 下一主题
收起左侧

单片机遥控控制流水灯的开和关,程序出现了死循环没有跳出

[复制链接]
跳转到指定楼层
楼主
ID:237797 发表于 2019-10-17 16:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
自己51单片机写的用遥控器来控制流水灯开和关,现在遥控可以打开流水灯工作,不能关闭。出现问题的原因是在流水灯程序里出现了死循环没有跳出来,有啥解决思路?

单片机源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>
  3. sbit ADDR0 = P1^0;
  4. sbit ADDR1 = P1^1;
  5. sbit ADDR2 = P1^2;
  6. sbit ADDR3 = P1^3;
  7. sbit ENLED = P1^4;
  8. sbit LED1 = P0^0;



  9. typedef unsigned char uint8;
  10. typedef unsigned int uint16;

  11. uint8 dir = 0;                //移位方向
  12. uint8 shift = 0x01;                //循环变量
  13. uint16 i = 0;

  14. extern bit irflag;
  15. extern unsigned char ircode[4];
  16. extern void InitInfrared();
  17. void LshiftRshift();


  18. void main()
  19. {
  20.         EA = 1;
  21.         ADDR0 = 0;
  22.         ADDR1 = 1;
  23.         ADDR2 = 1;
  24.         ADDR3 = 1;
  25.         ENLED = 0;

  26.         InitInfrared();

  27.         while (1)
  28.         {
  29.                 if (irflag)
  30.                 {
  31.                         irflag = 0;
  32.                         if (ircode[2] == 0x45)          //0X45  遥控器键值
  33.                         {
  34.                                 LshiftRshift();
  35.                         }
  36.                         else if (ircode[2] == 0x46)          
  37.                         {
  38.                                 ENLED = 1;
  39.                         }
  40.                        
  41.                 }
  42.         }
  43. }


  44. void LshiftRshift()
  45. {       
  46.         ENLED = 0;
  47.         ADDR3 = 1;

  48.         ADDR0 = 0;
  49.         ADDR1 = 1;                    
  50.         ADDR2 = 1;


  51.         while(1)
  52.         {       
  53.                 P0 = ~shift;
  54.                 for (i=0;i<20000;i++);
  55.                 if (!dir)           //!dir和dir==0 逻辑相同   dir和dir==1 逻辑相同
  56.                 {
  57.                         shift = shift<<1;
  58.                         if (shift == 0x80)
  59.                         {
  60.                                 dir = 1;
  61.                         }
  62.                 }
  63.                 else
  64.                 {
  65.                         shift = shift>>1;
  66.                         if (shift == 0x01)
  67.                         {
  68.                                 dir = 0;
  69.                         }
  70.                 }
  71.         }
  72. }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:601639 发表于 2019-10-17 17:21 | 只看该作者
设个标志位,工作完成后标志位置0,需要执行时标志位置1
回复

使用道具 举报

板凳
ID:235200 发表于 2019-10-17 18:30 | 只看该作者
把流水灯LshiftRshift程序中的while(1)改为while(退出条件)就能退出了
回复

使用道具 举报

地板
ID:237797 发表于 2019-10-18 08:16 | 只看该作者
csmyldl 发表于 2019-10-17 18:30
把流水灯LshiftRshift程序中的while(1)改为while(退出条件)就能退出了

谢谢你的回答,你的方法有效!
回复

使用道具 举报

5#
ID:237797 发表于 2019-10-18 08:17 | 只看该作者
那个谁和谁 发表于 2019-10-17 17:21
设个标志位,工作完成后标志位置0,需要执行时标志位置1

你说的方法,我试过,不知道是加错了,不能实现想要的功能
回复

使用道具 举报

6#
ID:237797 发表于 2019-10-18 17:46 | 只看该作者
本帖最后由 lclbf 于 2019-10-19 10:43 编辑

遥控部分程序如下:#include<reg51.h>

sbit IR_INPUT = P3^3;

bit irflag = 0;
unsigned char ircode[4];

void InitInfrared()
{
        IR_INPUT = 1;
        TMOD &= 0X0F;
        TMOD |= 0X10;
        TR1 = 0;
        ET1 = 0;
        IT1 = 1;
        EX1 = 1;
}

unsigned int GetHighTime()
{
        TH1 = 0;
        TL1 = 0;
        TR1 = 1;
        while (IR_INPUT)
        {
                if (TH1 >= 0X40)
                {
                        break;
                }
        }
        TR1 = 0;
        return (TH1*256 + TL1);
}

unsigned int GetLowTime()
{
        TH1 = 0;
        TL1 = 0;
        TR1 = 1;
        while (!IR_INPUT)
        {
                if (TH1 >= 0X40)
                {
                        break;
                }
        }
        TR1 = 0;
        return (TH1*256 + TL1);
}

void EXINT1_ISR() interrupt 2
{
        unsigned char i,j;
        unsigned char byt;
        unsigned int time;

        time = GetLowTime();
        if ((time<7833)||(time>8755))
        {
                IE1 = 0;
                return;
        }
        time = GetHighTime();
        if ((time<3686)||(time>4608))
        {
                IE1 = 0;
                return;
        }
        for (i=0;i<4;i++)
        {
                for (j=0;j<8;j++)
                {
                        time = GetLowTime();
                        if ((time<313)||(time>718))
                        {
                                IE1 = 0;
                                return;
                        }
                        time = GetHighTime();
                        if ((time>313)&&(time<718))
                        {
                                byt >>= 1;
                        }
                        else if ((time>1345)&&(time<1751))
                        {
                                byt >>= 1;
                                byt |= 0x80;
                        }
                        else
                        {
                                IE1 = 0;
                                return;
                        }
                }
                ircode = byt;
        }
        irflag = 1;
        IE1 = 0;
}

回复

使用道具 举报

7#
ID:237797 发表于 2019-10-18 17:48 | 只看该作者
lclbf 发表于 2019-10-18 08:16
谢谢你的回答,你的方法有效!

这是按照你说的方法,修改的程序:


#include<reg51.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

typedef unsigned char uint8;
typedef unsigned int uint16;


uint16 i = 0;
uint8 dir = 0;                //移位方向
uint8 shift = 0x01;                //循环变量
uint8 LRshiftflag = 0;

extern bit irflag;
extern unsigned char ircode[4];
extern void InitInfrared();
void LshiftRshift();

void main()
{
        EA = 1;

        InitInfrared();

        while (1)
        {
                if (irflag)
                {
                        irflag = 0;
                        if (ircode[2] == 0x45)          //0X45  遥控器键值
                        {       
                                LshiftRshift();
                        }
                        else if (ircode[2] == 0x46)          
                        {       
                                ENLED = 1;
                        }
                       
                }
        }
}


void LshiftRshift()
{       
        ENLED = 0;
        ADDR3 = 1;

        ADDR0 = 0;
        ADDR1 = 1;                    
        ADDR2 = 1;


        while(ircode[2] == 0x45) //while(ircode[2] == 0x45)  while(ircode[2] != 0x46)        不能用while(1),会死在里面,跳不出来,不能关
        {       
               
                        P0 = ~shift;
                        for (i=0;i<20000;i++);
                        if (!dir)           //!dir和dir==0 逻辑相同   dir和dir==1 逻辑相同
                        {
                                shift = shift<<1;
                                if (shift == 0x80)
                                {
                                        dir = 1;
                                }
                        }
                        else
                        {
                                shift = shift>>1;
                                if (shift == 0x01)
                                {
                                        dir = 0;
                                }
                        }
        }
}

回复

使用道具 举报

8#
ID:237797 发表于 2019-10-20 11:14 | 只看该作者
那个谁和谁 发表于 2019-10-17 17:21
设个标志位,工作完成后标志位置0,需要执行时标志位置1

用你说的标志位的方法实现的控制,程序如下:
#include<reg51.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

bit sysOn = 0;


typedef unsigned char uint8;
typedef unsigned int uint16;


uint16 i = 0;
uint8 dir = 0;                //移位方向
uint8 shift = 0x01;                //循环变量
uint8 LRshiftflag = 0;

extern bit irflag;
extern unsigned char ircode[4];
extern void InitInfrared();
void LshiftRshift();

void main()
{
        EA = 1;

        InitInfrared();

                while (1)
                {
                        if (irflag)
                        {
                                irflag = 0;
                       
                                if (ircode[2] == 0x45)          //0X45  遥控器键值
                                {       
                                        sysOn = 1;
                                }
                                else if (ircode[2] == 0x46)          
                                {       
                                        sysOn = 0;
                                }                               
                        }
                        LshiftRshift();
        }

}


void LshiftRshift()
{       
//        ENLED = 0;                  //注消这部分不能放这个位置,会出现不能关灯
//        ADDR3 = 1;
//
//        ADDR0 = 0;
//        ADDR1 = 1;                    
//        ADDR2 = 1;

                if (sysOn)
                {       
                        ENLED = 0;
                        ADDR3 = 1;
               
                        ADDR0 = 0;
                        ADDR1 = 1;                    
                        ADDR2 = 1;

                        P0 = ~shift;
                        for (i=0;i<20000;i++);
                        if (!dir)           //!dir和dir==0 逻辑相同   dir和dir==1 逻辑相同
                        {
                                shift = shift<<1;
                                if (shift == 0x80)
                                {
                                        dir = 1;
                                }
                        }
                        else  
                        {
                                shift = shift>>1;
                                if (shift == 0x01)
                                {
                                        dir = 0;
                                }
                        }
                }
                else
                {
                ENLED = 1;        //关灯程序
                }

}

回复

使用道具 举报

9#
ID:237797 发表于 2019-10-20 11:18 | 只看该作者
现在还有个问题,就是关的时候灯在哪里灭,下次开灯接着哪里亮,有没有办法每次开灯在同一个地方亮?想到在关灯的时候赋初值,还是不行,会出现下次开灯就是初值的灯亮,不流动了。
回复

使用道具 举报

10#
ID:542032 发表于 2019-10-20 13:18 | 只看该作者
你这需要把数据存到51的eeprom里,用的时候调用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表