首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >修正UART溢出

修正UART溢出
EN

Stack Overflow用户
提问于 2015-09-18 10:28:59
回答 1查看 1.7K关注 0票数 0

我有一个GSM模块与我的微控制器通过硬件UART交谈。当我收到小数据时,一切都正常。当我试图获取存储在SIM卡中的所有SMS消息的列表时,我会得到UART缓冲区溢出错误。

我有一个动态字符串函数,它在使用malloc的缓冲区中追加每个接收到的字符。我就是这样接受的。我把引起问题的那一行评论掉了。

代码语言:javascript
运行
复制
while( uart_available() > 0 )
    {
        /*
         *  There are characters in the buffer so
         *  keep receiving until buffer in empty.
         */
        unsigned int c = uart_getc();

        if ( c & UART_NO_DATA )
        {
            /*
             * No data available from UART. This is not an error.
             */
            error( AT, "No error but - No uart data" );// TODO: Delete it. It is not an error actually.
        }
        else if ( c & UART_FRAME_ERROR )
        {
            /* Framing Error detected, i.e no stop bit detected */
            errorOccured( ER_UART_FRAME_ERROR );
            error( AT, "Frame error" );
        }
        else if ( c & UART_OVERRUN_ERROR )
        {
            /* 
             * Overrun, a character already present in the UART UDR register was 
             * not read by the interrupt handler before the next character arrived,
             * one or more received characters have been dropped.
             */
            errorOccured( ER_UART_OVERRUN_ERROR );
            error( AT, "Overrun error" );
        }
        else if ( c & UART_BUFFER_OVERFLOW )
        {
            /* 
             * We are not reading the receive buffer fast enough,
             * one or more received characters have been dropped.
             */
            errorOccured( ER_UART_BUFFER_OVERFLOW );
            error( AT, "Buffer overflow error" );
        }
        else
        {
            /*
             * There are data available add them to cString.
             */
            appendChar( data, (const char)c );// This line is slow and causes UART overflow.
            if ( *data == 0 )
            {
                /*
                 * Report bad pointer.
                 */
                errorOccured( ER_SIM900_BAD_POINTER );
                error( AT, "Bad pointer" );
            }

            /*
             * We received something so change the flag
             * even if an error occurs in the next loop.
             */
            isReceivedData = true;
        }
    }

我想问你们,你们是否知道malloc是慢的,或者你是否知道UART被UART中断了,接收中断是个问题。如何在不提高时钟速度的情况下不降低UART比特率来解决这一问题?

更新:

调试之后,我确定malloc正在工作(如果malloc失败了,我会得到一个断言),所以我的下一个猜测是appendChar是慢的。虽然只用于阅读SMS,但我会尝试使用Mateo建议的固定字符数组,每次使用一个SMS (每个SMS最多160个字符+发件人信息)。

更新2-新代码

我成功了,但我幸运地做到了。代码中有一行代码,我不明白为什么需要它。我有8 8Mhz和19200 UART比特率。我想时机有点问题。

如果我移除函数,这一行就不能工作:

代码语言:javascript
运行
复制
_delay_us(150); // TODO: WEIRD KNOWN BUG!!!

在这里,整个功能:

代码语言:javascript
运行
复制
/**
 * @brief   Receives raw data from SIM900.
 *
 * @param   data    Get SIM900's raw data on exit.
 *
 * @return  True if at least one character received.
 */
bool SIM900_receive( cString* data )
{
    /*
     * Because we append chars we need to init it.
     */
    #define SIM900_MAX_RECEIVE_CHARACTERS 300
    char temp[SIM900_MAX_RECEIVE_CHARACTERS+1];
    strcpy_P( temp, PSTR("") );
    int32_t i = 0;

    /*
     * There are no received data so far.
     */
    bool isReceivedData = false;

    /*
     * Check UART buffer
     */
    while( uart_available() > 0 )
    {
        /*
         *  There are characters in the buffer so
         *  keep receiving until buffer in empty.
         */
        unsigned int c = uart_getc();
        _delay_us(150); // TODO: WEIRD KNOWN BUG!!!

        if ( c & UART_NO_DATA )
        {
            /*
             * No data available from UART. This is not an error.
             */
            error( AT, "No error but - No uart data" );// TODO: Delete it. It is not an error actually.
        }
        else if ( c & UART_FRAME_ERROR )
        {
            /* Framing Error detected, i.e no stop bit detected */
            errorOccured( ER_UART_FRAME_ERROR );
            error( AT, "Frame error" );
        }
        else if ( c & UART_OVERRUN_ERROR )
        {
            /* 
             * Overrun, a character already present in the UART UDR register was 
             * not read by the interrupt handler before the next character arrived,
             * one or more received characters have been dropped.
             */
            errorOccured( ER_UART_OVERRUN_ERROR );
            error( AT, "Overrun error" );
        }
        else if ( c & UART_BUFFER_OVERFLOW )
        {
            /* 
             * We are not reading the receive buffer fast enough,
             * one or more received characters have been dropped.
             */
            errorOccured( ER_UART_BUFFER_OVERFLOW );
            error( AT, "Buffer overflow error" );
        }
        else
        {
            /*
             * There are data available add them to cString.
             */
            if( i<SIM900_MAX_RECEIVE_CHARACTERS )
            {
                temp[i] = (char) c;
                temp[i+1] = '\0';
                i++;
            }

            /*
             * We received something so change the flag
             * even if an error occurs in the next loop.
             */
            isReceivedData = true;
        }
    }

    copyString( data, temp );

    /*
     * Exit.
     */
    return isReceivedData;
}
EN

回答 1

Stack Overflow用户

发布于 2015-09-18 11:31:23

阅读基于堆的动态内存分配是如何工作的;这太宽泛了,无法解释。它的运行时是不确定的,它可能会导致堆的碎片,因此在一段时间后,您最终将不会得到任何块。

你还在印些我猜的东西。这也可能是个问题。总之:不要使用(可能)运行时间超过实时场景中可接受的运行时间的函数( UART接收器规定处理时间的上限)。

使用足够长的缓冲区来获得最大值。包的大小。无论如何,如果您坚持使用线性处理序列,那么您必须为这种情况做好准备。

一种更好的方法是使用中断来增强数据。这样,您可以使用两个交替缓冲区(每个最大)。并在正常代码中处理一个缓冲区,同时通过中断处理程序接收下一个缓冲区。

注意:除非你真的必须考虑了所有的含义,否则不要进行强制转换。通常情况下,转换是接口设计不良的信号。

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

https://stackoverflow.com/questions/32649762

复制
相关文章

相似问题

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