我一直在用C语言开发一个控制软件。我决定花光 有些时候开发通用功能块可用于我将来开发的其他程序(某种类型的库)。从应用程序的角度来看,我的软件分为两个主要部分。一部分是控制部分 (PI控制器,调制器,锁相环等),第二个是逻辑 部分(应用程序的有限状态机等)。逻辑部分与逻辑信号一起工作。这些信号由逻辑门和触发器的软件实现来处理。我的目标是实现一些振荡器的软件版本。我的意思是一些功能块能够产生0到1之间的振荡,其输出具有规定的周期和占空比。原则上我可以在一个程序中有几个这样的振荡器。所以我有 决定以下列方式实施振荡器。振荡产生由函数完成,振荡器的每个实例由先前定义的结构的实例实现。该结构包含振荡周期,占空比和振荡器执行周期的主要项目,即RTOS任务的执行周期,其中实例为放置振荡器。基于振荡周期和任务执行周期产生振荡器功能振荡
void OSC(uint32_t output, Osc_t *p){
// p->T is the task execution period in ms
// p->period is the desired oscillations period in ms
// p->counter is the internal state of the oscillator
p->delay_count = (uint16_t)((p->period)/(2*p->T));
if(++(p->counter) >= p->delay_count){
p->counter = 0;
NegLogicSignal(output);
}
}
}
下面是包含各个振荡器实例状态的结构
typedef struct{
float period; // period of the oscillations (ms)
float T; // function execution period (ms)
uint16_t counter; // initial number of execution periods
uint16_t delay_count; // number of execution periods corresponding to half
// period
}Osc_t;
以及振荡器功能的使用如下
Debug_LED_Oscillator_state.T = 1; // T = 1 ms
Debug_LED_Oscillator_state.period = 500; // period 0.5 s = 500 ms
OSC(LDbgLedOsc, &Debug_LED_Oscillator_state);
我的问题是我必须将我的一个振荡器置于最快的任务中(执行周期为1 ms的任务) 因为我无法在另一个任务中达到500毫秒(半周期250毫秒)的时间段,因为我的其余任务的执行周期为500毫秒(20毫秒和100毫秒,即250/20 = 12.5 - 不是整数值,250/100 = 2.5 - 也不是整数值)。问题是我将其余的应用程序逻辑放在另一个任务中。
预期用途是为LED闪烁模式产生逻辑信号。问题是我不得不将振荡器移动到逻辑上不同的任务,因为我无法在逻辑上适当的任务中实现所需的定时精度(因为商half_period / execution_period的非整数值)。我正在考虑不同的实现方式,它可以将振荡器置于逻辑上适当的任务并实现所需的时序精度。
我想过以下解决方案。我将定义一组全局变量(uint16_t Timer_1ms,uint16_t Timer_5ms等)。这些全局变量将在最高优先级任务中递增(在我的案例中为Task_1ms)。我将重新定义OSC功能
void OSC(uint32_t output, Osc_t *p){
float act_time;
taskENTER_CRITICAL();
switch(p->timer_type){
case TMR_1MS:
act_time = Timer_1ms;
break;
case TMR_5MS:
act_time = Timer_5ms;
break;
}
taskEXIT_CRITICAL();
if(p->init){
SetLogicSignal(output);
switch(p->timer_type){
case TMR_1MS:
p->delta = ((p->period)/(2*1*p->T));
break;
case TMR_5MS:
p->delta = ((p->period)/(2*5*p->T));
break;
}
p->stop_time = (act_time + p->delta);
p->init = FALSE;
}
if(act_time >= (p->stop_time)){
NegLogicSignal(output);
p->stop_time = (act_time + p->delta);
}
}
和振荡器结构
// oscillator state
typedef struct{
float period; // period of the oscillations (ms)
float T; // function execution period (ms)
float delta; // half_period in timer counts
float stop_time; // timer counts when to negate the output
BOOL init; // force initialization of the timer
timer_e timer_type;
}Osc_t;
我试过这个解决方案,似乎没有功能。有人知道为什么吗?提前感谢任何消化。
答案 0 :(得分:0)
当您使用软截止日期执行任务时,RTOS的线程非常有用。软截止日期意味着如果执行延迟,系统将不会失败。在你的情况下,振荡器有一个很难的截止日期,例如如果PWM的占空比不精确且稳定,则电动机将不具有所需的恒定角速度。在这种情况下,您必须使用MCU的可用定时器/计数器外设。
您可以设置定时器以在给定间隔内中断CPU并在ISR(中断服务程序)中切换输出。使用这种方法,时间计数的负载从CPU移动到定时器外围设备,允许精确的振荡输出和顺利执行其他任务。
您不清楚正在使用哪个RTOS或MCU / CPU,但它们都有定时器/计数器外设。如果不直接从RTOS支持,请查看CPU供应商数据表。