gpt4 book ai didi

c - C 中振荡器的软件实现

转载 作者:太空宇宙 更新时间:2023-11-04 00:00:48 25 4
gpt4 key购买 nike

我一直在用C语言开发一个控制软件。我决定花一些时间开发通用功能 block ,可用于我将来开发的其他程序(某种类型的库)。我的软件从应用的角度分为两个主要部分。一部分是控制部分(PI Controller 、调制器、锁相环等)第二个是逻辑部分(应用程序的有限状态机等)。逻辑部分使用逻辑信号。这些信号由逻辑门和触发器的软件实现处理。我的目标也是实现振荡器的某些软件版本。我的意思是一些功能 block 能够在其输出端以规定的周期和占空比产生 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 毫秒的任务)因为我无法在另一个任务中达到 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;

我试过这个解决方案,但似乎不起作用。有人知道为什么吗?提前感谢您的任何建议。

最佳答案

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

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

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

关于c - C 中振荡器的软件实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45717653/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com