在 PIC32 上启用中断时,不等于运算符不工作
Not Equals Operator not working when interrupts are enabled on PIC32
我目前正在尝试通过 UART 接收中断协议解析通过 UART 从 PIC32MZ2048EFG100 微控制器上的 GPS 模块接收到的字符串。我正在为我的 IDE 和编译器使用 MPLAB X IDE v4.10 和 XC32 v2.05。
当我启用 UART4 接收中断时,!= 运算符停止正常运行。我的主函数中有一段代码永远不会执行,但它确实执行了。
我已将问题范围缩小到启用中断。如果我注释掉 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 中的中断代码禁用了中断,则代码可以工作,并且不执行不应执行的代码。
这里:
if (c == '\n') {
currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string
如果收到的第一个字符是\n
并且lineIndex
初始化为零,lineIndex
将从零开始递减。假设它是无符号的,那么 lineIndex < MAX_LINE_LENGTH
将为假并且:
} 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
取决于您需要的语义。发送系统对 line-ends 使用 CR+LF 对并不确定,您不应该这样假设。可能应该进一步修改代码以在递减 lineindex
之前检查前面的字符是否确实是 CR。 reader.
的练习
最后的 else 也类似:
}
else if( lineIndex != 0 )
{
currentLine[--lineIndex] = c;
}
或
}
else
{
if( lineIndex != 0 )
{
lineindex-- ;
}
currentLine[lineIndex] = c;
}
后一种保护可能不是必需的,但保护可能对清晰度和维护很有用 - 它是防御代码 - 你的决定。
让 ISR 简单地将任何接收到的字符放入 ring-buffer,然后在中断上下文之外处理 line-input 可能是一种更安全、更高效的中断设计。您可以在收到的每个 \n
上增加一个计数器,并在 \n
未缓冲时减少它,以便接收者知道当前有多少行被缓冲以进行处理。
我目前正在尝试通过 UART 接收中断协议解析通过 UART 从 PIC32MZ2048EFG100 微控制器上的 GPS 模块接收到的字符串。我正在为我的 IDE 和编译器使用 MPLAB X IDE v4.10 和 XC32 v2.05。
当我启用 UART4 接收中断时,!= 运算符停止正常运行。我的主函数中有一段代码永远不会执行,但它确实执行了。
我已将问题范围缩小到启用中断。如果我注释掉 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 中的中断代码禁用了中断,则代码可以工作,并且不执行不应执行的代码。
这里:
if (c == '\n') {
currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string
如果收到的第一个字符是\n
并且lineIndex
初始化为零,lineIndex
将从零开始递减。假设它是无符号的,那么 lineIndex < MAX_LINE_LENGTH
将为假并且:
} 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
取决于您需要的语义。发送系统对 line-ends 使用 CR+LF 对并不确定,您不应该这样假设。可能应该进一步修改代码以在递减 lineindex
之前检查前面的字符是否确实是 CR。 reader.
最后的 else 也类似:
}
else if( lineIndex != 0 )
{
currentLine[--lineIndex] = c;
}
或
}
else
{
if( lineIndex != 0 )
{
lineindex-- ;
}
currentLine[lineIndex] = c;
}
后一种保护可能不是必需的,但保护可能对清晰度和维护很有用 - 它是防御代码 - 你的决定。
让 ISR 简单地将任何接收到的字符放入 ring-buffer,然后在中断上下文之外处理 line-input 可能是一种更安全、更高效的中断设计。您可以在收到的每个 \n
上增加一个计数器,并在 \n
未缓冲时减少它,以便接收者知道当前有多少行被缓冲以进行处理。