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.

[参考译文] MSP430FR2311:如何从 LPM4.5唤醒

Guru**** 2595805 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/647030/msp430fr2311-how-to-wake-up-from-lpm4-5

器件型号:MSP430FR2311

大家好、

我正在使用 FR2311进行一个项目。 要求比较简单。 按键将系统置于 LPM4.5中、

再次按下 EXIT LPM4.5..... 就像这样。

我认为一个小时就足够完成这项工作了。 但是,这花费了我将近一整天的时间,问题是

仍在等待中 (   所以,我来这里寻求帮助。

以下代码在 MSP_EXP430FR2311 LaunchPad 上运行、存在2个问题:

1) 1)它仅在 IDE 的调试模式下工作。

2)它可以从 LPM4.5退出、而无需按键。 因为键充当电源开关,

无意中退出/进入 LPM4.5是无法忍受的。   

问题很容易重现、希望有些人能提供一些线索。

此外,我还有一个问题:进入中断服务程序中的 LPMx.5,它是否可以?  

提前感谢。

Seafesse

/*********
用于 MSP430 V6.50

MSP-EXP430FR2311 LaunchPad

P1.1----的 IAR 密钥

使用 P1.1作为开关。

P1.0 P2.0代表2个状态:进入 LPM4.5或从 LPM4.5退出

1)
进入 LPM4.5-P2.0高电平-


2)绿色 LED
从 LPM4.5-P1.0高电平-
PS:低电平红色 LED -高电平边缘



/
#include"msp430fr2311.h"

#define u08_t unsigned char
#define U16_t unsigned int
#define u32_t unsigned long
#define MCLK_FREQ_MHz 8
/*******
===================================================================================================================================
(三 /
__否_初始化 u08_t key_ok_arry[5];


/*********
===================================================================================================================================
(三 /
void Software_Trim (void);

void InitSysClk (void);
void Init_GeneralIO (void);
void StopAllPerihClock (void);
void InitKeyBuf (void);
void SetPwmAndAD_IO (void);
void InitPwm_Pole1Pole2 (void);
void PowerOffTheSystem (void);
/*********
=================================== ========================================================================
(三 /
void main( void ){

__no_operation();
__no_operation();
// if (PMMLPM5IFG & PMMIFG)

IF (SYSRSTIV = SYSRSTIV_LPM5WU)
{
_DELAY_CYCLES (1000);
PMMCTL0_H = PMMPW_H;
PMMIFG &=~PMMLPM5IFG;

InitSysClk();
InitKeyBuf();
SetPwmAndAD_IO();
InitPwm_Pole1Pole2();
while (1)
{
_bis_SR_register (GIE|LPM4_BITS);
__no_operation();
__no_operation();
}
}
其他
{
PowerOffTheSystem();
}
}


空 InitKeyBuf (空)
{
u08_t i;
for (i=0;i<5;i++)
{
key_ok_arry[i]=1;
}
}
/*********
函数名:
100us脉宽 InitPwm_Pole1Pole2 **说明:100Hz
********* /
void InitPwm_Pole1Pole2 (void)
{
TB0CTL = TBSSEL_2 + TBCLR;//SMCLK = 8MHz
TB0CTL |= TBIE + ID_3;//1MHz
TB0CCR0 = 5000-1;//10ms
TB0CCR1 = 50;
TB0CCR2 = 5000-50;
TB0CCTL0 = 0;
TB0CCTL1 = 0;
TB0CCTL2 = 0;
增减计数模式 μ s
TB0CTL |=MC_3;
}

/*********
函数名:
说明:InitSysClk **
MCLK:8MHz
/
void InitSysClk (void)
{
_bis_SR_register (SCG0); //禁用 FLL
CSCTL3 |= SELREF_REFOCLK; //将 REFO 设置为 FLL 基准源
CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3;// DCOFTRIM = 3、DCO 范围= 10MHz
CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
_DELAY_CYCLES (4);
_BIC_SR_register (SCG0); //启用 FLL
Software_Trim (); //软件调整以获得最佳 DCOFTRIM 值
CSCTL4 = SELMS_DCOCLKDIV | SELA_REFOCLK;//将默认 REFO (~32768Hz)设置为 ACLK 源、ACLK = 32768Hz
操作
{
CSCTL7 &=~(XT1OFFG | DCOFFG); //清除 XT1和 DCO 故障标志
SFRIFG1 &=~OFIFG;
} while (SFRIFG1和 OFIFG); //测试振荡器故障标志

CSCTL8=0x0007;
}

/*********
函数名:**初始
**说明:
/
void Init_GeneralIO (void)
{

P1OUT =BIT1;
P1SEL0=0;
P1SEL1=0;
P1REN=BIT1;
P1DIR = BIT0;
//低边沿
P1IES = 0;
P1IFG = 0;
P1IE = BIT1;


P2OUT = BIT0;
P2SEL0 = 0;
P2SEL1=0;
P2REN=0;
P2DIR = BIT0;
P2IES = 0;
P2IE=0;

PM5CTL0 &=~LOCKLPM5;
}/

*********
函数名:


是PWM输出 SetPwmAndAD_IO **说明:P1.0/P1.1是AD输入 P1.6/P1.7/P2.0
/
void SetPwmAndAD_IO (void)
{

P1OUT = BIT0+BIT1;
P1SEL0 = 0;
P1SEL1 = 0;
P1REN = BIT1;
P1DIR = BIT0;
P1IES = 0;
P1IFG=0;
P1IE = 0;

P2OUT=0;
P2SEL0 = 0;
P2SEL1 = 0;
P2REN = 0;
P2DIR = 0;
P2IES = 0;
P2IE=0;

PM5CTL0 &=~LOCKLPM5;

}


/*********
函数名:
说明:TBIFG_10ms_ISR **
IBIFG
/
#pragma vector=TIMER0_B1_vector
__interrupt void TBIFG_10ms_ISR (void)
{
TB0CTL &=~ TBIFG;

/********* 键_确定********** /
key_ok_arry[4]= key_ok_arry[0];
IF (P1IN 和 BIT1)
{
key_ok_arry[1]= 1;
}
其他
{
key_ok_arry[1]= 0;
}
key_ok_arry[0]&&(key_ok_arry[1]|key_ok_arry[2]|key_ok_arry[3]);
key_ok_arry[0]|=(key_ok_arry[1]和 key_ok_arry[2]和 key_ok_arry[3]);
key_ok_arry[3]= key_ok_arry[2];
key_ok_arry[2]= key_ok_arry[1];

//高-低-边缘按键
if ((~key_ok_arry[0])&(key_ok_arry[4]))
{
PowerOffTheSystem();
返回;
}


}


/*********
函数名:
说明:StopAllPerihClock **
/
void StopAllPerihClock (void)
{
CSCTL8 = 0;
TB0CTL = TBCLR;//SMCLK = 8MHz
TB1CTL = TBCLR;
ADCCTL0 = 0;
RTCCTL =0;
}
/*********
函数名:软件_调整
**说明:
/
void Software_Trim (void)
{
U16_t oldDcotTap = 0xFFFF;
U16_t newDcotTap = 0xFFFF;
U16_t newDcoDelta = 0xFFFF;
u16_t bestDcoDelta = 0xFFFF;
U16_t csCtl0Copy = 0;
U16_t csCtl1Copy = 0;
U16_t csCtl0Read = 0;
U16_t csCtl1Read = 0;
u16_t dcoFreqTrim = 3;
u08_t endLoop = 0;

操作
{
CSCTL0 = 0x100; // DCO 抽头= 256
操作
{
CSCTL7 &=~DCOFFG; //清除 DCO 故障标志
} while (CSCTL7 & DCOFFG); //测试 DCO 故障标志

_DELAY_CYCLLES (((U16_t) 3000 * MCLK_FREQ_MHz);//等待 FLL 锁定状态(FLLUNLOCK)保持稳定
//建议等待24个经过分频的 FLL 参考时钟周期
while (((CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1))和&((CSCTL7 & DCOFFG)= 0));

CSCCtl0Read = CSCTL0; //读取 CSCTL0
CSCCtl1Read = CSCTL1; //读取 CSCTL1

oldDcoTap = newDcoTap; //记录上次的 DCOTAP 值
NewDcoTap = csCtl0Read & 0x01ff; //获取此次的 DCOTAP 值
dcoFreqTrim =(csCtl1Read & 0x0070)>>4;//获取 DCOFTRIM 值

if (newDcoTap < 256) // DCOTAP < 256
{
newDcoDelta = 256 - newDcoTap; // DCPTAP 和256之间的增量值
if ((oldDcotap!= 0xFFFF)&&(oldDcotap >= 256)// DCOTAP 交叉256
endLoop = 1; //停止 while 循环
其他
{
dcoFreqTrim --;
CSCTL1 =(csCtl1Read &(~DCOFTRIM))|(dcoFreqTrim<4);
}
}
其他 // DCOTAP >= 256
{
newDcoDelta = newDcoTap - 256; // DCPTAP 和256之间的增量值
if (oldDcoTap < 256) // DCOTAP 交叉256
endLoop = 1; //停止 while 循环
其他
{
dcoFreqTrim++;
CSCTL1 =(csCtl1Read &(~DCOFTRIM))|(dcoFreqTrim<4);
}
}

if (newDcoDelta < bestDcoDelta) //记录最接近256的 DCOTAP
{
csCtl0Copy = csCtl0Read;
csCtl1Copy = csCtl1Read;
bestDcoDelta = newDcoDelta;
}

}while (endLoop =0); //轮询直至 endLoop = 1

CSCTL0 = csCtl0Copy; //重新加载锁定的 DCOTAP
CSCTL1 = csCtl1Copy; //重新加载锁定的 DCOFTRIM
while (CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1));//轮询直到 FLL 锁定
为止}

/*********
函数名:
说明:进入LPM4.5进入极低的功耗 PowerOffTheSystem **
/
void PowerOffTheSystem (void)
{
__no_operation();
StopAllPerihClock();
_BIC_SR_register (GIE);
WDTCTL = WDTPW + WDTHOLD;


init_GeneralIO();


PMMCTL0_H = PMMPW_H; //打开 PMM 寄存器进行写入
PMMCTL0_L &=~(SVSHE); //禁用高侧 SVS
PMMCTL0_L |= PMMREGOFF; //并设置 PMMREGOFF
PMMCTL0_H = 0; //锁定 PMM 寄存器
_bis_SR_register (LPM4_bits | GIE);
} 

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

    您好、Seafesse、

    您可以使用类似这样的代码方案吗?

    #include 
    
    define u08_t unsigned char
    #define U16_t unsigned int
    #define u32_t unsigned long
    #define MCLK_FREQ_MHz 8
    
    void Software_Trim (void);
    void InitSysClk (void);
    void InitGPIO (void);
    /**
    * main.c
    */
    int main (void)
    {
    WDTCTL = WDTPW | WDTHOLD; //停止 WDT
    
    InitSysClk();
    InitGPIO();
    
    //等待按键 P1.1进入 LPM4.5
    P1IFG = 0;
    _bis_SR_register (LPM4_bits | GIE);
    
    //关闭系统电源
    //关闭红色 LED 并打开绿色 LED
    P1OUT &=~BIT0;
    P2OUT |= BIT0;
    
    _delay_cycles (80000);
    
    //关闭外设
    CSCTL8 = 0;
    TB0CTL = TBCLR;//SMCLK = 8MHz
    TB1CTL = TBCLR;
    ADCCTL0 = 0;
    
    //显式清除 RTC 控制寄存器以禁用它
    //以防之前启用 RTC
    RTCCTL = 0;
    PMMCTL0_H = PMMPW_H; //打开 PMM 寄存器进行写入
    PMMCTL0_L &=~(SVSHE); //禁用高侧 SVS
    PMMCTL0_L |= PMMREGOFF; //并设置 PMMREGOFF
    PMMCTL0_H = 0; //锁定 PMM 寄存器
    
    P1IFG = 0;
    //输入 LPM4请注意,此操作不会返回。 LPM4.5
    //将通过复位事件退出,从而重新启动
    代码的//。
    _bis_SR_register (LPM4_bits | GIE);
    
    __no_operation();
    返回0;
    }
    
    void InitSysClk (void)
    {
    _bis_SR_register (SCG0); //禁用 FLL
    CSCTL3 |= SELREF_REFOCLK; //将 REFO 设置为 FLL 基准源
    CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3;// DCOFTRIM = 3、DCO 范围= 10MHz
    CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
    _DELAY_CYCLES (4);
    _BIC_SR_register (SCG0); //启用 FLL
    Software_Trim (); //软件调整以获得最佳 DCOFTRIM 值
    CSCTL4 = SELMS_DCOCLKDIV | SELA_REFOCLK;//将默认 REFO (~32768Hz)设置为 ACLK 源、ACLK = 32768Hz
    操作
    {
    CSCTL7 &=~(XT1OFFG | DCOFFG); //清除 XT1和 DCO 故障标志
    SFRIFG1 &=~OFIFG;
    } while (SFRIFG1和 OFIFG); //测试振荡器故障标志
    
    CSCTL8=0x0007;
    }
    
    void InitGPIO (void)
    {
    //将所有 GPIO 设置为最低功耗
    P1DIR = 0xFF;P2DIR = 0xFF;
    P1REN = 0xFF;P2REN = 0xFF;
    P1OUT = 0x00;P2OUT = 0x00;
    
    //初始化密钥1.1
    P1OUT |= BIT1;
    P1REN |= BIT1;
    P1DIR &=~BIT1;
    P1IES &=~BIT1; //从低到高的转换
    P1IFG = 0;
    P1IE = BIT1;
    
    //打开红色 LED 并关闭绿色 LED
    P1OUT |= BIT0;
    P2OUT &=~BIT0;
    
    //禁用 GPIO 上电默认高阻抗模式
    //激活先前配置的端口设置
    PM5CTL0 &=~LOCKLPM5;
    }
    
    void Software_Trim (void)
    {
    U16_t oldDcotTap = 0xFFFF;
    U16_t newDcotTap = 0xFFFF;
    U16_t newDcoDelta = 0xFFFF;
    u16_t bestDcoDelta = 0xFFFF;
    U16_t csCtl0Copy = 0;
    U16_t csCtl1Copy = 0;
    U16_t csCtl0Read = 0;
    U16_t csCtl1Read = 0;
    u16_t dcoFreqTrim = 3;
    u08_t endLoop = 0;
    
    操作
    {
    CSCTL0 = 0x100; // DCO 抽头= 256
    操作
    {
    CSCTL7 &=~DCOFFG; //清除 DCO 故障标志
    } while (CSCTL7 & DCOFFG); //测试 DCO 故障标志
    
    _DELAY_CYCLLES (((U16_t) 3000 * MCLK_FREQ_MHz);//等待 FLL 锁定状态(FLLUNLOCK)保持稳定
    //建议等待24个经过分频的 FLL 参考时钟周期
    while (((CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1))和&((CSCTL7 & DCOFFG)= 0));
    
    CSCCtl0Read = CSCTL0; //读取 CSCTL0
    CSCCtl1Read = CSCTL1; //读取 CSCTL1
    
    oldDcoTap = newDcoTap; //记录上次的 DCOTAP 值
    NewDcoTap = csCtl0Read & 0x01ff; //获取此次的 DCOTAP 值
    dcoFreqTrim =(csCtl1Read & 0x0070)>>4;//获取 DCOFTRIM 值
    
    if (newDcoTap < 256) // DCOTAP < 256
    {
    newDcoDelta = 256 - newDcoTap; // DCPTAP 和256之间的增量值
    if ((oldDcotap!= 0xFFFF)&&(oldDcotap >= 256)// DCOTAP 交叉256
    endLoop = 1; //停止 while 循环
    其他
    {
    dcoFreqTrim --;
    CSCTL1 =(csCtl1Read &(~DCOFTRIM))|(dcoFreqTrim<4);
    }
    }
    其他 // DCOTAP >= 256
    {
    newDcoDelta = newDcoTap - 256; // DCPTAP 和256之间的增量值
    if (oldDcoTap < 256) // DCOTAP 交叉256
    endLoop = 1; //停止 while 循环
    其他
    {
    dcoFreqTrim++;
    CSCTL1 =(csCtl1Read &(~DCOFTRIM))|(dcoFreqTrim<4);
    }
    }
    
    if (newDcoDelta < bestDcoDelta) //记录最接近256的 DCOTAP
    {
    csCtl0Copy = csCtl0Read;
    csCtl1Copy = csCtl1Read;
    bestDcoDelta = newDcoDelta;
    }
    
    }while (endLoop =0); //轮询直至 endLoop = 1
    
    CSCTL0 = csCtl0Copy; //重新加载锁定的 DCOTAP
    CSCTL1 = csCtl1Copy; //重新加载锁定的 DCOFTRIM
    while (CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1));//轮询直至 FLL 锁定
    }
    
    //端口1中断服务例程
    #if defined (__TI_Compiler_version__)|| defined (__IAR_systems_ICC__)
    #Elima vector=Port1_vector
    __interrupt Port_1 (void
    
    )(void Port_1 (void)(void)(void)(#_port1)(void)(nu_port1)(void!
    
    
    #endif
    {
    switch (__evo_in_range (P1IV、P1IV_P1IFG7)){
    案例 P1IV_none:中断;
    案例 P1IV_P1IFG0:中断;
    案例 P1IV_P1IFG1:// P1.1上的边沿
    _BIC_SR_REGISTER_ON_EXIT (LPM4_BITS);//返回时退出 LPM4
    中断;
    案例 P1IV_P1IFG2:中断;
    案例 P1IV_P1IFG3:中断;
    案例 P1IV_P1IFG4:中断;
    案例 P1IV_P1IFG5:中断;
    案例 P1IV_P1IFG6:中断;
    案例 P1IV_P1IFG7:中断;
    默认值:break;
    }
    } 

    这避免了使用定时器和手动检查钥匙输入上的上升沿。 您应该能够从一个中断处理例程进入 LPMx.5而不会出现问题。

    此致、

    Ryan  

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

    您好、Ryan、

    谢谢。 我已经解决了这个问题。 我犯了一个愚蠢的错误。 :(

    "单击"操作包括"从高到低"和"从低到高"边沿。 我配置"从高到低"以将系统置于 LPM4.5中、并 配置"从低到高"沿以从 LPM4.5中唤醒。

    因此,“单击”会触发这两个事件。 这就是为什么我认为系统在没有任何人工干预的情况下从 LPM4.5唤醒的原因。

    无论如何,感谢您的热情。