Как ограничить передачу управляемых прерываний UART PIC24H?

Я передаю данные со своего микроконтроллера PIC24H через UART 460 Кбод на радиомодуль Bluetooth. В большинстве случаев этот поток работает нормально, и модуль Bluetooth использует линии CTS и RTS для управления потоком, когда его внутренние буферы данных заполнены. Однако в модуле bluetooth есть какая-то ошибка, которая сбрасывает его, когда данные постоянно отправляются на него без каких-либо перерывов, что происходит, если мои данные копируются в другом узком месте.

Было бы хорошо, если бы модуль работал правильно, но это вне моего контроля. Таким образом, кажется, что мой единственный вариант - выполнить некоторое регулирование скорости передачи данных на моем конце, чтобы убедиться, что я не превышаю лимиты пропускной способности (которые я знаю примерно экспериментально).

Мой вопрос - как реализовать регулирование скорости передачи данных?

Моя текущая реализация UART представляет собой кольцевой буфер FIFO RAM длиной 1024 байта, в который основной цикл записывает данные. Периферийное прерывание запускается PIC, когда последний байт был отправлен оборудованием UART, и мой ISR считывает следующий байт из буфера и отправляет его на оборудование UART.

Вот идея исходного кода:

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

Edit
Я вижу два способа реализации дросселирования:

  1. Обеспечивает временную задержку между записываемым байтом UART, которая устанавливает верхний ограничение на пропускную способность данных.

  2. Сохраняйте текущий счет байтов, переданных за определенный период времени, и если максимальное количество байтов превышено для этого промежутка времени, создайте немного более длительную задержку перед продолжением передачи.

Теоретически будет работать любой вариант, это реализация, которая меня интересует.

8
задан CodeFusionMobile 11 July 2011 в 15:32
поделиться