搜索
bottom↓
回复: 18

如何把for循环改为实时系统(已经解决)

[复制链接]

出0入0汤圆

发表于 2014-6-20 09:41:48 | 显示全部楼层 |阅读模式
本帖最后由 biying 于 2014-6-21 00:04 编辑

有个报警音函数,是用for循环来实现,但这样影响了系统的实时性,我想把它改成实时系统,却遇到这个for循环是有两个初值的呢,大家都是怎么解决的?

  1. void alarm(void)   //报警
  2. {
  3.   //static unsigned char k;
  4.   TCCR1=0x56;// 开启A路PWM输出
  5.   if(alarm_ON==1)  //警报音开关
  6.     {
  7.      for(LIGHT=124;LIGHT>82;LIGHT--)  //138对应1.8KHZ,70对应3.5KHZ  ,频率从1.8K到3.5K匀速增加,
  8.      {     
  9.          //OCR1C=LIGHT; //改到溢出中断中修改就不会出爆破音了                 
  10.          if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  11.            {
  12.             OCR1A=(LIGHT/2);
  13.             Even_numbers=0;
  14.            }
  15.          Even_numbers++;   
  16.          delay_ms(6); //         
  17.      }        
  18.         for(LIGHT=82;LIGHT<124;LIGHT++)  //138对应1.8KHZ,70对应3.5KHZ  ,频率从3.5K到1.8K匀速减少,
  19.         {         
  20.          //OCR1C=LIGHT;  //改到溢出中断中修改就不会出爆破音了
  21.          if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  22.            {
  23.             OCR1A=(LIGHT/2);
  24.             Even_numbers=0;
  25.            }
  26.          Even_numbers++;
  27.          delay_ms(6);         
  28.         }         
  29.     }
  30. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-6-20 11:44:05 | 显示全部楼层
for(LIGHT=124;LIGHT>40;LIGHT--)
{
    if(LIGHT > 82)
    {
        OCR1A=(LIGHT/2);   
    }
    else
    {
        OCR1A=((82 + 82 - LIGHT)/2);
    }
}


这样就是一个初值了

出0入0汤圆

发表于 2014-6-20 11:49:08 | 显示全部楼层
改实时系统的话,计时就得用外部计时了,主程序每次运行这个报警函数的时候,根据计时变量的值的不同执行不同的动作。

出0入0汤圆

 楼主| 发表于 2014-6-20 15:23:44 | 显示全部楼层
xiaowu191 发表于 2014-6-20 11:44
for(LIGHT=124;LIGHT>40;LIGHT--)
{
    if(LIGHT > 82)

谢谢!这是用PWM模拟警报音,频率改变得修改LIGHT值。除以2那个是为了保持50%的占空比。改为实时系统我用T0产生2ms,现在要把for改为if,但for中对LIGHT=124的赋初值不好处理。

出0入0汤圆

 楼主| 发表于 2014-6-20 15:26:55 | 显示全部楼层
yht0312 发表于 2014-6-20 11:49
改实时系统的话,计时就得用外部计时了,主程序每次运行这个报警函数的时候,根据计时变量的值的不同执行不 ...

是的,Tiny85,我用T0产生计时,T1做互补PWM,做实时真是麻烦呢!

出0入0汤圆

发表于 2014-6-20 15:51:40 | 显示全部楼层
就是改成2ms调用一次这个函数,是吧

出0入0汤圆

 楼主| 发表于 2014-6-20 16:09:15 | 显示全部楼层
xiaowu191 发表于 2014-6-20 15:51
就是改成2ms调用一次这个函数,是吧

不是,原for程序是6ms改变一次LIGHT的值,改实时系统就不能用for死循环了

出0入0汤圆

 楼主| 发表于 2014-6-20 16:11:18 | 显示全部楼层
这个报警函数得放主循环里,有报警才跑里面的,在前头有个if开关呢!

出0入8汤圆

发表于 2014-6-20 16:17:51 | 显示全部楼层
改成状态机就可以。

出0入0汤圆

发表于 2014-6-20 16:21:47 | 显示全部楼层
状态机可以

出0入0汤圆

发表于 2014-6-20 16:43:48 | 显示全部楼层
  1. uint8_t LIGHT;
  2.        
  3. void alarm(void)                        //报警
  4. {
  5.         static uint8_t time_tick = 0x03;
  6.         static uint8_t index = 0x00;
  7.        
  8.         static uint8_t Even_numbers = 0x00;
  9.        
  10.         //static unsigned char k;
  11.         TCCR1 = 0x56;                        // 开启A路PWM输出
  12.        
  13.         if(alarm_ON != 1)                  //警报音开关关
  14.         {
  15.                 time_tick = 0x03;
  16.                 index = 0x00;
  17.                 Even_numbers = 0x00;
  18.         }
  19.         else if(alarm_ON == 1)  //警报音开关开
  20.         {
  21.                 if(time_tick --)
  22.                 {
  23.                         return;                        //没到时间,不执行
  24.                 }
  25.                
  26.                 time_tick = 0x03;        //2ms * 3 = 6ms
  27.                
  28.                 index ++;
  29.                
  30.                 if(index > 83)
  31.                 {
  32.                         index = 0x00;
  33.                 }
  34.                
  35.                 if(index <= 41)                               
  36.                 {
  37.                         LIGHT = 124 - index;        //124 - 83
  38.                 }
  39.                 else if(index <= 83)               
  40.                 {
  41.                         LIGHT = 40 + index;                //82 - 123
  42.                 }
  43.                
  44.                 if((Even_numbers ++) & 0x01)
  45.                 {
  46.                         OCR1A = LIGHT >> 1;
  47.                 }

  48.         }
  49. }
复制代码


这样可以不?2ms调用一次

出0入0汤圆

发表于 2014-6-20 16:59:56 来自手机 | 显示全部楼层
状态机就行了

出0入0汤圆

发表于 2014-6-20 18:22:14 | 显示全部楼层
虽然上面很多人说了,但是还是要告诉楼主一声,状态机就可以

出0入0汤圆

 楼主| 发表于 2014-6-20 19:40:26 | 显示全部楼层
大家说的状态机是不是指马潮老师按键处理的那种程序?

出0入0汤圆

 楼主| 发表于 2014-6-21 00:04:09 | 显示全部楼层
搞定了,看起来和原FOR比没有多几行嘛,谢谢大家!不知道还能否再优化
  1. void alarm(void)   //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
  2. {
  3.   static unsigned char alarm_status,initial_a;   
  4.   if(alarm_ON==1)  //警报音开关
  5.   {
  6.      switch (alarm_status)
  7.      {
  8.         case 0:
  9.           if(initial_a==0)    //初始值装载开关,自关闭型  
  10.           {
  11.             PWM_Frequency=124; //初始PWM频率
  12.             OCR1A=62;//初始占空比
  13.             initial_a=1;//关闭初始值装载开关
  14.             TCCR1=0x56;// 开启A路PWM输出
  15.             alarm_Delay=0;
  16.           }
  17.           if(alarm_Delay>=3) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
  18.            {
  19.              alarm_Delay=0;
  20.              if(PWM_Frequency-->82) //频率从1.8K到3.5K匀速增加
  21.               {
  22.                 if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  23.                  {
  24.                    OCR1A=(PWM_Frequency/2);
  25.                    Even_numbers=0;
  26.                  }
  27.                  Even_numbers++;
  28.               }
  29.               else  alarm_status=1;         
  30.            }
  31.            break;           
  32.         case 1:         
  33.           if(alarm_Delay>=3) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
  34.            {
  35.              alarm_Delay=0;
  36.              if(PWM_Frequency++<124)  //频率从3.5K到1.8K匀速减少
  37.               {
  38.                 if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  39.                  {
  40.                    OCR1A=(PWM_Frequency/2);
  41.                    Even_numbers=0;
  42.                  }
  43.                  Even_numbers++;
  44.               }
  45.               else  alarm_status=0;
  46.               if(++alarm_total_time>=250)  //报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
  47.                {
  48.                 alarm_ON=0;//关闭报警开关
  49.                 TCCR1=0x00;// 关闭A路PWM输出
  50.                 alarm_status=0;
  51.                }         
  52.            }
  53.            break;
  54.       /*   
  55.      for(PWM_Frequency=124;PWM_Frequency>82;PWM_Frequency--)  //138对应1.8KHZ,70对应3.5KHZ  ,频率从1.8K到3.5K匀速增加,
  56.      {     
  57.          //OCR1C=LIGHT; //改到溢出中断中修改就不会出爆破音了                 
  58.          if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  59.            {
  60.             OCR1A=(LIGHT/2);
  61.             Even_numbers=0;
  62.            }
  63.          Even_numbers++;   
  64.          delay_ms(6); //         
  65.      }        
  66.         for(PWM_Frequency=82;PWM_Frequency<124;PWM_Frequency++)  //138对应1.8KHZ,70对应3.5KHZ  ,频率从3.5K到1.8K匀速减少,
  67.         {         
  68.          //OCR1C=LIGHT;  //改到溢出中断中修改就不会出爆破音了
  69.          if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  70.            {
  71.             OCR1A=(PWM_Frequency/2);
  72.             Even_numbers=0;
  73.            }
  74.          Even_numbers++;
  75.          delay_ms(6);         
  76.         }  */      
  77.      }
  78.   }
  79. }
复制代码

出0入0汤圆

 楼主| 发表于 2014-6-21 00:12:08 | 显示全部楼层
xiaowu191 发表于 2014-6-20 16:43
这样可以不?2ms调用一次

谢谢,你那23行                        return;                        //没到时间,不执行
是怎么执行的,我没看懂

出0入0汤圆

 楼主| 发表于 2014-6-21 04:33:40 | 显示全部楼层
加入节拍速度、报警次数
  1. void alarm(void)   //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
  2. {
  3.   static unsigned char alarm_status,initial_a,i,j;   
  4.   if(alarm_ON==1)  //警报音开关
  5.   {
  6.      switch (alarm_status)
  7.      {
  8.         if(alarm_ON_flag==1)    //新开报警标识,有新的报警指令时为1
  9.           {
  10.             alarm_status=0;
  11.             initial_a=0;
  12.             alarm_ON_flag=0;            
  13.           }
  14.         case 0:
  15.           if(initial_a==0)    //初始值装载开关,自关闭型  
  16.           {
  17.             PWM_Frequency=124; //初始PWM频率
  18.             OCR1A=62;//初始占空比
  19.             initial_a=1;//关闭初始值装载开关
  20.             TCCR1=0x56;// 开启A路PWM输出
  21.             alarm_Delay=0;
  22.           }
  23.           if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
  24.            {
  25.              alarm_Delay=0;
  26.              if(PWM_Frequency-->82) //频率从1.8K到3.5K匀速增加
  27.               {
  28.                
  29.                 if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  30.                  {
  31.                    Duty_Ratio=(PWM_Frequency/2);
  32.                    Even_numbers=0;
  33.                  }
  34.                  Even_numbers++;
  35.               }
  36.               else  alarm_status=1;         
  37.            }
  38.            break;           
  39.         case 1:         
  40.           if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
  41.            {
  42.              alarm_Delay=0;
  43.              if(PWM_Frequency++<124)  //频率从3.5K到1.8K匀速减少
  44.               {
  45.                 if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  46.                  {
  47.                    Duty_Ratio=(PWM_Frequency/2);
  48.                    Even_numbers=0;
  49.                  }
  50.                  Even_numbers++;
  51.               }
  52.               else  alarm_status=2;
  53.            }
  54.            break;
  55.          case 2:  
  56.            if(++j>=alarm_total_time)  //报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
  57.            {
  58.            alarm_total_time=0;//清零报警总时间               
  59.            initial_a=0;//下次再开报警时再装载初始值
  60.            TCCR1=0x00;// 关闭A路PWM输出
  61.            alarm_status=3;
  62.            }
  63.            else  alarm_status=0;
  64.            break;
  65.          case 3:
  66.            if(alarm_Delay>=alarm_Interval)//报警声间隔,不响的时间
  67.            {
  68.             alarm_Delay=0;
  69.             alarm_status=4;
  70.             
  71.            }
  72.             break;
  73.           case 4:
  74.            if(++i>=alarm_counter)  //报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
  75.             {
  76.              i=0;
  77.              alarm_ON=0;//关闭报警开关
  78.             }
  79.             else  alarm_status=0;
  80.             break;     
  81.      }
  82.   }
  83. }
  84. void alarm_EverySlow(void)//隔1秒慢响一次响3次,无需理会-----预警(单次震动、数错密码)
  85. {
  86. alarm_ON = 1;//开报警
  87. alarm_ON_flag=1;//开报警标示,标示这是一次新的报警
  88. alarm_total_time=1;//响一次为1秒
  89. alarm_Rhythm=6;//节奏快慢
  90. alarm_Interval=500;//间隔1秒响一回
  91. alarm_counter=3;//报警3次  
  92. }
  93. void alarm_EveryFast(void)//隔1秒快响一次直到用完电,必须处理-----特急(电瓶断电)
  94. {
  95. alarm_ON = 1;//开报警
  96. alarm_ON_flag=1;//开报警标示,标示这是一次新的报警
  97. alarm_total_time=2;//响一次为1秒
  98. alarm_Rhythm=3;//节奏快慢
  99. alarm_Interval=250;//间隔0.5秒响一回
  100. alarm_counter=3;//报警250次
  101. }
复制代码

出0入0汤圆

 楼主| 发表于 2014-6-21 16:56:34 | 显示全部楼层
修改了以上错误
  1. void alarm(void)   //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
  2. {
  3.   static unsigned char alarm_status,initial_a,i,j;   
  4.   if(alarm_ON==1)  //警报音开关
  5.   {
  6.       if(alarm_ON_flag==1)    //新开报警标识,有新的报警指令时为1
  7.           {
  8.             alarm_status=0;
  9.             initial_a=0;
  10.             alarm_ON_flag=0;            
  11.           }
  12.      switch (alarm_status)
  13.      {
  14.       
  15.         case 0:
  16.           if(initial_a==0)    //初始值装载开关,自关闭型  
  17.           {
  18.             PWM_Frequency=124; //初始PWM频率
  19.             OCR1A=62;//初始占空比
  20.             initial_a=1;//关闭初始值装载开关
  21.             TCCR1=0x56;// 开启A路PWM输出
  22.             alarm_Delay=0;
  23.           }
  24.           if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
  25.            {
  26.              alarm_Delay=0;
  27.              if(PWM_Frequency-->82) //频率从1.8K到3.5K匀速增加
  28.               {
  29.                
  30.                 if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  31.                  {
  32.                    Duty_Ratio=(PWM_Frequency/2);
  33.                    Even_numbers=0;
  34.                  }
  35.                  Even_numbers++;
  36.               }
  37.               else  alarm_status=1;         
  38.            }
  39.            break;           
  40.         case 1:         
  41.           if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
  42.            {
  43.              alarm_Delay=0;
  44.              if(PWM_Frequency++<124)  //频率从3.5K到1.8K匀速减少
  45.               {
  46.                 if(Even_numbers==2)   //偶数判断后计算占空比为一半,保证音量为最大
  47.                  {
  48.                    Duty_Ratio=(PWM_Frequency/2);
  49.                    Even_numbers=0;
  50.                  }
  51.                  Even_numbers++;
  52.               }
  53.               else  alarm_status=2;
  54.            }
  55.            break;
  56.          case 2:  
  57.            if(++j>=alarm_total_time)  //报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
  58.            {
  59.            j=0;//清零报警总时间               
  60.            //initial_a=0;//下次再开报警时再装载初始值
  61.            TCCR1=0x00;// 关闭A路PWM输出
  62.            alarm_status=3;
  63.            }
  64.            else  alarm_status=0;
  65.            break;
  66.          case 3:
  67.            if(alarm_Delay>=alarm_Interval)//报警声间隔,不响的时间
  68.            {
  69.             alarm_Delay=0;
  70.             alarm_status=4;
  71.             
  72.            }
  73.             break;
  74.           case 4:
  75.            if(++i>=alarm_counter)  //报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
  76.             {
  77.              i=0;
  78.              alarm_ON=0;//关闭报警开关
  79.             }
  80.             else  
  81.              {
  82.               alarm_status=0;
  83.               TCCR1=0x56;// 开启A路PWM输出
  84.              }
  85.             break;     
  86.      }
  87.   }
  88. }
复制代码

出0入0汤圆

 楼主| 发表于 2014-6-21 17:15:47 | 显示全部楼层
糟了,一不小心i=0;  j=0; 没有写入if(alarm_ON_flag==1)    //新开报警标识,有新的报警指令时为1,导致新切换报警音时会碰到少响次数。
  1. void alarm(void)   //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
  2. {
  3.   static unsigned char alarm_status,initial_a,i,j;   
  4.   if(alarm_ON==1)  //警报音开关
  5.   {
  6.       if(alarm_ON_flag==1)    //新开报警标识,有新的报警指令时为1
  7.           {
  8.             alarm_status=0;
  9.             initial_a=0;
  10.             alarm_ON_flag=0;
  11.             i=0;
  12.             j=0;            
  13.           }
  14.      switch (alarm_status)
  15.      {
  16.       
  17.         case 0:
复制代码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-4 04:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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