如何根据C中的状态机生成单个脉冲?

Posted

技术标签:

【中文标题】如何根据C中的状态机生成单个脉冲?【英文标题】:How to gererate a single pulse depending on a state machne in C? 【发布时间】:2017-12-28 10:32:00 【问题描述】:

我想编写一个 c 代码来生成一个脉冲,但我似乎无法围绕逻辑来实现它。我来自强大的 Verilog 背景并且知道如何在 verilog 中执行此操作(使用 xor 查找状态变化并使用该脉冲,如果需要,通过多次注册它随着时间的推移拉伸它)

我应该如何在 C 中做到这一点?我想做类似的事情

while(1)

   switch(state)
   case 0: // generate single pulse
   case 1: // dont generate 
   case 2: // dont gererate
   case 3: // generate single pulse
   usleep(1000) // I want a 1ms pulse
  

状态由运行在 FPGA 上的代码修改,因此它会根据某些逻辑而改变。 似乎无法做到这一点。一些指导将不胜感激

【问题讨论】:

"pulse" 是什么意思?什么样的“脉冲”。想要脉搏什么? 您可以在一个循环中切换为高电平,然后在下一个循环中切换为低电平,例如通过使用状态 4“脉冲”。 单脉冲作为默认低电平的信号,但当某些情况发生时,高电平和低电平时间 = 说 1 毫秒 @Yunnosch 我尝试了类似“if(signal=0) signal =1; else signal = 0”的方法,但只要该状态稳定,就会产生多个脉冲 您需要提供更多上下文。使用您显示的代码,“进入操作”之类的东西是不可能的。请尝试提供更接近minimal reproducible example 的内容。朝着合适的强大状态机迈出的一步是维护一个“statebefore”变量。 【参考方案1】:

你需要一个稍微强大一点的状态机,它可以执行进入操作。

假设

状态机在脉冲时失明是可以的 变量 state 在您的循环内发生变化(例如,可能是易失性的并且可能从 ISR 更新) 或状态在循环内以某种方式更新(存在伪代码)

您在聊天中表示您可以控制变量 state 何时更改。这很重要。要么使用从伪代码行调用的轮询函数updatestate();或者以某种方式确保变量不会在 // enter protection ...// leave protection ... 之间发生变化。 但是,状态机仍会因之间的更改而失明,尤其是在usleep(1000); 期间。如果这是一个问题,您需要明显更复杂的机制。

伪代码提案:

// somewhere before
volatile int state = 0; // somehow changing within the loop 

int statecopy = 0;  
int statebefore = state,

while(1)

    // updatestate(); // if that is necessary

    // Note that the state machine is blind for changes to state
    // between executions of these initial lines.
    // I.e. changes are noticed only when executing the update above
    // or the critical section below this comment. (depending on how
    // the variable state changes.

    // enter protection for critical section
    statebefore = statecopy;
    statecopy   = state;
    // leave protection for critical section

    switch(statecopy )
    
        case 0: // generate single pulse
            if (statecopy != statebefore)
            
                // switch high
                usleep(1000); // I want a 1ms pulse
                // switch low
            
            break;
        case 1: // dont generate 
            break;
        case 2: // dont gererate
            break;
        case 3: // generate single pulse
            if (statecopy != statebefore)
            
                // switch high
                usleep(1000); // I want a 1ms pulse
                // switch low
            
            break;
        default:
            break;
    

【讨论】:

【参考方案2】:

您只需要为每个状态的状态更改和操作实现少量逻辑,如下所示:

int state = 0;
while(1) 
  switch(state) 
    case 0: // generate single pulse
       start_pulse();
       usleep(1000);
       stop_pulse();
       break;
    case 1: // dont generate , wait 1ms?
       usleep(1000);
       break;
    case 2: // dont generate, wait 1ms?
       usleep(1000);
       break;
    case 3: // generate single pulse
       start_pulse();
       usleep(1000);
       stop_pulse();
       break;
  
  state = (state+1)%3; // next state: 0, 1, 2, 3, 0, 1, 2,...
 

【讨论】:

【参考方案3】:

为了简化开关示例

switch( state ) 
case 1:
case 2:
  usleep(1000);
  break;
case 0:
case 3:
  /* pulse high */
  usleep(1000);
  /* pulse low */

更多是可能的,但可能不值得,让编译器弄清楚。

【讨论】:

以上是关于如何根据C中的状态机生成单个脉冲?的主要内容,如果未能解决你的问题,请参考以下文章

React 状态机

C函数指针状态机实现

Unity/C#:如何在动画状态机中禁用组件

用状态机表示SFC中的并行分支

UML之状态机图

如何在反应中保持 Xstate 状态机中的状态?