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.

MSP430F6438 低功耗模式下的串口通信失败

Other Parts Discussed in Thread: MSP430F6438

大家好:

    我现在遇到一个棘手的问题。MSP430F6438 工作在低功耗LPM3模式下,系统时钟为通过倍频得到的2.45MHz,串口时钟使用smclk。

    现在问题出来了,若在仿真状态下,串口可以正常接收数据;若退出仿真状态,拔掉仿真器,串口则不能接收数据了。这是什么原因呢?

    下面是时钟初始化和串口初始化代码:

void Init_FLL_CLK(void)                        // 初始化锁相环主时钟: MCLK = XT1×(FLL_FACTOR+1)
{
  while(BAKCTL & LOCKBAK)                    // Unlock XT1 pins for operation
  BAKCTL &= ~(LOCKBAK);
  P7SEL  |=(BIT0+BIT1);                        // 端口选择外部低频晶振XT1 ,32768
  UCSCTL6&=~XT1OFF;                            // 使能外部晶振
  UCSCTL6|= XCAP_3;                            // 设置内部负载电容
  UCSCTL3|= SELREF_0;        //  SELREF_0选择 XT1 ; 
 UCSCTL4|= SELA__XT1CLK;          // ACLK   = ref
 // Loop until XT1,XT2 & DCO fault flag is cleared
  do
  {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
                                            // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG;                      // Clear fault flags
  }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
 UCSCTL6 &= ~(XT1DRIVE_3);                 // Xtal is now stable, reduce drive strength
 // Initialize DCO to 2.45MHz
  __bis_SR_register(SCG0);                  // Disable the FLL control loop
  UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx.
  UCSCTL1 &= ~(DCORSEL_7);                  // Clear DCO frequency select bits first
  UCSCTL1 = DCORSEL_3;                      // Set RSELx for DCO = 4.9 MHz
  UCSCTL2 = FLLD_1 + 74;                    // Set DCO Multiplier for 2.45MHz
                                            // (N + 1) * FLLRef = Fdco
                                            // (74 + 1) * 32768 = 2.4576MHz
  __delay_cycles(5000);
  __bic_SR_register(SCG0);                  // Enable the FLL control loop

  UCSCTL4 |= SELM__DCOCLK + SELA__XT1CLK + SELS__DCOCLK; //选择MCLK,ACLK,SMCLK,
}
 void Init_USCI_A0_UART(void)
{
  UCA0IE&=~UCRXIE; 
  UCA0IE&=~UCTXIE;         // 关闭中断
  P2SEL   |= (BIT4+BIT5);        
  P2DIR   |=  BIT4;                
  P2DIR   &= ~BIT5;                 // 选择引脚方向
  UCA0CTL1 = UCSWRST;               // 状态机复位
  UCA0CTL1|= UCSSEL__SMCLK;              // 选择时钟源CLK = SMCLK
  UCA0CTL0 = UCMODE_0;              //选择uart模式
  UCA0CTL0 &= ~UC7BIT;              //8字节传输
  
  UCA0BR0 = 0x40;                     //波特率分频 2457600hz/38400
  UCA0BR1 = 0x00;
  UCA0MCTL= 0x00;
  UCA0CTL1&=~UCSWRST;               // 启动状态机,即启用串口功能
  UCA0IE  |= UCRXIE;                // 允许接收中断
}

  • 建议观察一下串口通讯的时序,估计断开仿真器时改变了

  • xu zheng4 说:

    大家好:

        我现在遇到一个棘手的问题。MSP430F6438 工作在低功耗LPM3模式下,系统时钟为通过倍频得到的2.45MHz,串口时钟使用smclk。

        现在问题出来了,若在仿真状态下,串口可以正常接收数据;若退出仿真状态,拔掉仿真器,串口则不能接收数据了。这是什么原因呢?

        下面是时钟初始化和串口初始化代码:

    void Init_FLL_CLK(void)                        // 初始化锁相环主时钟: MCLK = XT1×(FLL_FACTOR+1)
    {
      while(BAKCTL & LOCKBAK)                    // Unlock XT1 pins for operation
      BAKCTL &= ~(LOCKBAK);
      P7SEL  |=(BIT0+BIT1);                        // 端口选择外部低频晶振XT1 ,32768
      UCSCTL6&=~XT1OFF;                            // 使能外部晶振
      UCSCTL6|= XCAP_3;                            // 设置内部负载电容
      UCSCTL3|= SELREF_0;        //  SELREF_0选择 XT1 ; 
     UCSCTL4|= SELA__XT1CLK;          // ACLK   = ref
     // Loop until XT1,XT2 & DCO fault flag is cleared
      do
      {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
                                                // Clear XT2,XT1,DCO fault flags
        SFRIFG1 &= ~OFIFG;                      // Clear fault flags
      }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
     UCSCTL6 &= ~(XT1DRIVE_3);                 // Xtal is now stable, reduce drive strength
     // Initialize DCO to 2.45MHz
      __bis_SR_register(SCG0);                  // Disable the FLL control loop
      UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx.
      UCSCTL1 &= ~(DCORSEL_7);                  // Clear DCO frequency select bits first
      UCSCTL1 = DCORSEL_3;                      // Set RSELx for DCO = 4.9 MHz
      UCSCTL2 = FLLD_1 + 74;                    // Set DCO Multiplier for 2.45MHz
                                                // (N + 1) * FLLRef = Fdco
                                                // (74 + 1) * 32768 = 2.4576MHz
      __delay_cycles(5000);
      __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
      UCSCTL4 |= SELM__DCOCLK + SELA__XT1CLK + SELS__DCOCLK; //选择MCLK,ACLK,SMCLK,
    }
     void Init_USCI_A0_UART(void)
    {
      UCA0IE&=~UCRXIE; 
      UCA0IE&=~UCTXIE;         // 关闭中断
      P2SEL   |= (BIT4+BIT5);        
      P2DIR   |=  BIT4;                
      P2DIR   &= ~BIT5;                 // 选择引脚方向
      UCA0CTL1 = UCSWRST;               // 状态机复位
      UCA0CTL1|= UCSSEL__SMCLK;              // 选择时钟源CLK = SMCLK
      UCA0CTL0 = UCMODE_0;              //选择uart模式
      UCA0CTL0 &= ~UC7BIT;              //8字节传输
      
      UCA0BR0 = 0x40;                     //波特率分频 2457600hz/38400
      UCA0BR1 = 0x00;
      UCA0MCTL= 0x00;
      UCA0CTL1&=~UCSWRST;               // 启动状态机,即启用串口功能
      UCA0IE  |= UCRXIE;                // 允许接收中断
    }
    

    建议先跑一下官方例程~

  • 你好 dirtwillfly :

        串口时序并未发生改变。我的电路是另外一个主控CPU向该msp430通过串口发送数据。数据手册上说LPM3模式下,SMCLK停止,是不是说这时选择SMCL做时钟源的串口不能用了?谢谢你!!

  • 你好 juring_2016 :

          我这查找了好多帖子。从TI的官网上看,TI 的工程师说是这个MSP430F5XXX 6XXX系列的BUG,又说可以采用外部P1 P2口中断的方式来解决,但不知道具体如何操作?下面附上相关的论坛地址:

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/19023#pi316701=1

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/304352

  • 你好juring_2016 :

        TI提供的例程MSP430F66XX ,里面关于串口的有两个。

    1.是在LPM0模式下,使用DCO倍频来的SMCLK做串口的时钟源。该模式下功耗太大了。

    2.是在LPM3模式下,使用32768的ACLK做时钟源,但在9600下误差有14%,只能正确接收1~2个字符,很不稳定,无法用来做稳定的产品。

    鉴于TI提供的例程的两种方式都无法使用,所以特来请教。

    谢谢~


  • 你好 juring_2016 :
    在初始化中增加如下代码,故障排除了。
      // Disable SVS
    PMMCTL0_H = PMMPW_H; // PMM Password
    SVSMHCTL &= ~(SVMHE | SVSHE); // Disable High side SVS
    SVSMLCTL &= ~(SVMLE | SVSLE); // Disable Low side SVS
    PMMCTL0_H = 00; //  
  • 为什么这做,能说一下思路吗?和我的有点像