我目前正在尝试通过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会增加。
这是我的中断服务程序的代码。
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中运行中断代码并禁用中断,则代码可以工作,并且不会执行永不执行的代码。
答案 0 :(得分:3)
下面:
if (c == '\n') {
currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string
如果收到的第一个字符为\n
且lineIndex
初始化为零,则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
未缓冲时递减计数器,以便接收器知道当前缓冲了多少行进行处理。