C

时间:2017-08-16 15:31:54

标签: c

我一直在用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;

我试过这个解决方案,似乎没有功能。有人知道为什么吗?提前感谢任何消化。

1 个答案:

答案 0 :(得分:0)

当您使用软截止日期执行任务时,RTOS的线程非常有用。软截止日期意味着如果执行延迟,系统将不会失败。在你的情况下,振荡器有一个很难的截止日期,例如如果PWM的占空比不精确且稳定,则电动机将不具有所需的恒定角速度。在这种情况下,您必须使用MCU的可用定时器/计数器外设。

您可以设置定时器以在给定间隔内中断CPU并在ISR(中断服务程序)中切换输出。使用这种方法,时间计数的负载从CPU移动到定时器外围设备,允许精确的振荡输出和顺利执行其他任务。

您不清楚正在使用哪个RTOS或MCU / CPU,但它们都有定时器/计数器外设。如果不直接从RTOS支持,请查看CPU供应商数据表。