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.

[参考译文] MSP430G2452:处理低功耗模式和中断

Guru**** 2511985 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/814028/msp430g2452-handling-low-power-mode-and-interrupts

器件型号:MSP430G2452

大家好、

在 C 语言中对微控制 器进行编程是一项相当新的工作、我在优化低功耗模式的同时使中断保持较短的时间、就像在这篇博文中一样。 想知道是否有人可以给我一些关于如何进行的建议。  

基本上,我要做的就是在 main()中设置我的器件,然后在执行相应的代码之前等待低功耗模式下的中断。 目前、我进行了如下设置、ISR 中包含大量代码:

(笑声) 
_bis_SR_register (CPUOFF + GIE); //输入 LPM0并在 (1)时启用中断 //循环永久 {}
//端口1中断服务例程
#pragma vector=Port1_vector
__interrupt void Port_1 (void)
{
WDTCTL = WDTPW + WDTCNTCL;
P1IFG &=~BIT3;// P1.3 IFG (中断标志)清零
TRIG += 1;//通过'TRIG'值循环以按顺序激活不同的 LED

if (trig==4){
TRIG = 0x000;
}
IF (TRIG = 1){
LED = BIT1;
}否则(TRIG =2){
LED = BIT3;
}否则(TRIG =3){
LED = BIT5;
}否则(TRIG =0){
LED = 0x000;
}
} 

由于这只是一个简短的示例,而且这种方法最终会导致很大的 ISR,我想尽量避免这种情况,我想在低功耗模式下使用中断进行轮询,然后处理 main()中的触发操作。 我在线找到的下图似乎表明这是可能的、但我不知道如何在 CPU 关闭的情况下检查情况。

我尝试运行以下脚本、但由于无法在 LPM0中评估条件、因此继续返回错误。 有人知道另一种处理方式吗? 也许与 MSP432的等待中断(WFI)函数类似、我认为该函数会暂停代码执行、直到生成中断?  

{... 
_bis_SR_register (CPUOFF + GIE); //输入 LPM0并启用中断

while (1){ //永久循环
if (trig==4){
TRIG = 0x000;
}
IF (TRIG = 1){
LED = BIT1;
}否则(TRIG =2){
LED = BIT3;
}否则(TRIG =3){
LED = BIT5;
}否则(TRIG =0){
LED = 0x000;
} 
_bis_SR_register (CPUOFF + GIE);// 



//端口1中断服务例程
#pragma vector=Port1_vector
__interrupt void Port_1 (void)
{
WDTCTL = WDTPW + WDTCNTCL;
P1IFG &=~BIT3;// P1.3 IFG (中断标志)清零
TRIG += 1;//循环通过'TRIG'值来按顺序激活不同的 LED
__BIC_SR_REGISTER_ON_EXIT (LPM0_Bits + GIE); //在退出中断时退出 LMP0,禁用中断,直至主函数中的任务完成

} 

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

    >  已尝试运行以下脚本、但仍会返回错误、因为无法在 LPM0中评估条件。

    我不确定我是否理解这句话。 您看到了什么错误? 它来自哪里? (编译器? 调试器? 模拟器?)

    >  但我无法确定如何在 CPU 关闭的情况下检查条件

    该图总体上非常有用,但我认为“修改 SR ”这一措辞是非常有用的。 在右侧的框中、模糊了这一点。 假设这些框仅包含文本“唤醒 main()”,不会停留在实际的机制上。

    ISR 可以检查条件、因为 CPU 被临时打开以执行它们。 一旦 ISR 唤醒了 main(),CPU 就不会关闭,因此它可以检查条件。

    LPM 机制类似于 WFI (和 AVR "SLEEP"),但对于 LPM,软件(ISR)(而不是 CPU)决定何时唤醒 main()。

    ----------

    我猜您正在使用 P1.3上的 Launchpad 按钮来仿真您的器件。 按钮容易"抖动"。 这通常是一个轻微的烦恼、但在这里、我担心它会使您对流量的理解变得混乱。 简单的去抖机制如下所示:

    _interrupt void Port1_ISR (void){
    __DELAY_CYCLES (2000);//旋转2000us (2ms)以进行去抖(可能足够长)
    P1IFG &=~BIT3; //现在清除它已停止弹跳
    如果((P1IN 和 BIT3)=0){//按钮低电平(即按下)?
    //按此处的按钮操作
    }
    } 

    是的、这会将一个旋转环路引入 ISR、通常您需要避免这种情况。 假设这是您的"测试装置"的一项让步--大多数器件信号不会"抖动",因此不需要此代码。

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

    您好、Bruce、

    感谢您的帮助! 尝试在 LPM 中执行语句时最初遇到的错误是:

    我在进入低功耗模式后立即添加了一个__NO_OPERAT()函数,这似乎解决了这种情况,因为这提供了一行代码来保留,而无需 CPU 操作。 我还意识到、当正确使用 LPM 时、我所使用的 while 环路不是必需的、我能够进一步简化代码以按照您描述的方式使用它。 对于可能存在类似问题的其他人、这是我使用的最终代码:

    void main (void){
    WDTCTL = WDTPW + WDTHOLD;//保持看门狗计时
    器...
    P1IE |= BIT3; // P1.3中断使能
    P1IES |= BIT3; // P1.3高/低边沿选择
    ...
    while (1){ //循环永远
    
    _bis_SR_register (CPUOFF + GIE);//进入 LPM0并启用全局中断
    __no_operation(); //在 LPM 中保持此函数,在中断后继续执行 main,再次保持每个循环迭代
    
    //在 main 中工作、由中断触发(在本例中、我正在读取 RGB 值并激活相应的 LED)
    I2C_SEND_SEQUENCE (Vals_Read、9、RGB_Trans、0); //读取值并将其存储在数组 RGB_Trans 中
    while (!i2c_done ());//检查以确保发送/读取过程完成
    
    //将 RGB 值存储在3字节数组中
    RGB_Data[0]=(RGB_Trans [3]<< 8)| RGB_Trans [2];//附加高字节和低字节以获取传感器值
    RGB_Data[1]=(RGB_Trans [5]<< 8)| RGB_Trans [4];
    RGB_Data[2]=(RGB_Trans [7]<< 8)| RGB_Trans [6];
    
    if (RGB_Data[0]>= RGB_Data[1]&& RGB_Data[0]>=RGB_Data[2]){
    P2OUT = BIT1;
    P2IFG &=~BIT1;
    } 否则、如果(RGB_Data[1]>= RGB_Data[0]&& RGB_Data[1]>=RGB_Data[2]){
    P2OUT = BIT3;
    P2IFG &=~BIT3;
    } 否则{
    P2OUT = BIT5;
    P2IFG &=~BIT4;
    }
    }
    //
    
    端口1中断服务例程
    #pragma vector=Port1_vector
    __interrupt void Port_1 (void)
    {
    P1IFG &=~BIT3;// P1.3 IFG (中断标志)清除(按钮)
    __BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//在退出中断时关闭低功耗模式
    }
    

    也感谢 去抖技巧、这不是我知道的问题。

    谢谢、

    Charlie