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

嵌入式C计数器中的FIFO队列是否会溢出?

  •  1
  • Fua  · 技术社区  · 8 年前

    所以我正在阅读一本关于实时操作系统的教科书,其中有一节讨论了FIFO队列。我想实现书中提供的UART设备代码。我查看了代码,发现代码中的计数器没有重置。计数器是32位的,所以它们可以达到2^32,但是如果它们要在超过该值的设备中实现呢? 如果计数器溢出,它们是否会环绕并继续作为计数器正常工作?

    #include <stdint.h>
    
    #define Size 32 //temporary value. It can be any value 2^n
    
    uint32_t volatile TxPutI;//Counter 1
    uint32_t volatile TxGetI;//Counter 2
    static char TxFifo[size];
    void TxFifo_Init(void)
    {
        TxPutI = TxGetI = 0;
    }
    int TxFifo_Put(char data)
    {
        if( (TxPutI - TxGetI)&~(Size-1) )
            return 0;
        TxFifo[TxPutI&(Size-1)] = data;
        TxPutI++; //it can overflow
        return 1;
    }
    int TxFifo_Get(char *datapt)
    {
        if( TxPutI == TxGetI )
            return 0;
        *datapt = TxFifo[TxGetI & (Size-1)];
        TxGetI++; //it can overflow
        return 1;
    }
    uint16_t TxFifo_Size(void) //If someone can explain how this work, that'd be awesome!
    {
        return( (uint16_t)(TxPutI - TxGetI) );
    }
    

    书中的一个特殊条件是值大小必须为2^n。这个条件是否可以防止计数器导致不正确的索引?非常感谢。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Doug Currie    8 年前

    这些计数器是否溢出无关紧要。由于无符号算术的特性,该算术“只起作用”。当取差分时,运算从未表示的高位进行“借用”,结果的低位是正确的。因为差异必须远小于类型的最大值 uint32_t 差分的高位始终为零。

    下面是一个使用 uint8_t 以避免出现大量数据。我们将使用 uint8\u t getI 和 putI 变量和大小为16的FIFO。 格蒂 和 普蒂 格蒂 is 254和 普蒂 是7(由于溢出,263-256)。在无符号算术中,7-254是9。学习一些例子!

    在给定的实现中,FIFO的大小也必须是二的幂,因为按位用于模运算,这是测试FIFO是否已满的可爱技巧。