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.

MSP430F5418A能否动态写RTC寄存器?谢谢

Other Parts Discussed in Thread: MSP430F5418A

您好:

我们在项目中拟使用MSP430F5418A的RTC功能,日历模式,想实现的功能是当收到网络时间同步消息后,通过写RTC的寄存器

直接修改年、月、日、时、分、秒等信息。写寄存器函数的代码如下所示。该代码能够修改RTCYEAR等寄存器,但是似乎会导致

一些奇怪的现象,如RTC走时过程中RTCMIN突然不正常跳变等。请教TI的工程师,日历模式下RTCYEAR等寄存器和RTCAMIN寄存器

能够在运行时被动态地修改?如果可以,如何安全地修改这些寄存器?谢谢!

void write_calendar(calendar_time caltime)
{
   for(;!(RTCCTL01&RTCRDY););
  RTCYEAR = caltime.year  ;        // Year  
  RTCMON  =  caltime.mon  ;        // Month   
  RTCDAY  =  caltime.day  ;        // Day   
  RTCDOW  =  caltime.day_of_week ; // Day of week   
  RTCHOUR = caltime.hour  ;        // Hour
  RTCMIN  =  caltime.min  ;        // Minute
  RTCSEC  =  caltime.sec  ;        // Seconds
}

  • 建议看一下用户手册:

    22.2.2.3 Reading or Writing Real-Time Clock Registers in Calendar Mode Because the system clock may be asynchronous to the RTC_A clock source, special care must be taken when accessing the real-time clock registers.

    In calendar mode, the real-time clock registers are updated once per second. To prevent reading any realtime clock register at the time of an update, which could result in an invalid time being read, a keepout window is provided. The keepout window is centered approximately -128/32768 s around the update transition. The read-only RTCRDY bit is reset during the keepout window period and set outside the keepout the window period. Any read of the clock registers while RTCRDY is reset is considered to be potentially invalid, and the time read should be ignored. An easy way to safely read the real-time clock registers is to use the RTCRDYIFG interrupt flag. Setting RTCRDYIE enables the RTCRDYIFG interrupt. Once enabled, an interrupt is generated based on the rising edge of the RTCRDY bit, causing the RTCRDYIFG to be set. At this point, the application has nearly a complete second to safely read any or all of the real-time clock registers. This synchronization process prevents reading the time value during transition. The RTCRDYIFG flag is reset automatically when the interrupt is serviced, or can be reset with software. In counter mode, the RTCRDY bit remains reset. RTCRDYIE is a don't care and RTCRDYIFG remains reset.

    NOTE: Reading or writing real-time clock registers When the counter clock is asynchronous to the CPU clock, any read from any RTCSEC, RTCMIN, RTCHOUR, RTCDOW, RTCDAY, RTCMON, RTCYEARL, or RTCYEARH register while the RTCRDY is reset may result in invalid data being read. To safely read the counting registers, either polling of the RTCRDY bit or the synchronization procedure previously described can be used. Alternatively, the counter register can be read multiple times while operating, and a majority vote taken in software to determine the correct reading. Reading the RT0PS and RT1PS can only be handled by reading the registers multiple times and a majority vote taken in software to determine the correct reading or by halting the counters. Any write to any counting register takes effect immediately. However, the clock is stopped during the write. In addition, RT0PS and RT1PS registers are reset. This could result in losing up to 1 s during a write. Writing of data outside the legal ranges or invalid time stamp combinations results in unpredictable behavior.

  • 谢谢您的回答。

    用户手册这一部分我们仔细研究过了,但还是没把握,所以才上来提问。

    可否给一个正确写RTC寄存器的例程?谢谢!

  • 写的时候应该把RTC hold 住吧

    #include <msp430.h>
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop Watchdog Timer
      P1DIR |= BIT0;                            // Set P1.0 as output
    
      // Initialize LFXT1
      P7SEL |= 0x03;                            // Select XT1
      UCSCTL6 &= ~(XT1OFF);                     // XT1 On
      UCSCTL6 |= XCAP_3;                        // Internal load cap
    
      // 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
    
      // Configure RTC_A
      RTCCTL01 |= RTCTEVIE + RTCRDYIE + RTCBCD + RTCHOLD + RTCMODE;
                                                // RTC enable, BCD mode, RTC hold
                                                // enable RTC read ready interrupt
                                                // enable RTC time event interrupt
    
      RTCYEAR = 0x2010;                         // Year = 0x2010
      RTCMON = 0x4;                             // Month = 0x04 = April
      RTCDAY = 0x05;                            // Day = 0x05 = 5th
      RTCDOW = 0x01;                            // Day of week = 0x01 = Monday
      RTCHOUR = 0x10;                           // Hour = 0x10
      RTCMIN = 0x32;                            // Minute = 0x32
      RTCSEC = 0x45;                            // Seconds = 0x45
    
      RTCADOWDAY = 0x2;                         // RTC Day of week alarm = 0x2
      RTCADAY = 0x20;                           // RTC Day Alarm = 0x20
      RTCAHOUR = 0x10;                          // RTC Hour Alarm
      RTCAMIN = 0x23;                           // RTC Minute Alarm
    
      RTCCTL01 &= ~(RTCHOLD);                   // Start RTC calendar mode
    
      __bis_SR_register(LPM3_bits + GIE);       // Enter LPM3 mode with interrupts
                                                // enabled
      __no_operation();
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    __interrupt void RTC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(RTCIV,16))
      {
        case RTC_NONE:                          // No interrupts
          break;
        case RTC_RTCRDYIFG:                     // RTCRDYIFG
          P1OUT ^= 0x01;                        // Toggles P1.0 every second
          break;
        case RTC_RTCTEVIFG:                     // RTCEVIFG
          __no_operation();                     // Interrupts every minute
          break;
        case RTC_RTCAIFG:                       // RTCAIFG
          break;
        case RTC_RT0PSIFG:                      // RT0PSIFG
          break;
        case RTC_RT1PSIFG:                      // RT1PSIFG
          break;
        case 12: break;                         // Reserved
        case 14: break;                         // Reserved
        case 16: break;                         // Reserved
        default: break;
      }
    }