首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何节流中断驱动的UART传输PIC24H?

如何节流中断驱动的UART传输PIC24H?
EN

Stack Overflow用户
提问于 2011-07-06 21:02:40
回答 4查看 2.6K关注 0票数 8

我正在传输数据从我的PIC24H单片机超过460 module UART到一个蓝牙无线电模块。在大多数情况下,这个流程工作得很好,蓝牙模块使用CTS和RTS线来管理内部数据缓冲区已满时的流控制。然而,在蓝牙模块中有一个bug,当数据连续发送到蓝牙模块时,它会重新设置它,而不会中断,如果我的数据被备份到另一个瓶颈中,就会发生这种情况。

如果模块正常工作,那就太好了,但这是我无法控制的。因此,我的唯一选择似乎是在我的终端上做一些数据节流,以确保我不超过数据吞吐量限制(我通过实验大致知道这一点)。

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

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

下面是源代码的一个想法:

uart_isr.c

代码语言:javascript
运行
复制
//*************** 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

代码语言:javascript
运行
复制
//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];
    }
}

编辑

在我看来,有两种方法可以实现节流:

  1. 在要写入的UART字节之间强制执行时间延迟,这对数据吞吐量设置了上限。
  2. 保持在特定时间范围内传输的字节的运行记录,如果超过该时间段的最大字节数,则在继续传输之前创建一个稍长的延迟。

从理论上讲,这两种方法都是可行的,这就是我想知道的实现方法。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-07-12 06:38:03

也许配额制就是你想要的。使用相关时间刻度的周期性中断,将“要传输的字节”的配额添加到全局变量中,这样就不会超过相应的洪流调整后的某个级别。然后,只需检查是否有配额,然后您来发送一个字节。在新的传输方式下,将有一个最初的洪水,但稍后配额将限制传输速率。

代码语言:javascript
运行
复制
~~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
票数 3
EN

Stack Overflow用户

发布于 2011-07-06 21:13:54

如果您有一个空闲的计时器,或者您可以使用一个现有的计时器,您可以对发送的字节进行某种类型的“删除”。

假设您有这个全局变量,byte_interval,并且每微秒都有一个计时器溢出(并触发ISR)。它看起来可能是这样的:

代码语言:javascript
运行
复制
timer_usec_isr() {
    // other stuff
    if (byte_interval)
        byte_interval--;
}

然后在"putchar“函数中,您可以得到如下内容:

代码语言:javascript
运行
复制
uart_send_byte(unsigned char b) {
    if (!byte_interval) { // this could be a while too, 
                          // depends on how you want to structure the code
        //code to send the byte
        byte_interval = AMOUNT_OF_USECS;
    }

}

很抱歉,我没有仔细研究你的代码,所以我可以说得更具体一些。这只是个主意,我不知道它是否适合你。

票数 2
EN

Stack Overflow用户

发布于 2011-07-11 15:44:52

首先,有两种常用的串行流控制。

  • CTS/RTS握手 (硬件流控制)
  • XON/XOFF (“软件流控制”)

您说CTS是开着的,但是您可能想看看是否可以以某种方式启用XON/XOFF。

另一种方法,如果你可以配置它是简单地使用一个较低的波特率。这显然取决于您可以在链接的另一端配置什么,但是当设备无法处理更高的速度传输时,这通常是解决问题的最简单方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6602933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档