代码中的真值表?如何构建状态机?

时间:2009-03-02 16:43:08

标签: c state-machine truthtable

我有一个(有点)大的真值表/状态机,我需要在我的代码中实现(嵌入式C)。我预计这个状态机的行为规范将来会发生变化,所以我希望将来可以很容易地修改它。

我的真值表有4个输入和4个输出。我已经在Excel电子表格中完成了所有工作,如果我可以通过一点格式将其粘贴到我的代码中,那将是理想的。

我以为我想这样访问我的真值表:

u8 newState[] = decisionTable[input1][input2][input3][input4];

然后我可以通过以下方式访问输出值:

setOutputPin( LINE_0, newState[0] );
setOutputPin( LINE_1, newState[1] );
setOutputPin( LINE_2, newState[2] );
setOutputPin( LINE_3, newState[3] );

但是为了达到这个目的,看起来我必须像这样做一个相当令人困惑的表:

static u8 decisionTable[][][][][] =
 {{{{ 0, 0, 0, 0 },
    { 0, 0, 0, 0 }},
   {{ 0, 0, 0, 0 },
    { 0, 0, 0, 0 }}},
  {{{ 0, 0, 1, 1 },
    { 0, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}}},
 {{{{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}},
  {{{ 0, 1, 1, 1 },
    { 0, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}}};

那些嵌套的括号可能有些令人困惑 - 是否有人能更好地了解如何在我的代码中保留漂亮的表格?

谢谢!

根据HUAGHAGUAH的回答进行编辑:

使用每个人输入的合并(谢谢 - 我希望我能“接受”这些答案中的3个或4个),我想我会尝试将其作为二维数组。我将使用一个小的位移宏来索引我的数组:

#define SM_INPUTS( in0, in1, in2, in3 ) ((in0 << 0) | (in1 << 1) | (in2 << 2) | (in3 << 3))

这会让我的真值表数组看起来像这样:

static u8 decisionTable[][] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }};
然后我可以这样访问我的真值表:

decisionTable[ SM_INPUTS( line1, line2, line3, line4 ) ]

我会试一试,看看它是如何运作的。我还将用更有用的#defines代替0和1来表示每个状态的含义,以及解释每行输出的输入的/ ** /注释。感谢大家的帮助!

7 个答案:

答案 0 :(得分:4)

我建议(首选首选方法):

  • 使用宏来初始化每个“行” - 这将隐藏宏调用中的大括号。
  • 使用注释来分解行。
  • 使用init函数显式初始化上下文 - 也许使用函数初始化每个部分。这类似于上面的第一个选项,但缺点是必须在使用状态机之前调用init函数。

答案 1 :(得分:3)

就个人而言,我是从配置文件中读取的。也许,CSV很容易从Excel导出。或者您可以只从Excel复制并粘贴到纯文本中,这样就可以获得以空格分隔的值,同样易于导入。

这也意味着,假设您正在使用C,那么每次决策表更改时都不必重新编译代码。

答案 2 :(得分:3)

不需要多维表。用4位=&gt; 4位映射,您可以将单个u8 [16]阵列映射输入到输出。状态查找将更便宜,您可以使用一些移位和掩码操作来提取单个位。

如果填充行的算法很容易编纂,你可以#define一个宏来按索引号填充每一行。

答案 3 :(得分:2)

如果你的真值表都是布尔值,你可以把它折叠成一对列表,例如。

1111,0000
1110,0110
...

用于数据压缩,将值表示为字节(两个nybbles)......

在特定的嵌入式系统配置中,如何/如何存储它以进行软编码,只有你可以说; - )

答案 4 :(得分:1)

如果真值表真的只有4x4x4x4那么我会使用宏。如果它能够超越它,我会使用Ragel。有可能会制作比你更小,更快的C代码。

答案 5 :(得分:1)

我没有看到任何对当前状态的引用以获得输出状态。这意味着它不是状态机,而只是一个真值表。有四个输入,因此只有16种可能的输入组合。因此,有16个职位的表应该这样做。

答案 6 :(得分:1)

通常当你遇到这样的问题时,会尝试将其简化为一个简单的布尔公式。我不明白为什么这不是最好的方法。它会更紧凑,更易读,而且它有可能更快(我想一些AND和OR的执行速度比查找表方法所需的乘法/移位+内存访问的集合更快)。将此表格缩减为布尔公式的最简单方法是使用K-Map