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.

[参考译文] MSP430FR5994:使用来自外围设备的数字输出从LPM唤醒

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1092899/msp430fr5994-using-a-digital-output-from-a-peripheral-to-wake-up-from-the-lpm

部件号:MSP430FR5994

我正在使用BOOSTXL回放作为在MSP430FR5994上运行音频检测代码的参考。 使用的MSP是外部的,并且由启动板成功检测到。 在我的代码中,我已将外部麦克风配置为提供从低到高的转换,该转换将作为从LPM唤醒设备的中断。 'main.c'文件中的代码如下:

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    initClock();
    initGpio();

    PM5CTL0 &= ~LOCKLPM5;       // Clear lock bit

    // Set internal reference voltage to 2.0 V
    //REFCTL0 = REFVSEL_1;      //vm1010

    // vm1010 mode pin (P6.1), o/p, low at start for normal mode
    P6OUT &= ~BIT1;             // vm1010
    P6DIR |= BIT1;              // vm1010
    // vm1010 mic power on (P6.2)
    P6OUT |= BIT2;              // vm1010
    P6DIR |= BIT2;              // vm1010

    // vm1010 mode pin, o/p, high for WoS mode
    P6OUT |= BIT1;              // vm1010

    P5IFG &= ~BIT6;             // Clear interrupt on P5.6
    P5IE |= BIT6;               // Enable interrupt on P5.6
    P5IFG &= ~BIT5;             // Clear interrupt on P5.5
    P5IE |= BIT5;               // Enable interrupt on P5.5

    // vm1010
    P5IFG &= ~BIT7;             // Clear interrupt on P5.7
    P5IE |= BIT7;               // Enable interrupt on P5.7

    __bis_SR_register(GIE);

    runApplication();

    return 1;
}

void initGpio(void)
{

    // Configure switches to have pull up resistors
    P5DIR &= ~(BIT6|BIT5);      // Set P5.6 and P5.5 to input direction
    P5REN |= (BIT6|BIT5);       // Enable option of pull-up or pull-down resistors for P5.6 P5.5
    P5OUT |= (BIT6|BIT5);       // Enable pull-up resistor for P5.6 and P5.5

    // Configure switch pins to generate interrupts on high to low transitions
    P5IES |= BIT6;
    P5IES |= BIT5;

    // vm1010 WoS digital out pin, i/p
    P5DIR &= ~BIT7;             // Set P5.7 to input direction // vm1010
    P5REN |= BIT7;              // Enable pull-up or pull-down resistors // vm1010
    P5OUT &= ~BIT7;             // Enable pull-down resistor for P5.7
    //Configure vm1010 digi o/p pin to generate interrupts on low to high transitions
    P5IES &= ~BIT7;             // vm1010
    
}

随后,在运行应用程序的'application.c'文件中,我正在使用调试器验证代码的功能。 在这里,runApplication() 函数控制执行,在此中我使用两种模式-默认和录音,用于表示麦克风的使用。 此函数的代码如下所示:

void runApplication(void)
{
    while(1)
    {
        P5IE &= ~BIT7;      // Disable interrupt on P5.7 // vm1010
        P5IE &= ~BIT6;      // Disable interrupt on P5.6
        P5IE &= ~BIT5;      // Disable interrupt on P5.5

        switch(applicationMode)
        {
            case RECORD:
            {
                volatile uint16_t j;
                runRecord();
                amplify_data();
                fft_init();
                while(window_number < 64)
                {
                    fft_cal();
                }
                window_number=0;
                for(j = 1; j < (VECTOR_SIZE / 2); j++)  // vm1010
                {
                    // vm1010
                    real = fft_res[2 * j] << 2;
                    imag = fft_res[2 * j + 1] << 2;
                    if(real < 0)
                    {
                        real_abs = ~real + 1;
                    }
                    else
                    {
                        real_abs = real;
                    }
                    if(imag < 0)
                    {
                        imag_abs = ~imag + 1;
                    }
                    else
                    {
                        imag_abs = imag;
                    }
                    if(real_abs >= imag_abs)
                    {
                        max = real_abs;
                        min = imag_abs;
                    }
                    else
                    {
                        max = imag_abs;
                        min = real_abs;
                    }
                    mag = max + 3 * (min >> 3);
                    FFT_data[j] = mag << 1;
                }

                int16_t spectrum[SIGNAL_ROWS1][SIGNAL_COLS1];
                signed int a,b;
                for(a=0; a<1; a++)
                {
                    for(b=256; b>=0; b--)
                    {
                        spectrum[a][b] = FFT_data[b];
                    }
                }

                matrix_multiply(1, 256, 256, 20, spectrum, weights1, pdt1);
                matrix_add(1, 20, pdt1, bias1, layer1);
                act_funct(1, 20, layer1, act1);

                matrix_multiply(1, 20, 20, 10, act1, weights2, pdt2);
                matrix_add(1, 10, pdt2, bias2, layer2);
                act_funct(1, 10, layer2, act2);

                matrix_multiply(1, 10, 10, 2, act2, weights3, pdt3);
                matrix_add(1, 2, pdt3, bias3, layer3);
                act_out(1, 2, layer3, pred);

                if(pred[0][0]==1)
                {
                    //PM5CTL0 &= ~LOCKLPM5;
                    // TB0.6 ---- P3.7 ---- PWM 4kHz for buzzer
                    TB0CCR0 = 2000-1;                         // PWM Period, 4kHz --> 250 us --> 2000 (0 to 1999) ticks at SMCLK = 8MHz
                    TB0CCTL6 = OUTMOD_7;                      // CCR6 reset/set
                    TB0CCR6 = 1000;                           // CCR6 PWM duty cycle, 50% duty cycle, 1000 ticks
                    TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR;  // SMCLK, up mode, clear TBR
                    P1OUT |= BIT0;
                    // TA1.1 ---- P1.2 ---- Timer for approx. 3 seconds for buzzer and LED
                    TA1CTL = TASSEL__SMCLK | MC__CONTINUOUS | TACLR | TAIE;        // SMCLK, Continuous mode, clear TAR
                    __bis_SR_register(LPM4_bits + GIE);       // Enter LPM4 w/ interrupt
                    P1OUT &= ~BIT0;
                    TA1CTL &= ~MC;
                    TB0CTL &= ~MC;
                }
                memset(fft_res, 0, sizeof(fft_res));
                memset(FFT_data, 0, sizeof(signal_fft));
                break;
            }
            default:
                break;
        }

        applicationMode = DEFAULT;

        // Need to put in normal mode and back to WoS mode to avoid issue where continuous clapping
        // causes interrupts faster than we can go in sleep mode, thus causing a state where we
        // are in sleep mode, but the interrupt is not recognized since interrupt flag is already high and
        // not cleared
        // vm1010 mode pin, o/p, low for normal mode
        P6OUT &= ~BIT1;                 // vm1010

        // Set a Switch debounce to 10ms (500ms -- 0.5 * sys freq)
        __delay_cycles(0.01 * __SYSTEM_FREQUENCY_MHZ__);

        P5IFG &= ~BIT6;                 // Clear interrupt on P5.6
        P5IE |= BIT6;                   // Enable interrupt on P5.6
        P5IFG &= ~BIT5;                 // Clear interrupt on P5.5
        P5IE |= BIT5;                   // Enable interrupt on P5.5
        P5IFG &= ~BIT7;                 // Clear interrupt on P5.7 // vm1010
        P5IE |= BIT7;                   // Enable interrupt on P5.7 // vm1010
        // vm1010 mode pin, o/p, high for WoS mode
        P6OUT |= BIT1;  // vm1010

        __bis_SR_register(LPM4_bits + GIE);
    }
}

在调试模式下,当我在启动板上结合BOOSTXL BoosterPack使用MSP时,我使用按钮从LPM4中唤醒,然后转到CASE =记录并开始录制。  

但是,当我使用外置麦克风时,我想使用在WFP 5.7 上获得的数字输出作为中断,以便从LPM4中唤醒。 该ISR的编写方式如下:

#pragma vector=PORT5_VECTOR
__interrupt void port5IsrHandler(void)
{
    switch (__even_in_range(P5IV, P5IV_P5IFG7))
    {
        case P5IV_NONE:
            break;
        case P5IV_P5IFG0:
            break;
        case P5IV_P5IFG1:
            break;
        case P5IV_P5IFG2:
            break;
        case P5IV_P5IFG3:
            break;
        case P5IV_P5IFG4:
            break;
        case P5IV_P5IFG5:
        case P5IV_P5IFG6:
            // Toggle record mode
            applicationMode = RECORD ;
            //exit LPM mode on exit
            __bic_SR_register_on_exit(LPM0_bits);
            break;
        case P5IV_P5IFG7:
            // Toggle record mode
            applicationMode = RECORD;
            //exit LPM mode on exit
            __bic_SR_register_on_exit(LPM0_bits);
            break;
        default:
            break;
   }
}
 

但是,在调试过程中,我的代码成功地完成了该函数,直到它进入runApplication() 函数中的LPM4 -__bis_sr_register(LPM4_bit + GIE)。 但是,当我在设备进入LPM后运行调试器时,我的代码将持续运行,而不会在函数中分支到记录模式。 在浏览了这里发布的多个示例和各种问题后,我仍然不确定我可能会做什么错误。 如需进一步帮助澄清问题,请告知我是否需要任何其他信息。  

谢谢你。

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

    >__BIC_SR_REGISTER_ON_EXIT   (LPM0_bits);

    这无法从LPM4正确唤醒主电源。 我想(我没有尝试过)它会唤醒它(CPUOFF = 0)但一些时钟不会运行。 请尝试:

    >__BIC_SR_REGISTER_ON_EXIT   (LPM4_bits);

    --------

    此外,确保"applicationMode"(应用程序模式)声明为"volate"(易失性)。

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

    不幸的是,这些更改没有帮助,因为代码仍然表现得类似。 当我按调试器中的播放按钮时,代码在行-__bis_sr_register(LPM4_bits)上持续运行

    您能否告诉我,我如何触发LPM的中断逻辑中是否存在错误?  

    外部麦克风上的信号将作为过渡显示在WFP 5.7 上,需要将其用作从LPM唤醒的中断。 我对代码的排列或层次结构有些不确定。

            P5IFG &= ~BIT6;                 // Clear interrupt on P5.6
            P5IE |= BIT6;                   // Enable interrupt on P5.6
            P5IFG &= ~BIT5;                 // Clear interrupt on P5.5
            P5IE |= BIT5;                   // Enable interrupt on P5.5
            P5IFG &= ~BIT7;                 // Clear interrupt on P5.7 // vm1010
            P5IE |= BIT7;                   // Enable interrupt on P5.7 // vm1010
            // vm1010 mode pin, o/p, high for WoS mode
            P6OUT |= BIT1;  // vm1010
    
    //        // Enter low power mode
           __bis_SR_register(LPM4_bits + GIE);
           
           
           

    在ISR中使用了WFP 5.7 上的中断信号,如下所示:

    #pragma vector=PORT5_VECTOR
    __interrupt void port5IsrHandler(void)
    {
        switch (__even_in_range(P5IV, P5IV_P5IFG7))
        {
        ..............
        .............
        case P5IV_P5IFG7:
                // Toggle record mode
                applicationMode = RECORD;
                //exit LPM mode on exit
                __bic_SR_register_on_exit(LPM4_bits);
                break;
            default:
                break;
       }
    }

    根据我所发现的一些讨论和先前的帖子,我认为代码也应该在调试模式下流畅地工作。 理想情况下,当我在代码进入LPM后通过迭代播放代码时,代码应退出并切换到记录模式。 以前,此处配置了一个按钮。 现在,这已被麦克风中断所取代。  

    我对任何重复表示歉意,但我试图了解我是否有任何逻辑上缺失的内容,或者这是否是代码中的一个小问题。 谢谢你。

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

    您是否在ISR中遇到了断点? 它是否具有您期望的静脉输液值?  

    我不确定我是否理解您的麦克风如何为GPIO中断生成(数字)触发器。 是数字麦克风吗? 如果是这样,并且您正在使用计时器驱动时钟,请记住,LPM4中几乎所有时钟(MCLK/SMCLK/ACLK)都已禁用。 如果您使用LPM0,您是否获得相同的结果?

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

    否,代码在ISR中一直循环。 我在ISR中设置了一个断点,特别是在描述了WFP 5.7 的地方,但是代码从未达到这一阶段。 在调试模式下,当我按“播放”时,代码会继续运行,并且只有当我按“挂起”时,代码才会指示它仍处于进入LPM的相同点。

    我将检查LPM0是否适用于我的案例,并在此处更新信息。

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

    如果您使用PDM麦克风的信号,其边缘将很快出现。 可能在看到第一个P5IE.7位后禁用该位?

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

    是的,麦克风是数字的,我使用LPM0尝试了代码,但在这种情况下也出现了相同的问题。

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

    我在ISR中尝试了类似的方法:

    //Option 1
    
    case P5IV_P5IFG7:
                // Toggle record mode
                P5IE &= ~BIT7;
                appMode = app_mode_record;
                //exit LPM mode on exit
                __bic_SR_register_on_exit(LPM0_bits);
                break;
                
            
    // Option 2 - Another suggestion that I saw on the forum was to use __disable_interrupt()
    case P5IV_P5IFG7:
                __disable_interrupt();
                // Toggle record mode
                appMode = app_mode_record;
                //exit LPM mode on exit
                __bic_SR_register_on_exit(LPM0_bits);
                break;
            
    
    
    

    请告诉我,这两种方法中的任何一种都能奏效,还是我在错误的位置使用了某种方法。  

    但是,他们和代码都不会拒绝迁移到ISR,也不会太快地运行到同一个时间点。 我认为它永远不会进入ISR,就像进入ISR一样-它会找到录制模式的切换,代码将分支到下一步。  谢谢!!

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

    根据我的猜测,我投票支持选项1 (选项2并不能真正实现任何目标)。 在下一次LPM之前,请不要忘记重新启用P5IE.7。

    可能会发生多种情况。 我没有你的设备,所以我无法尝试任何一种。 您是否检查了applicationMode声明?

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

    是的,我已对applicationMode volatile作出声明。 但是,我无法理解为什么代码拒绝进入ISR。 根据示例中代码的等价性,我认为MIC或相应ISR的中断中没有任何错误。 此问题的其他原因(如果有)是什么?

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

    你好,Siddhant Kishor Yeole,

    我注意到您没有在initGpio()函数中显式设置P5SEL。 您必须正确设置这些设置,因为它们在重置/启动时未定义。 我希望看到这样的情况:

    void initGpio(void)
    {
    
        // Configure switches to have pull up resistors
        P5DIR &= ~(BIT6|BIT5);      // Set P5.6 and P5.5 to input direction
        P5SEL0 &= ~(BIT6|BIT5);     // <-- ADD THIS TO SET AS INPUT
        P5SEL1 &= ~(BIT6|BIT5);     // <-- ADD THIS TO SET AS INPUT
        P5REN |= (BIT6|BIT5);       // Enable option of pull-up or pull-down resistors for P5.6 P5.5
        P5OUT |= (BIT6|BIT5);       // Enable pull-up resistor for P5.6 and P5.5
    
        // Configure switch pins to generate interrupts on high to low transitions
        P5IES |= BIT6;
        P5IES |= BIT5;
    
        // vm1010 WoS digital out pin, i/p
        P5DIR &= ~BIT7;             // Set P5.7 to input direction // vm1010
        P5SEL0 &= ~BIT7;             // <-- ADD THIS TO SET AS INPUT
        P5SEL1 &= ~BIT7;             // <-- ADD THIS TO SET AS INPUT
        P5REN |= BIT7;              // Enable pull-up or pull-down resistors // vm1010
        P5OUT &= ~BIT7;             // Enable pull-down resistor for P5.7
        //Configure vm1010 digi o/p pin to generate interrupts on low to high transitions
        P5IES &= ~BIT7;             // vm1010
        
    }

    如果这不起作用,我建议您删除代码,直到它是检测按钮按下所需的最小值。 然后,我会在ISR中添加一个while (1);在其上有一个断点以捕获它,这样我们就可以确认ISR是否正在触发。

    此致,

    Evan

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

    我不确定我是否理解您的症状。 是(a)您从不进入ISR还是(b)您反复(非常快)进入ISR?

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

    Bruce您好,我不确定是a还是b,但我尝试在ISR中设置一个断点,并尝试看看代码是否分支到该点-我想说这可能是前者。 但是,如果它确实是反复进入并且非常快速,我不知道调试器如何能够捕获它。 这两种情况是否都有明确和独特的解决办法?

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

    即使在到达断点时也触发了ISR。 推断"(非常快)"部分是一个判断调用。

    对于(A),您需要弄清楚为什么不会发生刺激(在WFP 5.7 的针脚上有一个示波器可能很方便)。 对于(b)一种可能性是在看到第一个触发器后禁用IE,然后在您感兴趣时重新启用它。