在PIC32

时间:2018-04-04 05:16:50

标签: c embedded uart mplab pic32

我目前正在尝试通过UART接收中断协议解析通过UART从PIC32MZ2048EFG100微控制器上的GPS模块接收的字符串。我正在为我的IDE和编译器使用MPLAB X IDE v4.10和XC32 v2.05。

当我启用UART4接收中断时,!=运算符停止运行。我的main函数中有一段代码块,永远不应该执行,但它确实是。

我已将其缩小到允许中断成为问题。如果我在ISR中注释掉所有工作代码,我仍然面临myCounter增加的问题。

这是我在主要功能中的代码。

int myCounter = 0;

void main ( void ){

    hal_sys_init();
    hal_uart4_init();
    gps_init();

    //Setup interrupt
    asm volatile("di"); //Disable all interrupts
    asm volatile("ehb"); //Disable all interrupts

    INTCON = 0; //Clear interrupt control register

    IEC0 = 0;
    IEC1 = 0;
    IEC2 = 0;
    IEC3 = 0;
    IEC4 = 0;
    IEC5 = 0;
    IEC6 = 0;

    INTCONbits.MVEC = 1; //Enable multi-vectored interrupts

    IFS5bits.U4RXIF = 0; //Clear interrupt flag
    IPC42bits.U4RXIP = 1; //Set priority level to 7
    IPC42bits.U4RXIS = 0; //Set sub-priority to 0
    IEC5bits.U4RXIE = 1; //Enable interrupt

    asm volatile("ei"); //Enable all interrupts

    while(1){
        int x = 0;
        if(x != 0){
            myCounter++;  //Should never be executed
        }
    }
}

在启用了中断的PIC上运行此代码时,myCounter会增加。 myCounter has a value of 0x275 after running for a few seconds

这是我的中断服务程序的代码。

void __ISR(_UART4_RX_VECTOR, ipl7SRS) UART4_Interrupt(void) {
    while (U4STAbits.URXDA) {
        char c = U4RXREG;
        if (c == '\n') {
            currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string
            parseStringFlag = 1;
            lineIndex = 0;

            if (currentLine == buff_1) {
                currentLine = buff_2;
                previousLine = buff_1;
            } else {
                currentLine = buff_1;
                previousLine = buff_2;
            }

        } else if (lineIndex < MAX_LINE_LENGTH) {
            currentLine[lineIndex++] = c;
        } else {
            currentLine[--lineIndex] = c;
        }
    }
    IFS5bits.U4RXIF = 0; //Clear interrupt flag
    return;
}

这是仍然使myCounter增量的基本ISR代码。

void __ISR(_UART4_RX_VECTOR, ipl7SRS) UART4_Interrupt(void) {
    while (U4STAbits.URXDA) {
        char c = U4RXREG;
    }
    IFS5bits.U4RXIF = 0; //Clear interrupt flag
    return;
}

什么可能导致永远不应该执行的代码执行?如果我在main中运行中断代码并禁用中断,则代码可以工作,并且不会执行永不执行的代码。

1 个答案:

答案 0 :(得分:3)

下面:

    if (c == '\n') {
        currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string

如果收到的第一个字符为\nlineIndex初始化为零,则lineIndex将从零开始递减。假设它是未签名的,那么lineIndex < MAX_LINE_LENGTH将为false并且:

    } else {
        currentLine[--lineIndex] = c;
    }

将重复运行,直到lineIndex最终减少到MAX_LINE_LENGTH - 1 - 踩踏大量的内存 - 这很可能是在这种情况下发生的事情。

推荐:

    if( lineIndex != 0 && c == '\n' && ) 
    {
        currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for 

或:

    if( c == '\n' ) 
    {
        if( lineIndex != 0 ) 
        {
            lineindex-- ;
        }
        currentLine[lineIndex] = 0; //Overwrite /r as null terminator for 

取决于您需要的语义。发送系统使用CR + LF对作为行尾并不是给定的,你不应该假设这一点。在递减lineindex之前,可能应该进一步修改代码以检查前面的字符是否确实是CR。为读者练习。

同样对于最后的其他人:

    } 
    else if( lineIndex != 0 )
    {
        currentLine[--lineIndex] = c;
    }

    } 
    else
    {
        if( lineIndex != 0 ) 
        {
            lineindex-- ;
        }
        currentLine[lineIndex] = c;
    }

后一种保护可能不是必需的,但保护对于清晰度和维护也很有用 - 它是防御性代码 - 你的电话。

让ISR简单地将任何接收到的字符放入环形缓冲区,然后处理中断上下文之外的行输入,这可能是一种更安全,更中断的设计。您可以在每个收到的\n上递增计数器,并在\n未缓冲时递减计数器,以便接收器知道当前缓冲了多少行进行处理。

相关问题