找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3099|回复: 16
收起左侧

单片机单键切换4模式 子程序跳不出循环问题

[复制链接]
ID:128588 发表于 2020-3-4 22:08 | 显示全部楼层 |阅读模式
编了一个单键控制一个led四个模式的程序,进入子程序之后,进入while(1)循环无法跳出。。。不怎么如何解决
请朋友们帮我改改(使用的是stc15w104单片机)

单片机源程序如下:
#include<reg52.h>
#define uchar unsigned char
uchar num;
sbit led=P3^1;
sbit S3=P3^0;

void delay(uchar i)
{
        uchar j,k;
        for(j=i;j>0;j--)
        for(k=125;k>0;k--);
}

void ledm1()
{
                                                        
        while(1)
        {
                        led=0;
                 delay(1000);
                 led=1;
                 delay(1000);
        }                    
}

void ledm2()
{
         while(1)
        {
                 led=0;
                 delay(2000);
                 led=1;
                 delay(2000);
         }                                 
}

void ledm3()
{                                                               
           while(1)
           {
                 led=0;
                 delay(3000);
                 led=1;
                 delay(3000);
             }

}

void ledm4()
{                                                                                
                 led=1;              
}

void main()
{
        while(1)
        {
                if(S3==0)
                {
                        delay(20);                 //消抖
                        if(S3==0)
                        {
                                while(!S3);         //等待按键松开
                                    if(num<4)
                                    num++;
                                    else
                                    num=1;
                        }
                        switch(num)
                        {
                                case 1: ledm1();num=1; break;
                                case 2: ledm2();num=2; break;
                                case 3: ledm3();num=3; break;
                                case 4: ledm4();num=4; break;
                                default: break;
                        }
                }
        }
}

回复

使用道具 举报

ID:213173 发表于 2020-3-5 10:12 | 显示全部楼层
楼主在子程序中使用了死循环,程序运行到此时再也出不来,再按按键也就无效了。所有程序都得在主循环 while(1)中跑起来,中断除外。
另外还有两处错误:
1.延时函数的参数数据类型要与实际应用相对应。
2.stc15w104是1T单片机,速度比普通51快许多,延时函数里的变量也要相应增量。
修改如下:
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. sbit led=P3^1;
  5. sbit S3=P3^0;

  6. uchar num;
  7. uint num1;

  8. //1T单片机ms延时程序
  9. void delay(uint i)
  10. {
  11.         uint j,k;
  12.         for(j=i;j>0;j--)
  13.                 for(k=1150;k>0;k--);
  14. }
  15. /*
  16. //12T单片机ms延时程序
  17. void delay(uint i)
  18. {
  19.         uint j,k;
  20.         for(j=i;j>0;j--)
  21.                 for(k=125;k>0;k--);
  22. }
  23. */
  24. void main()
  25. {
  26.         while(1)
  27.         {
  28.                 if(S3==0)
  29.                 {
  30.                         delay(10);                 //消抖
  31.                         if(S3==0)
  32.                         {
  33.                                 while(!S3);         //等待按键松开
  34.                                 num++;
  35.                                 if(num>=4)
  36.                                         num=0;
  37.                         }
  38.                 }
  39.                 if(num==0)
  40.                 {
  41.                         led=1;
  42.                         num1=0;
  43.                 }
  44.                 else
  45.                         num1++;

  46.                 if(num1>num*1000)
  47.                 {
  48.                         num1=0;
  49.                         led=~led;
  50.                 }
  51.                 delay(1);
  52.         }
  53. }

复制代码
回复

使用道具 举报

ID:413383 发表于 2020-3-5 00:19 | 显示全部楼层
在子程序里不能用while(1)吧
回复

使用道具 举报

ID:128588 发表于 2020-3-5 07:35 | 显示全部楼层
hulilanyua 发表于 2020-3-5 00:19
在子程序里不能用while(1)吧

是的  那我怎么让子程序循环?
回复

使用道具 举报

ID:128588 发表于 2020-3-5 08:23 | 显示全部楼层
hulilanyua 发表于 2020-3-5 00:19
在子程序里不能用while(1)吧

那如何让子程序循环
回复

使用道具 举报

ID:697917 发表于 2020-3-5 08:42 | 显示全部楼层
子函数中是用while(1),程序一旦进入就死在里面了。你把判断按键是否放开放在子函数while中,不要用while(1)
回复

使用道具 举报

ID:679425 发表于 2020-3-5 08:54 | 显示全部楼层
break跳出循环操作能用不?
回复

使用道具 举报

ID:697884 发表于 2020-3-5 09:00 | 显示全部楼层
void ledm1()
{
                                                        
       // while(1)
        {
                        led=0;
                 delay(1000);
                 led=1;
                 delay(1000);
        }                    
}

void ledm2()
{
       //  while(1)
        {
                 led=0;
                 delay(2000);
                 led=1;
                 delay(2000);
         }                                 
}

void ledm3()
{                                                               
          // while(1)
           {
                 led=0;
                 delay(3000);
                 led=1;
                 delay(3000);
             }

}
把这些函数里面的while(1)都去掉就可以了。
回复

使用道具 举报

ID:462827 发表于 2020-3-5 09:41 | 显示全部楼层
几个ledm跟数字的子函数中不要用循环了
回复

使用道具 举报

ID:342451 发表于 2020-3-5 10:14 | 显示全部楼层
要子程序循环,你就用最简单的if判断条件就好了,不用搞得那么麻烦
比如
while(1){
   if(按键){num++;}
   if(num == xx){执行什么}
   if(num == xx){执行什么}
... ...
}
就这么多,只要你的num不变,在主函数的while里就会一直执行if满足条件下的语句,不就循环了,而且还不影响你按键切换
回复

使用道具 举报

ID:128588 发表于 2020-3-5 15:09 | 显示全部楼层
之一知足 发表于 2020-3-5 10:14
要子程序循环,你就用最简单的if判断条件就好了,不用搞得那么麻烦
比如
while(1){

这样做的话  我试了  按键检测就成了问题  比如说我子程序的执行的周期是2秒  按下按键的时候 得子程序周期结束才能识别key==0,怎么再增加按键识别频率
回复

使用道具 举报

ID:128588 发表于 2020-3-5 15:11 | 显示全部楼层
黎明初至 发表于 2020-3-5 08:42
子函数中是用while(1),程序一旦进入就死在里面了。你把判断按键是否放开放在子函数while中,不要用while(1 ...

那怎么让子程序中的led一直循环闪烁?
回复

使用道具 举报

ID:128588 发表于 2020-3-5 15:19 | 显示全部楼层
本帖最后由 523503527 于 2020-3-5 15:49 编辑
wulin 发表于 2020-3-5 10:12
楼主在子程序中使用了死循环,程序运行到此时再也出不来,再按按键也就无效了。所有程序都得在主循环 while ...

谢谢,学到了。您编的我差不多看懂了,但是延时的这段,可以移植性不太强,譬如我想改延时 亮500ms,灭1000ms,或者其他没有规律的,num1无法*1000的。能不能教我如何写子程序?
回复

使用道具 举报

ID:128588 发表于 2020-3-5 19:13 | 显示全部楼层
wulin 发表于 2020-3-5 10:12
楼主在子程序中使用了死循环,程序运行到此时再也出不来,再按按键也就无效了。所有程序都得在主循环 while ...

谢谢大神。认真理解了你的编程。还想额外请教你一个问题,如果用子程序,思路该如何?比如子程序1是led1亮500,灭700,循环闪烁,这种无规律,没办法使用num1>num*1000判的
if(num==0)
                {
                        led=1;
                        num1=0;
                }
                else
                        num1++;

                if(num1>num*1000)
                {
                        num1=0;
                        led=~led;
                }
                delay(1);
        }
}

回复

使用道具 举报

ID:703117 发表于 2020-3-5 19:59 | 显示全部楼层
if(num==0)
                {
                        led=1;
                        num1=0;
                }
                else
                        num1++;

                if(num1>num*1000)
                {
                        num1=0;
                        led=~led;
                }
                delay(1);
        }
}
回复

使用道具 举报

ID:213173 发表于 2020-3-5 22:25 | 显示全部楼层
523503527 发表于 2020-3-5 19:13
谢谢大神。认真理解了你的编程。还想额外请教你一个问题,如果用子程序,思路该如何?比如子程序1是led1 ...

给你再改一下,按键不影响程序正常运行,循环闪烁用子程序任意设置周期和亮灭比。
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. sbit led=P3^1;
  5. sbit S3=P3^0;

  6. uchar num;
  7. uchar count=0;        //计数延时
  8. bit   sign=0;        //按键自锁标志

  9. //1T单片机ms延时程序
  10. void delay(uint i)
  11. {
  12.         uint j,k;
  13.         for(j=i;j>0;j--)
  14.                 for(k=1150;k>0;k--);
  15. }
  16. /*
  17. //12T单片机ms延时程序
  18. void delay(uint i)
  19. {
  20.         uint j,k;
  21.         for(j=i;j>0;j--)
  22.                 for(k=125;k>0;k--);
  23. }
  24. */
  25. void ledm1()
  26. {
  27.         static uint i=0;
  28.         i++;
  29.         if(i<=200)
  30.                 led=0;
  31.         if(i>200)
  32.                 led=1;
  33.         if(i>400)
  34.                 i=0;
  35. }
  36. void ledm2()
  37. {
  38.         static uint i=0;
  39.         i++;
  40.         if(i<=100)
  41.                 led=0;
  42.         if(i>100)
  43.                 led=1;
  44.         if(i>300)
  45.                 i=0;
  46. }
  47. void ledm3()
  48. {
  49.         static uint i=0;
  50.         i++;
  51.         if(i<=400)
  52.                 led=0;
  53.         if(i>400)
  54.                 led=1;
  55.         if(i>600)
  56.                 i=0;
  57. }

  58. void main()
  59. {
  60.         while(1)
  61.         {
  62.                 if(!S3)//键按下
  63.                 {
  64.                         if(++count>=10 && sign==0)//消抖与自锁
  65.                         {
  66.                                 sign=1;
  67.                                 num++;
  68.                                 if(num>=4)
  69.                                         num=0;
  70.                         }
  71.                 }
  72.                 else //键松手
  73.                 {
  74.                         count=0;
  75.                         sign=0;       
  76.                 }
  77.                 switch(num)
  78.                 {
  79.                         case 0:  led=1;   break;
  80.                         case 1:  ledm1(); break;
  81.                         case 2:  ledm2(); break;
  82.                         case 3:  ledm3(); break;
  83.                 }
  84.                 delay(1);//控制主循环周期约1ms,如用定时器可以更精确
  85.         }
  86. }

复制代码
回复

使用道具 举报

ID:128588 发表于 2020-3-6 08:41 | 显示全部楼层
wulin 发表于 2020-3-5 22:25
给你再改一下,按键不影响程序正常运行,循环闪烁用子程序任意设置周期和亮灭比。

谢谢   单片机初学   没有这种编程思路,不知道要过多久才能像你一样
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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