如何把for循环改为实时系统(已经解决)
本帖最后由 biying 于 2014-6-21 00:04 编辑有个报警音函数,是用for循环来实现,但这样影响了系统的实时性,我想把它改成实时系统,却遇到这个for循环是有两个初值的呢,大家都是怎么解决的?
void alarm(void) //报警
{
//static unsigned char k;
TCCR1=0x56;// 开启A路PWM输出
if(alarm_ON==1)//警报音开关
{
for(LIGHT=124;LIGHT>82;LIGHT--)//138对应1.8KHZ,70对应3.5KHZ,频率从1.8K到3.5K匀速增加,
{
//OCR1C=LIGHT; //改到溢出中断中修改就不会出爆破音了
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
OCR1A=(LIGHT/2);
Even_numbers=0;
}
Even_numbers++;
delay_ms(6); //
}
for(LIGHT=82;LIGHT<124;LIGHT++)//138对应1.8KHZ,70对应3.5KHZ,频率从3.5K到1.8K匀速减少,
{
//OCR1C=LIGHT;//改到溢出中断中修改就不会出爆破音了
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
OCR1A=(LIGHT/2);
Even_numbers=0;
}
Even_numbers++;
delay_ms(6);
}
}
} for(LIGHT=124;LIGHT>40;LIGHT--)
{
if(LIGHT > 82)
{
OCR1A=(LIGHT/2);
}
else
{
OCR1A=((82 + 82 - LIGHT)/2);
}
}
这样就是一个初值了 改实时系统的话,计时就得用外部计时了,主程序每次运行这个报警函数的时候,根据计时变量的值的不同执行不同的动作。 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的赋初值不好处理。 yht0312 发表于 2014-6-20 11:49
改实时系统的话,计时就得用外部计时了,主程序每次运行这个报警函数的时候,根据计时变量的值的不同执行不 ...
是的,Tiny85,我用T0产生计时,T1做互补PWM,做实时真是麻烦呢! 就是改成2ms调用一次这个函数,是吧 xiaowu191 发表于 2014-6-20 15:51
就是改成2ms调用一次这个函数,是吧
不是,原for程序是6ms改变一次LIGHT的值,改实时系统就不能用for死循环了 这个报警函数得放主循环里,有报警才跑里面的,在前头有个if开关呢! 改成状态机就可以。 状态机可以 uint8_t LIGHT;
void alarm(void) //报警
{
static uint8_t time_tick = 0x03;
static uint8_t index = 0x00;
static uint8_t Even_numbers = 0x00;
//static unsigned char k;
TCCR1 = 0x56; // 开启A路PWM输出
if(alarm_ON != 1) //警报音开关关
{
time_tick = 0x03;
index = 0x00;
Even_numbers = 0x00;
}
else if(alarm_ON == 1)//警报音开关开
{
if(time_tick --)
{
return; //没到时间,不执行
}
time_tick = 0x03; //2ms * 3 = 6ms
index ++;
if(index > 83)
{
index = 0x00;
}
if(index <= 41)
{
LIGHT = 124 - index; //124 - 83
}
else if(index <= 83)
{
LIGHT = 40 + index; //82 - 123
}
if((Even_numbers ++) & 0x01)
{
OCR1A = LIGHT >> 1;
}
}
}
这样可以不?2ms调用一次 状态机就行了 虽然上面很多人说了,但是还是要告诉楼主一声,状态机就可以{:lol:} 大家说的状态机是不是指马潮老师按键处理的那种程序? 搞定了,看起来和原FOR比没有多几行嘛,谢谢大家!不知道还能否再优化
void alarm(void) //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
{
static unsigned char alarm_status,initial_a;
if(alarm_ON==1)//警报音开关
{
switch (alarm_status)
{
case 0:
if(initial_a==0) //初始值装载开关,自关闭型
{
PWM_Frequency=124; //初始PWM频率
OCR1A=62;//初始占空比
initial_a=1;//关闭初始值装载开关
TCCR1=0x56;// 开启A路PWM输出
alarm_Delay=0;
}
if(alarm_Delay>=3) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
{
alarm_Delay=0;
if(PWM_Frequency-->82) //频率从1.8K到3.5K匀速增加
{
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
OCR1A=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
}
elsealarm_status=1;
}
break;
case 1:
if(alarm_Delay>=3) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
{
alarm_Delay=0;
if(PWM_Frequency++<124)//频率从3.5K到1.8K匀速减少
{
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
OCR1A=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
}
elsealarm_status=0;
if(++alarm_total_time>=250)//报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
{
alarm_ON=0;//关闭报警开关
TCCR1=0x00;// 关闭A路PWM输出
alarm_status=0;
}
}
break;
/*
for(PWM_Frequency=124;PWM_Frequency>82;PWM_Frequency--)//138对应1.8KHZ,70对应3.5KHZ,频率从1.8K到3.5K匀速增加,
{
//OCR1C=LIGHT; //改到溢出中断中修改就不会出爆破音了
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
OCR1A=(LIGHT/2);
Even_numbers=0;
}
Even_numbers++;
delay_ms(6); //
}
for(PWM_Frequency=82;PWM_Frequency<124;PWM_Frequency++)//138对应1.8KHZ,70对应3.5KHZ,频率从3.5K到1.8K匀速减少,
{
//OCR1C=LIGHT;//改到溢出中断中修改就不会出爆破音了
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
OCR1A=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
delay_ms(6);
}*/
}
}
} xiaowu191 发表于 2014-6-20 16:43
这样可以不?2ms调用一次
谢谢,你那23行 return; //没到时间,不执行
是怎么执行的,我没看懂 加入节拍速度、报警次数 void alarm(void) //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
{
static unsigned char alarm_status,initial_a,i,j;
if(alarm_ON==1)//警报音开关
{
switch (alarm_status)
{
if(alarm_ON_flag==1) //新开报警标识,有新的报警指令时为1
{
alarm_status=0;
initial_a=0;
alarm_ON_flag=0;
}
case 0:
if(initial_a==0) //初始值装载开关,自关闭型
{
PWM_Frequency=124; //初始PWM频率
OCR1A=62;//初始占空比
initial_a=1;//关闭初始值装载开关
TCCR1=0x56;// 开启A路PWM输出
alarm_Delay=0;
}
if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
{
alarm_Delay=0;
if(PWM_Frequency-->82) //频率从1.8K到3.5K匀速增加
{
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
Duty_Ratio=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
}
elsealarm_status=1;
}
break;
case 1:
if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
{
alarm_Delay=0;
if(PWM_Frequency++<124)//频率从3.5K到1.8K匀速减少
{
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
Duty_Ratio=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
}
elsealarm_status=2;
}
break;
case 2:
if(++j>=alarm_total_time)//报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
{
alarm_total_time=0;//清零报警总时间
initial_a=0;//下次再开报警时再装载初始值
TCCR1=0x00;// 关闭A路PWM输出
alarm_status=3;
}
elsealarm_status=0;
break;
case 3:
if(alarm_Delay>=alarm_Interval)//报警声间隔,不响的时间
{
alarm_Delay=0;
alarm_status=4;
}
break;
case 4:
if(++i>=alarm_counter)//报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
{
i=0;
alarm_ON=0;//关闭报警开关
}
elsealarm_status=0;
break;
}
}
}
void alarm_EverySlow(void)//隔1秒慢响一次响3次,无需理会-----预警(单次震动、数错密码)
{
alarm_ON = 1;//开报警
alarm_ON_flag=1;//开报警标示,标示这是一次新的报警
alarm_total_time=1;//响一次为1秒
alarm_Rhythm=6;//节奏快慢
alarm_Interval=500;//间隔1秒响一回
alarm_counter=3;//报警3次
}
void alarm_EveryFast(void)//隔1秒快响一次直到用完电,必须处理-----特急(电瓶断电)
{
alarm_ON = 1;//开报警
alarm_ON_flag=1;//开报警标示,标示这是一次新的报警
alarm_total_time=2;//响一次为1秒
alarm_Rhythm=3;//节奏快慢
alarm_Interval=250;//间隔0.5秒响一回
alarm_counter=3;//报警250次
} 修改了以上错误 void alarm(void) //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
{
static unsigned char alarm_status,initial_a,i,j;
if(alarm_ON==1)//警报音开关
{
if(alarm_ON_flag==1) //新开报警标识,有新的报警指令时为1
{
alarm_status=0;
initial_a=0;
alarm_ON_flag=0;
}
switch (alarm_status)
{
case 0:
if(initial_a==0) //初始值装载开关,自关闭型
{
PWM_Frequency=124; //初始PWM频率
OCR1A=62;//初始占空比
initial_a=1;//关闭初始值装载开关
TCCR1=0x56;// 开启A路PWM输出
alarm_Delay=0;
}
if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
{
alarm_Delay=0;
if(PWM_Frequency-->82) //频率从1.8K到3.5K匀速增加
{
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
Duty_Ratio=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
}
elsealarm_status=1;
}
break;
case 1:
if(alarm_Delay>=alarm_Rhythm) //6毫秒延时到,步进为2毫秒。加大于是防止万一单片机忙过时。
{
alarm_Delay=0;
if(PWM_Frequency++<124)//频率从3.5K到1.8K匀速减少
{
if(Even_numbers==2) //偶数判断后计算占空比为一半,保证音量为最大
{
Duty_Ratio=(PWM_Frequency/2);
Even_numbers=0;
}
Even_numbers++;
}
elsealarm_status=2;
}
break;
case 2:
if(++j>=alarm_total_time)//报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
{
j=0;//清零报警总时间
//initial_a=0;//下次再开报警时再装载初始值
TCCR1=0x00;// 关闭A路PWM输出
alarm_status=3;
}
elsealarm_status=0;
break;
case 3:
if(alarm_Delay>=alarm_Interval)//报警声间隔,不响的时间
{
alarm_Delay=0;
alarm_status=4;
}
break;
case 4:
if(++i>=alarm_counter)//报警声总时间=数值X0.012秒,250时为3秒,即:响3秒后自动关闭报警
{
i=0;
alarm_ON=0;//关闭报警开关
}
else
{
alarm_status=0;
TCCR1=0x56;// 开启A路PWM输出
}
break;
}
}
} 糟了,一不小心i=0;j=0; 没有写入if(alarm_ON_flag==1) //新开报警标识,有新的报警指令时为1,导致新切换报警音时会碰到少响次数。void alarm(void) //报警 ,频率从1.8K到3.5K匀速增加,然后再从3.5K到1.8K匀速减少,匀速进行,模拟报警音,占空比保持最大保证音量最大
{
static unsigned char alarm_status,initial_a,i,j;
if(alarm_ON==1)//警报音开关
{
if(alarm_ON_flag==1) //新开报警标识,有新的报警指令时为1
{
alarm_status=0;
initial_a=0;
alarm_ON_flag=0;
i=0;
j=0;
}
switch (alarm_status)
{
case 0:
页:
[1]