您好:
我们在项目中拟使用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}
Ling Zhu2:
建议看一下用户手册:
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.
Lanshun Nie:
回复 Ling Zhu2:
谢谢您的回答。
用户手册这一部分我们仔细研究过了,但还是没把握,所以才上来提问。
可否给一个正确写RTC寄存器的例程?谢谢!
Ling Zhu2:
回复 Lanshun Nie:
写的时候应该把RTC hold 住吧
#include <msp430.h>int main(void) {WDTCTL = WDTPW + WDTHOLD;// Stop Watchdog TimerP1DIR |= BIT0;// Set P1.0 as output// Initialize LFXT1P7SEL |= 0x03;// Select XT1UCSCTL6 &= ~(XT1OFF);// XT1 OnUCSCTL6 |= XCAP_3;// Internal load cap// Loop until XT1,XT2 & DCO fault flag is cleareddo{UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);// Clear XT2,XT1,DCO fault flagsSFRIFG1 &= ~OFIFG;// Clear fault flags}while (SFRIFG1&OFIFG);// Test oscillator fault flag// Configure RTC_ARTCCTL01 |= RTCTEVIE + RTCRDYIE + RTCBCD + RTCHOLD + RTCMODE;// RTC enable, BCD mode, RTC hold// enable RTC read ready interrupt// enable RTC time event interruptRTCYEAR = 0x2010;// Year = 0x2010RTCMON = 0x4;// Month = 0x04 = AprilRTCDAY = 0x05;// Day = 0x05 = 5thRTCDOW = 0x01;// Day of week = 0x01 = MondayRTCHOUR = 0x10;// Hour = 0x10RTCMIN = 0x32;// Minute = 0x32RTCSEC = 0x45;// Seconds = 0x45RTCADOWDAY = 0x2;// RTC Day of week alarm = 0x2RTCADAY = 0x20;// RTC Day Alarm = 0x20RTCAHOUR = 0x10;// RTC Hour AlarmRTCAMIN = 0x23;// RTC Minute AlarmRTCCTL01 &= ~(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 interruptsbreak;case RTC_RTCRDYIFG:// RTCRDYIFGP1OUT ^= 0x01;// Toggles P1.0 every secondbreak;case RTC_RTCTEVIFG:// RTCEVIFG__no_operation();// Interrupts every minutebreak;case RTC_RTCAIFG:// RTCAIFGbreak;case RTC_RT0PSIFG:// RT0PSIFGbreak;case RTC_RT1PSIFG:// RT1PSIFGbreak;case 12: break;// Reservedcase 14: break;// Reservedcase 16: break;// Reserveddefault: break;} }