我正在通过460Kbaud UART将数据从PIC24H微 Controller 传输到蓝牙 radio 模块。在大多数情况下,此流工作正常,并且蓝牙模块在内部数据缓冲区已满时使用CTS和RTS线来管理流控制。但是,蓝牙模块中存在某种错误,可在不间断地将数据连续发送到蓝牙模块时将其重置,如果我的数据在另一个瓶颈中备份,则会发生这种错误。

如果模块正常工作会很好,但是那是我无法控制的。因此,看来我唯一的选择是在最后进行一些数据限制,以确保不超出数据吞吐量限制(我通过实验大致了解了这一点)。

我的问题是如何实现数据速率调节?

我当前的UART实现是一个RAM循环FIFO缓冲区,该缓冲区长1024个字节,主循环将数据写入该缓冲区。当UART硬件发送完最后一个字节并且我的ISR从缓冲区读取下一个字节并将其发送到UART硬件时,PIC将触发外设中断。

这是源代码的一个想法:

uart_isr.c

//*************** Interrupt Service routine for UART2 Transmission
void __attribute__ ((interrupt,no_auto_psv)) _U2TXInterrupt(void)
{
//the UART2 Tx Buffer is empty (!UART_TX_BUF_FULL()), fill it
//Only if data exists in data buffer (!isTxBufEmpty())
while(!isTxBufEmpty()&& !UART_TX_BUF_FULL())    {
    if(BT_CONNECTED)
    {   //Transmit next byte of data
        U2TXREG = 0xFF & (unsigned int)txbuf[txReadPtr];
        txReadPtr = (txReadPtr + 1) % TX_BUFFER_SIZE;
    }else{
        break;
    }
}
IFS1bits.U2TXIF = 0;
}

uart_methods.c
//return false if buffer overrun
BOOL writeStrUART(WORD length, BYTE* writePtr)
{
    BOOL overrun = TRUE;
    while(length)
    {
        txbuf[txWritePtr] = *(writePtr);
        //increment writePtr
        txWritePtr = (txWritePtr + 1) % TX_BUFFER_SIZE;
        if(txWritePtr == txReadPtr)
        {
            //write pointer has caught up to read, increment read ptr
            txReadPtr = (txReadPtr + 1) % TX_BUFFER_SIZE;
            //Set overrun flag to FALSE
            overrun = FALSE;
        }

        writePtr++;
        length--;
    }

    //Make sure that Data is being transmitted
    ensureTxCycleStarted();

    return overrun;
}


void ensureTxCycleStarted()
{
    WORD oldPtr = 0;
    if(IS_UART_TX_IDLE() && !isTxBufEmpty())
    {
        //write one byte to start UART transmit cycle
        oldPtr = txReadPtr;
        txReadPtr = (txReadPtr + 1) % TX_BUFFER_SIZE;//Preincrement pointer
        //Note: if pointer is incremented after U2TXREG write,
        //      the interrupt will trigger before the increment
        //      and the first piece of data will be retransmitted.
        U2TXREG = 0xFF & (unsigned int)txbuf[oldPtr];
    }
}

编辑
如我所见,有两种方法可以实现节流:
  • 强制要写入的UART字节之间存在时间延迟,这会导致数据吞吐量的上限。
  • 保持在一定时间范围内传输的字节的连续计数,如果超过该时间段的最大字节数,则在继续传输之前会创建稍长的延迟。

  • 从理论上讲,这两种方法都可以使用,我想知道的是它的实现。

    最佳答案

    也许您需要配额方法。
    使用相关时间范围的周期性中断,将“要传输的字节”配额添加到全局变量,以至于您不会超过为相关的洪水调整的某个级别。
    然后只需检查是否有配额,然后再发送字节。在新的传输中,将出现最初的洪水,但随后的配额将限制传输速率。

    ~~some periodic interrupt
    if(bytes_to_send < MAX_LEVEL){
      bytes_to_send = bytes_to_send + BYTES_PER_PERIOD;
      }
    ~~in uart_send_byte
    if(bytes_to_send){
      bytes_to_send = bytes_to_send - 1;
      //then send the byte
    

    10-08 13:49
    查看更多