代码之家  ›  专栏  ›  技术社区  ›  Chathuranga Chandrasekara

将数据发送到串行端口的最佳方式是什么?

  •  7
  • Chathuranga Chandrasekara  · 技术社区  · 14 年前

    1. 在微控制器中有一个模数转换器 位分辨率。(它将输出 值介于0和1023之间)

    2. 但你一次只能写8位。(需要写入字节)。它是 微控制器的一个限制。

    3. 所以在上面的例子中,至少我需要发送2个字节。

    4. 我的电脑应用程序只是读取一系列的数字进行绘图。所以 字节数,然后重新生成数字。但是 性格也一样。但是定界符字符的ascii值仍然在0-255之间,那么它将混淆进程。

    Ex : 1023 = "1""0""2""3" Vs "Char(255)Char(4)"
    

    总之,我需要以最快的方式通过串行发送一个由10位数字组成的序列。:)

    4 回复  |  直到 14 年前
        1
  •  15
  •   Nick Fortescue    14 年前

    你需要发送10位,因为你一次发送一个字节,你必须发送16位。最大的问题是速度有多重要,发送端和接收端的同步程度如何?根据这些条件,我可以想出3个答案。

    常规采样,未知连接点

    abcdefghij (每个字母一位)。

    我会派人 pq0abcde 然后 pq1fghij ,其中 p q error checking bits

    • 不需要分隔符(您可以通过0或1判断您正在读取的字节)
    • 你肯定能发现任何1位错误,所以你知道坏数据

    我正在努力寻找一个好的两位纠错码,所以我想我应该把p设为2,3和4位的奇偶校验位(0,a b以上)和qa设为56和7位的奇偶校验位(c,d,e以上)。举个例子也许会更清楚。

    1. 一分为二10110101010
    2. 添加位以指示第一和第二字节010110、101010
    3. 计算每一半的奇偶校验:p0=par(010)=1,q0=par(110)=0,p1=par(101)=0,q1=par(010)=1
    4. 字节是100101101101101010

    然后,您可以检测到许多不同的错误情况,如果失去同步,快速检查发送的是哪个字节,微控制器中的任何操作都不会花费很长时间(我将使用8项查找表进行奇偶校验)。

    如果您知道读卡器和写卡器同时启动,只需将4个10位值作为5个字节发送。如果你总是一次读5个字节,那就没问题了。如果您想节省更多的空间,并且已经有了很好的示例数据,我将使用 huffman coding

    密集数据,未知连接点

    在7字节中,您可以发送5个10位值和6个备用位。发送5个值,如下所示:

    • 字节0:0(7位)
    • 字节2:1(7位)
    • 字节3:1(7位)
    • 字节4:0(7位)
    • 字节6:(8位)

    然后每当你看到31在一行中最重要的一位,你就知道你有字节1,2和3。这个想法浪费了56位中的1位,因此可以使效率更高,但你必须一次发送更多的数据。例如(5个连续的,16字节中发送120位):

    • 字节0:0(7位)7
    • 字节1:1(7位)14
    • 字节3:1(7位)28
    • 字节4:1(7位)35
    • 字节5:1(7位)42
    • 字节6:0(7位)49
    • 字节7:(8位)57
    • 字节8:(8位)65
    • 字节9:(8位)73
    • 字节11:0(7位)88
    • 字节12:(8位)96
    • 字节13:(8位)104
    • 字节15:(8位)120

        2
  •  7
  •   Paul R    14 年前

    最好的方法是将数据转换成一个ASCII字符串并以这种方式发送它-这使得调试变得更加容易,并且避免了各种通信问题(某些控制字符的特殊含义等)。

    如果您确实需要使用所有可用带宽,那么您可以将4个10位值打包成5个连续的8位字节。你需要小心同步。

        3
  •  4
  •   Peer Stritzinger    14 年前

    因为您指定了“最快的方式”,所以我认为不可能将数字扩展到ASCII。

    在我看来,代码的简单性和性能的良好折衷可以通过以下编码获得:

    两个10位值将被编码成3个字节,如下所示。

    前10位值位:=abcdefghij

    第二个10位值位:=klmnopqrst

    要编码的字节:

    1abcdefg
    0hijklmn
    0_opqrst
    

    还有一个位(u)可用于校验所有20位上的奇偶校验以进行错误检查,或仅设置为固定值。

    #include <assert.h>
    #include <inttypes.h>
    
    void
    write_byte(uint8_t byte);    /* writes byte to serial */
    
    void
    encode(uint16_t a, uint16_t b)
    {
      write_byte(((a >> 3) & 0x7f) | 0x80);
      write_byte(((a & 3) << 4) | ((b >> 6) & 0x7f));
      write_byte(b & 0x3f);
    }
    
    uint8_t
    read_byte(void);  /* read a byte from serial */
    
    void
    decode(uint16_t *a, uint16_t *b)
    {
      uint16_t x;
    
      while (((x = read_byte()) & 0x80) == 0)  {}  /* sync */
      *a = x << 3;
    
      x = read_byte();
      assert ((x & 0x80) == 0); /* put better error handling here */
    
      *a |= (x >> 4) & 3;
      *b = x << 6;
    
      x = read_byte();
      assert ((x & 0xc0) == 0); /* put better error handling here */
    
      *b |= x;
    }
    
        4
  •  0
  •   old_timer    14 年前

    我通常使用一个起始字节和校验和,在这种情况下是固定长度的,所以发送4个字节,接收者可以寻找起始字节,如果接下来的3个字节加起来是一个已知的数量,那么它是一个很好的包,取出中间的2个字节,如果不继续寻找的话。接收器总是可以重新同步,而且不会浪费ascii的带宽。Ascii是另一个选项,它是一个起始字节,不是数字,可能是十进制的四个数字。十进制在微控制器中肯定不好玩,所以以一些非十六进制的例如X开始,然后用十六进制ascii值作为数字的三个字节。搜索x检查下三个字节,希望最好。