This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR2355:exit.c --永远循环----???

Guru**** 2538950 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/905545/msp430fr2355-exit-c----forever-loop---

器件型号:MSP430FR2355

我有一个函数(见下文),不管我尝试什么(timer3或 UCRXIFG 检查),我最终会进入一个永远的循环,而这一循环不会回到状态机的响应部分...有人能告诉我缺少什么吗??

#include 
#include 
#include 
#include "rc.h"
#include "LPRSnot.h"

char* radioReg (char * p){

字符 f;
放射性状态;
const char * configAck ="ack";
字符响应[10]={0};
char *pResponse;
uint8_t 长度;

长度= strlen (p);
状态= CMD;
pResponse =响应;
/*
*将无线电命令分类为3个单元中的1个
*
如果(*(p +(length - 2))="T")||(*(p +(length - 3))='N')||(*(p +(length - 3))='L'))
f = 2;
否则、如果(*(p +(length - 1))='?')
f = 1;
其他
f = 0;

while (state!= done){
开关(状态){
案例 CMD:
TX = T;ACK = F;
UCA1TXBUF =(* p);
UCA1IE |= UCTXIE;
_bis_SR_register (LPM3_bits + GIE);
*(p++);
如果(*p ='\0'){
UCA1IE &=~UCTXIE;
if ((f ==2)||(f ==0))
STATE =回波;
其他
状态=响应;
}
中断;
外壳回波:
TX = F;ACK = F;
if (howMany < length)
_bis_SR_register (LPM3_bits + GIE);
否则{
howMany = 0;
P = CONFIGACK;
PRx =传入;
状态= ACK;
}
中断;
案例 ACK:
TX = T;ACK = T;
UCA1TXBUF =(* p);
UCA1IE |= UCTXIE;
_bis_SR_register (LPM3_bits);
*(p++);
如果(*p ='\0'){
UCA1IE &=~UCTXIE;
P =*(configCmd);
如果(f = 0){
状态=完成;
}
否则{
状态=响应;
}
/*
*让 Rx 有机会进行响应
* RESPONSE...最长的响应是17个字符
*在19200波特或8.85ms +大约3.5ms 时
* ACK 后的延迟=~12.5ms...定时器置1
以在20ms 后唤醒
*/
// _bis_SR_register (LPM3_bits);
}
中断;
案例响应:
TX = F;ACK = F;
memset (传入、0、20);
TB3CTL |= MC__UP;
TB3CCTL0 |= CCIE;
if ((!timerExpired)){//(UCA1IFG & UCRXIFG)
_bis_SR_register (LPM3_bits);
}
否则{
PRx =传入;
howMany = 0;
memcpy (响应、传入、sizeof (传入));
状态=完成;
}
中断;
案例完成:
中断;
默认值:break;
}
}
返回 pResponse
;}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    TIMER3_A0_Vector 是否设置 timerExpired = 1?  timerExpired 是否声明为"volatile"?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是和是

    ISR

    #pragma vector=USCI_A1_vector //无线电通信
    __interrupt void RF_ISR (void)
    {
    switch (__evo_in_range (UCA1IV、USCI_UART_UCTXCPTIFG))
    {
    USCI_NONE 案例:中断;
    USCI_UART_UCRXIFG 案例:
    如果(!TX){
    * prx = UCA1RXBUF;
    howMany ++;
    prx++;
    _BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);
    }
    中断;
    USCI_UART_UCTXIFG 案例:
    IF (TX)
    _BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);
    中断;
    案例 USCI_UART_UCSTTIFG:中断;
    案例 USCI_UART_UCTXCPTIFG:break;
    }
    } 
    #pragma vector=TIMER3_B0_vector
    __interrupt void TimeoutRF (void)
    {
    TB3CCTL0 &=~CCIE;
    TB3R = 0;
    UCA1IFG &=~UCRXIFG;
    timerExpired = T;
    _BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);
    }
    

    尝试了 TIMEOUT 和 RXIFG,但是……唯一可以肯定地停止它并带回我的是,如果我做一些事情,比如(howMany <=#)……但是,问题是#是长度是动态的,取决于发送的命令  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    >  charresponse[10] = {0};

    >            memset(incoming, 0, 20);

    >            memcpy(response, incoming, sizeof(incoming));

    What I deduce from these is that either:

    1) incoming is size 10, and the memset overruns incoming[] or

    2) incoming is size 20, and the memcpy overruns response[]

    [编辑:此外、看起来您将返回一个指向堆栈变量的指针、就像他们说的"危险"。]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Bruce....Comment 和问题...

    首先评论: 似乎我想睡在一个 if - else 区域(在这种情况下是 if),然后我醒来,如果我从未做过其他事情...这看起来是合乎逻辑的吗?  我说 bcz 我决定尝试对代码进行以下更改、现在我似乎回到 main 并停止。  请注意、我删除了其他内容、并将其替换为第二个 IF

    if ((!timerExpired)){//(UCA1IFG & UCRXIFG)
    _bis_SR_register (LPM3_bits);
    }
    if (timerExpired){
    PRx =传入;
    howMany = 0;
    memcpy (响应、传入、sizeof (响应));
    状态=完成;
    }
    中断;
    

    问:您能告诉我有关返回指针的更多信息吗?  我很难将指针返回到数组响应,这样我就可以使用向前移动的数据了.....

    谢谢

    Steve

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在 C 语言中、执行 if 块或 else 块、而不是同时执行这两个。 就编译器而言,睡眠没有什么特别之处--它只是在寄存器中设置一个位。

    循环的构建方式是、它将保持响应状态、轮询 timerExpired (在大循环中)直到它变为非0、此时将执行其他块。

    --

    从函数返回(概念上)会消除其所有栈变量。 下一个函数调用(对于 Real)通过在顶部写入其自己的栈变量来消除所有这些栈变量。 该指针在指向的内容变为"谁知道什么"后可能会长时间挂起。 K&R 1ed 中提到了这种危险、甚至在最初的 Bell Labs C 报告中也提到了这种危险。

    廉价的修复方法是使指针目标"静态"、将其从堆栈中移出。 这可以避免出现大问题、但下次调用该函数时指针的目标(内容)仍将发生变化。 这是其中一个事情、如果我发现自己要做、我会停下来重新思考。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在这里、我有点困惑、因为我从您上面的发言中了解到、if-else 不应该起作用的逻辑原因是什么?  我相信计时器已经过期,因为我看到变量显示了这样的... 我(我想像您一样)看到 ISR 的返回在 IF 内唤醒、识别'if'部分为 false、 此时执行'else'或最坏的情况、从'if-else'运行到末尾、然后再次完成整个案例流程、直到它到达该部分、然后执行'else'部分... 很明显,bcz 上的东西正在工作…

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    否,它不会在唤醒后重新评估 if()。 由于该块没有更改“状态”,它将从情况中退出,然后大循环将返回到相同的情况,并重新评估 if()。

    但是(我怀疑)当它执行"else"时 、memcpy 会覆盖"state"、而大循环不会退出。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Ahh...interesting....although 我修复了您之前在 ie memcpy (...)上评论的问题 sizeof (RESPONSE),因为我犯了这个错误……但它对死循环没有任何影响… 看起来很奇怪,memcpy 写得太多了,但无论如何,我的问题似乎已经解决了……感谢所有的帮助!!

    Steve

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你能不能在指针上详细说明一下,因为我不理解。。。

    我的主代码如下所示:

    PTX =*配置命令;
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+1);
    pGroupNo = radioReg (PTX);
    PTX =*(configCmd+2);
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+3);
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+4);
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+5);
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+6);
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+7);
    pRadioResponse = radioReg (PTX);
    PTX =*(configCmd+8);
    pVersionNo = radioReg (PTX);
    PTX =*(configCmd+9);
    pRadFrq = radioReg (PTX);
    PTX =*(configCmd+10);
    pRadioResponse = radioReg (PTX);
    _bis_SR_register (LPM3_bits + GIE);
    

    我尝试使用和不使用静态但无效的函数 radioReg 返回指针。  如果我不使用 static 并在__bis_SR 处停止...所有内容都读为0 ...如果我使用 static 并在那里停止所有指针都读出最后一个命令响应...如何使 pGroupNo、pVersionNo (它们是唯一的)与下一个命令响应一起被改写?   

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如果你看看这些指针、你会发现它们是相同的、即它们指向同一个位置。 对 radioReg 的每次调用都会用新的内容覆盖该"相同的位置"。  

    堆栈和静态方法之间的区别在于、对于"静态"、指针(它指向的是什么)在您再次调用 radioReg 之前是"安全"的、但对于"堆栈"、它仅在调用任何其他函数(包括 ISR、您对 ISR 没有太多的控制)之前是"安全"的。

    除非您要立即对指针(它指向的内容)执行某种操作、否则应将内容复制到其他位置。 考虑到这一点后、您可能会得出这样的结论:首先将最终的目标缓冲区(指针)直接传递到 radioReg 会更容易。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 Bruce。。。。

    我理解...好消息是我将在这种情况下立即对响应执行操作、因为这些都是配置命令...我的实际有效负载数据以不同的方式处理。

    Steve