代码之家  ›  专栏  ›  技术社区  ›  HanClinto

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

  •  10
  • HanClinto  · 技术社区  · 16 年前

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

    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 }}}};
    

    这些嵌套的方括号可能有点让人困惑——对于如何在代码中保持一个漂亮的表,有人有更好的想法吗?

    谢谢

    通过合并每个人的输入(谢谢——我希望我能“接受”其中的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 ) ]
    

    我来试一试,看看结果如何。我还将用更有用的#定义替换0和1,这些定义表达了每个状态的含义,以及解释每行输出的输入的/**/注释。谢谢大家的帮助!

    7 回复  |  直到 16 年前
        1
  •  4
  •   Stephen Doyle    16 年前

    • 使用宏初始化每个“行”-这将在宏调用中隐藏大括号。
    • 使用注释分隔行。
    • 使用init函数显式初始化上下文-可能使用函数初始化每个部分。这与上面的第一个选项类似,但有一个缺点,即在使用状态机之前必须调用init函数。
        2
  •  3
  •   HUAGHAGUAH    16 年前

    如果填充行的算法很容易编码,那么可以定义一个宏来按索引号填充每一行。

        3
  •  3
  •   Ben    16 年前

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

    这也意味着,考虑到您使用的是C语言,您不必在每次决策表更改时都重新编译代码。

        4
  •  2
  •   Steven A. Lowe    16 年前

    1111,0000
    1110,0110
    ...
    

    对于数据压缩,将值表示为字节(两个Nybles)。。。

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

        5
  •  1
  •   Cameron Pope    16 年前

    如果真值表实际上只有4x4,那么我会使用宏。如果它能超越这个极限,我会用 Ragel . 它很可能会生成比您更小、更快的C代码。

        6
  •  1
  •   gbarry    16 年前

        7
  •  1
  •   rmeador    16 年前

    通常当你遇到这样的问题时,人们会试图把它简化成一个简单的布尔公式。我不明白为什么这不是最好的方法。它将更加紧凑,可读性更强,而且它可能更快(我认为少数and和OR将比查找表方法所需的乘法/移位+内存访问的集合执行得更快)。将此表简化为布尔公式的最简单方法是使用 K-Map