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:需要帮助了解 Launchpad 代码行为。

Guru**** 2589265 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/766750/msp430fr5994-launchpad-code-behavior-i-need-help-understanding

器件型号:MSP430FR5994
大家好、
我将介绍 MSP430FR5994的学习曲线、遇到了两个问题、我无法解释这两个问题、需要一些帮助才能理解。 代码相当简单、只要在 CCS 的终端上键入字符"A"(忽略不是"A"的任何字符)、它就只使用 BCL UART 以" hello world "进行响应。 此代码有效(非常感谢 Bruce 和 Matt)。 但是、当我注释掉 initGPIO 函数内的 P5IFG = 0x00;语句时、代码停止运行令我感到困惑。 我用黄色突出显示了问题说明。 代码按原样工作。 注释掉该语句、然后停止。 将语句移到函数外部并移到主函数中不会改变行为。 出于某种原因,该语句需要位于 initGPIO 函数中。 对发生什么情况有什么想法?  
1) 1)第二个问题是、按下 Launchpad 上的两个按钮(P5.6和 P5.5)产生的端口5中断无法识别。 我是否以某种方式锁定了端口? 。 如果能在这方面提供任何帮助,也将不胜感激。  
 
#include "driverlib.h"
uint32_t myMCLK = 0;
uint32_t mySMCLK = 0;
uint32_t myACLK = 0;
volatile uint8_t i;
volatile uint8_t j;
const char UCA0_string[]={" Hello World "};
extern int 模式;
extern int pingHost;
uint8_t RXData = 0;                              // UART 接收字节
INT MODE = 0;                                    //模式选择变量
int pingHost = 0;                                //从 PC GUI ping 请求
int noSDCard = 0;
日历日历;                               //用于 RTC 的日历

void initClocks (void){

  //将 DCO 频率设置为8MHz
  CS_setDCOFreq (CS_DCORSEL_0、CS_DCOFSEL_6);
  //将外部时钟频率设置为32.768KHz
  cs_setExternalClockSource (32768、0);
  //set ACLK=LFXT
  CS_initClockSignal (CS_ACLK、CS_LFXTCLK_select、CS_Clock_divider);
  //将 SMCLK = DCO 设置为分频器1
  CS_initClockSignal (CS_SMCLK、CS_DCOCLK_SELECT、CS_Clock_divider);
  //将 MCLK = DCO 设置为分频值为1
  CS_initClockSignal (CS_MCLK、CS_DCOCLK_select、CS_Clock_divider);
  //Start XT1、无超时
  CS_TurnOnLFXT (CS_LFXT_DRIVE_3);
  myACLK=CS_getACLK();
  mySMCLK=CS_getSMCLK();//8MHz
  myMCLK=CS_getMCLK ();  //16MHz
initTimer(void){
   myACLK=CS_getACLK ();  //10kHz
   Timer_A_initContinuousModeParam initA0 ={0};//初始化程序选择 TB1
   initA0.clockSource=timer_A_CLOCKSOURCE_ACLK;
   initA0.clockSourceDivider=timer_a_CLOCKSOURCE_divider;
   initA0.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
   initA0.timerClear = timer_a_do _clear;
   initA0.startTimer=false;
   Timer_A_initContinuousMode (timer_A0_BASE、&initA0);
   _bis_SR_register (GIE);
空 Init_BCL_UART ()
   //配置 UART
   EUSCI_A_UART_initParam param ={};
   param.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_ACLK;
   param.clockPrescalar = 3; //设置32.768kHz
   param.firstModReg = 0;
   param.secondModReg = 0x92;//3;/0x92;
   param.parity = EUSCI_A_UART_NO_parity;
   param.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
   param.numerofStopBits = EUSCI_A_UART_Oe_STOP_BIT;
   param.uartMode = EUSCI_A_UART_MODE;
   param.oversaming= EUSCI_A_UART_LOW_FREQUENCY BAUDRATE_generation;
   if (STATUS_FAIL = EUSCI_A_UART_init (EUSCI_A0_BASE、&param))
       返回;
   EUSCI_A_UART_ENABLE (EUSCI_A0_BASE);
   EUSCI_A_UART_clearInterrupt (EUSCI_A0_BASE、EUSCI_A_UART_receive_interrupt);

      //启用 USCI_A0 RX 中断
   EUSCI_A_UART_enableInterrupt (EUSCI_A0_BASE、
                                   EUSCI_A_UART_Receive_interrupt);//启用中断
   myACLK=CS_getACLK();
   mySMCLK=CS_getSMCLK();//8MHz
   myMCLK=CS_getMCLK ();  //16MHz
空 initGPIO()

       //将所有 GPIO 引脚设置为输出低电平以实现低功耗
       GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P2、          GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P3、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P4、          GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P5、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|                   GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P6、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P7、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_P8、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setOutputLowOnPin (GPIO_PORT_PJ、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN13|GPIO_PIN11|GPIO_PIN13|GPIO_PIN13|GPIO_PIN11|GPIO_PIN13|GPIO_PIN13|GPIO_PIN13|GPIO_PIN12|GPIO_PIN12|GPIO_PIN_PIN12|GPIO_PIN12|GPIO_PIN12
       GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P2、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P3、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P4、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P5、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|                   GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P6、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P7、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_P8、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
       GPIO_setAsOutputPin (GPIO_PORT_PJ、GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN13|GPIO_PIN11|GPIO_PIN13|GPIO_PIN13|GPIO_PIN11|GPIO_PIN13|GPIO_PIN12|GPIO_PIN12|GPIO_PIN12|GPIO_PIN12|GPIO_PIN12|GPIO_PIN12|GPIO_PIN_PIN12
       //将 PJ.4和 PJ.5设置为主模块函数输入、LFXT。
       GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_PJ、GPIO_PIN4 + GPIO_PIN5、GPIO_PRIMARY_MODULE_Function);

   //设置 P1.0和 P1.1 LED
   GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
   GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN1);
   //关闭 LED
   GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);
   GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN1);
   //将 P5.5和 P5.6设置为输入按钮
   GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P5、GPIO_PIN5);
   GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P5、GPIO_PIN6);
   GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、GPIO_PIN5、GPIO_PRIMARY_MODULE_Function);
   GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、GPIO_PIN6、GPIO_PRIMARY_MODULE_Function);
   GPIO_selectInterruptEdge (GPIO_PORT_P5、GPIO_PIN5、GPIO_HIGH_TO_LOW_TRANSITION);
   GPIO_selectInterruptEdge (GPIO_PORT_P5、GPIO_PIN6、GPIO_HIGH_TO_LOW_TRANSITION);
   //P5IE = 0x60;//在 P5.5和 P5.6上启用中断
   GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN5);
   GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN6);
   //setup BCL UART 引脚
   //配置 P2.0 - UCA0TXD 和 P2.1 - UCA0RXD
   GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P2、GPIO_PIN0、GPIO_secondary 模块_function);
   GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P2、GPIO_PIN1、GPIO_secondary 模块_function);
   //启用中断
   //注释掉以下函数会导致 EUSCI_A_UART 停止工作。EUSCI_A_UART 使用 P2.0和 P2.1
   P5IFG = 0x00;//清除所有端口5中断标志
   //禁用 GPIO 上电默认高阻抗模式
   //激活先前配置的端口设置
   //PMM_unlockLPM5 ();
空 Init_rtc ()

   //设置日历的当前时间
   calender.seconds   = 0x55;
   calender.minutes   = 0x30;
   calender.hours     = 0x04;
   calender.DayOfWeek = 0x01;
   calender.dayofmonth = 0x30;
   日历月     = 0x04;
   日历年      = 0x2014;
   //使用上面指定的日历初始化 RTC
   RTC_C_initCalendar (RTC_C_base、&日历、RTC_C_FORMAT_BCD);
   RTC_C_setCalendarEvent (RTC_C_base、RTC_C_CALENDAREVENT_INTOTECHANGE);
   RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
   RTC_C_enableInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
   //启动 RTC 时钟
   RTC_C_startClock (RTC_C_base);

int main (void){
   WDT_A_HOLD (WDT_A_base);
   initGPIO();
   initClocks();
   initTimer();
   init_BCL_UART();
   //P5IFG = 0x00;
 /*
   SDCardLib_setRTCTime (SDCardLib * lib、Calendar * curTime);
   SDCardLib_detectCard (SDCardLib * lib);

   SDCardLib_creeDirectory (SDCardLib * lib、char * DirectoryName);
   SDCardLib_WriteFile (SDCardLib * lib、
                              char * filename、char * buffer、uint16_t bufsize、
                              uint16_t *实际大小);

   返回(0);
*
      PMM_unlockLPM5 ();  //启用输出引脚设置-禁用 GPIO 上电默认高阻抗模式
     // PM5CTL0 &=~LOCKLPM5;
      //启动计时器 B1及其中断
      Timer_A_startCounter (timer_A0_BASE、timer_A_Continuous_mode);
      Timer_A_enableInterrupt (timer_A0_BASE);

       UCA0IE |= UCRXIE;//enable only receive interrupts
     //_bis_SR_register (GIE);//启用中断
      _enable_interrupt ();

      while (1)
      {
          volatile uint8_t k;
          ///EUSCI_A_UART_transmitData (EUSCI_A0_BASE、'K');
      }

#pragma vector = USCI_A0_vector
_interrupt void USCI_A0_ISR (void)

   switch (__evo_in_range (UCA0IV、18))
   {
       情况0x00://向量0:无中断
           中断;
       情况0x02://向量2:UCRXIFG
           if (UCA0RXBUF ='A'){
               I=0;
               UCA0IE |= UCTXIE;//received "A"、启用发送响应
               UCA0TXBUF = UCA0_STRING[j];
           }
           中断;
       情况0x04: //向量4:UCTXIFG
           UCA0TXBUF = UCA0_STRING[j++];
          if (j=sizeof  (UCA0_string)-1){
               UCA0IE &=~UCTXIE;
           }
          if (j>= sizeof (UCA0_string)) j=0;
       中断;
       情况0x06: //向量6:UCSTTIFG
           中断;
       情况0x08: //向量8:UCTXCPTIFG
           中断;
       默认值:break;
   }
#pragma vector=TIMER0_A1_vector
_interrupt void timer_A0_ISR (void)

   switch (__evo_in_range (TA0IV、14))
   {
       案例0:                        //无
           中断;
       案例2:                        // CCR1 IFG
           中断;
       案例4:                        // CCR2 IFG
           中断;
       案例6:                        // CCR3 IFG
           中断;
       案例8:                        // CCR4 IFG
           中断;
       案例10:                       // CCR5 IFG
           中断;
       判例12:                       // CCR6 IFG
           中断;
       判例14:                       // TAOIFG
           GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
           Timer_A_clearTimerInterrupt (timer_A0_BASE);
           中断;
       默认值:                       //从未执行
           中断;
   }
#pragma vector=PORT5_vector
_interrupt void ISR_P5_Handler (void){
 开关(P5IFG)
       {
           情况0x20:                 //P5.5中断
               P5IFG &=~BIT4;        //清除 IFG
               P1OUT |= BIT1;         //Grn LED 端口1.1
               _delay_cycles (80000);  //等待
               P1OUT &=~BIT1;        //关闭 LED
               中断;
           情况0x40:                 //P5.6中断
               P5IFG &=~BIT6;        //清除 IFG
               int i;
               对于(i=3;i>0;i--){    //flash 3次
                   P1OUT |= BIT1;     //Grn LED 端口1.1
                   _delay_cycles (80000);
                   P1OUT ^= BIT1;
                   _delay_cycles (80000);
               }
               中断;
           默认值:                   //never executed
               中断;
       }

/*
#pragma vector=PORT5_vector
_interrupt void ISR_button_P55 (void){
   _delay_cycles (1000);//等待去抖
   //P1OUT &=~BIT0;
   P5IFG = 0x00;      //清除中断标志
   P5OUT |= BIT5;
   _delay_cycles (800000);
   P1OUT &=~BIT0;
#pragma vector=PORT5_vector
_interrupt void ISR_button_P56 (void)

   _delay_cycles (10);//等待去抖
   P1IFG = 0x00;//清除中断标志
   P6OUT &=~BIT6;
   对于(j=6;j>0;j-)//三次闪存-每个闪存循环两次代码
       {
       P6OUT ^= BIT6;
       _delay_cycles (200000);//替换为计时器
       }
   P5OUT &=~BIT6;
   //test UART pragma
   //UCA1IE |= UCTXIE;//enable txie

*
#pragma vector=RTC_vector
_interrupt void RTC_ISR (void)

   switch (__event_in_range (RTCIV、16))
   {
       案例 RTCIV_NONE:中断;        //无中断
       案例 RTCIV_RTCOFIFG:中断;    //RTCOFIFG
       案例 RTCIV_RTCRDYIFG:中断;   //RTCRDYIFG
       案例 RTCIV_RTCTEVIFG:          //RTCEVIFG
           //每5秒中断一次
           __no_operation();          //用于调试
           _BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);   //退出 LPM3
           中断;
       案例 RTCIV_RTCAIFG:中断;     //RTCAIFG
       案例 RTCIV_RT0PSIFG:中断;    //RT0PSIFG
       案例 RTCIV_RT1PSIFG:中断;    //RT1PSIFG
       默认值:break;
   }
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > GPIO_selectInterruptEdge (GPIO_PORT_P5、GPIO_PIN5、GPIO_HIGH_TO_LOW_TRANSITION);
    > GPIO_enableInterrupt (GPIO_PORT_P5、GPIO_PIN5);
    设置 P5IES 位会导致 P5IFG 位被置位。 也会设置 P5REN。 [参考 UG (SLAU367O)第12.2.6.2、12.2.6]节、一旦启用中断、您就会转至 ISR (两个 IFG 都已设置)。 在启用前、您应该将 GPIO_clearInterrupt 称为最后一项、或者像现在一样只设置 P5IFG=0。

    >开关(P5IFG)
    此开关不会检查是否设置了两个位(以上是您的情况);在这种情况下、它不会清除 IFG、并通过 ISR 永久递归。 对于您想要执行的操作、您可能只需单独检查它们。
    --------------------------------------
    > GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、GPIO_PIN5、GPIO_PRIMARY_MODULE_Function);
    > GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、GPIO_PIN6、GPIO_PRIMARY_MODULE_Function);
    就在将 P5.5/6设置为 GPIO (按钮)之后、这些引脚将 P5.5/6设置为备用功能(UCA2)。 我想您不需要这些行。
    --------------------------------------
    未经请求:
    > 情况0x20: //P5.5中断
    > P5IFG &=~BIT4; //清除 IFG
    > P1OUT |= BIT1; //Grn LED 端口1.1
    > _delay_cycles (80000);//等待
    > P1OUT &=~BIT1; //关闭 LED
    您没有明确地去抖,但会从 delay_cycles()调用中得到这种效果。 缺失的内容:IFG 将(反复)设置为按钮抖动。 你应该在你很确定弹跳已经停止后清除 IFG --在这里,在"情况"的末尾,而不是开头。 此处的症状是按钮似乎被按下两次。
    --------------------------------------
    未经请求:
    请勿发布注释了大块的代码。 这使得扫描非常困难、尤其是没有代码标签。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢你 Bruce!!!!

    我在 initTimer()中留下了一个使能中断,导致中断过早启用。 谢谢!!

    您对第二个问题的看法是正确的。 。
    GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、
    GPIO_PIN6、GPIO_PRIMARY_MODULE_FUNCTION);

    确实是问题的原因。 我展开了宏、它选择了错误的函数模块。 我删除了这两项陈述、并根据您的建议清理了处理程序。 代码更干净、功能齐全。 非常感谢!!