主题中讨论的其他器件:MSP-EXP430FR6989、
您好!
这个问题与我们器件的功耗以及我们为其创建的应用相关。
我们的初始开发是在 Launchpad MSP-EXP430FR6989上完成的。
我们的定制板是围绕 MSP430FR5989开发的。
创建低功耗模式测试的目的是验证 RTC_C 的时间事件中断将唤醒系统并在睡眠周期后恢复运行
然后、测试包括:
a)为每个可能的时间间隔分钟、小时、中午和午夜的时间事件中断对 RTC_C 进行编程。
b)进入 LPM3.5
c)返回时通知用户发生了时间事件。
下面的代码片段应显示我们要执行的操作。
======================================================================== 测试函数================================================================================================================
/*
*注
释*/
void testTimeEventMinute (void)
{
uint16_t count = 0;
uint8_t 应答;
log_print (log_always、"%s"、__function__);
静态日历 cm =
{
0、 //! 秒数介于0-59之间
0、 //! 0-59之间的分钟数
14、 //! 0到23之间的一天中的一小时
3、 //! 周中的某天
16、 //! 1至31之间的月中某天
6、 //! 1到12之间的月份
2020年 //! 介于0-4095之间
};
TEST_EVENT_MINUT_CONTINUE = true;
/*
*清除日历模块中的所有中断
*在决定通知之前
*
CM_clearInterrupt (RTC_C_TIME_EVENT_INTERRUPT |
RTC_C_CLOCK_READ_READY_INTERRUPT |
RTC_C_CLOCK_ALARM_INTERRUPT);
/*
*禁用日历模块中的所有中断
*在决定通知之前
*
CM_disableInterrupt (RTC_C_TIME_EVENT_INTERRUPT |
RTC_C_CLOCK_READ_READY_INTERRUPT |
RTC_C_CLOCK_ALARM_INTERRUPT);
/*
*初始化 Calendar Manager
*
cm_init (&cm);
/*
*每隔一分钟就会收到通知
*
CM_registerEvent (RTC_C_CALENDAREVENT_INTOTECHANGE);
/*
*在发生时间事件时生成中断
*
CM_enableInterrupt (RTC_C_TIME_EVENT_INTERRUPT);
/*
*启动日历
*
CM_START();
//询问用户是否要进入深度睡眠状态
//等待此事件
MP_PRINT (BACK_CHANNEL、"%s\n"r、"是否要进入低功耗模式等待此事件(y/n)? ");
应答= MP_getchar (BACK_CHANNEL);
mp_print (后退通道、"%s"、%c\n\r\n、"您的答案->、答案);
while (test_event_minute_continue == true)
{
如果(答案='y')
{
/*
*进入启用中断的低功耗模式
*
_enable_interrupt ();
//此代码用于深度睡眠-可以正常工作,但还无法通过它进行调试
log_print (log_always、"%s"进入深度睡眠\n\r\n、__function__);
ctpl_enterLpm35 (CTPL_disable_restore_ON_reset);<--- 在这里、我们进入深度睡眠模式
log_print (log_always、"%s"从深度睡眠返回)\n\n"、__function__);<--- 我们从未从深度睡眠中返回(代码适用于 MSP430FR6989)
}
count++;
如果(计数= 0)
{
mp_print (BACK_CHANNEL、".");
LED_TOGGLE (1);
}
/*
*检查第二个事件是否被触发
*
无符号长整型 val = 0;
Val = bit_CHK (eventBitmap、rtcReadyInterruptTrigged);
如果(val = 1)
{
/*
*记录每秒中断事件
*
mp_print (BACK_CHANNEL、"Interrupt for second was trigged\n"r);
/*
*请日历管理器处理事件
*
CM_handleSecondEvent();
}
/*
*检查事件分钟是否被触发
*
Val = bit_CHK (eventBitmap、rtcTimeEventMinutInterruptTrigged);
如果(val = 1)
{
mp_print (BACK_CHANNEL、"Interrupt for Minute was trigged\n"r);
/*
*让测试事件处理程序处理该事件
*
test_handleMinuteEvent();
}
/*
*检查事件小时是否被触发
*
Val = bit_CHK (eventBitmap、rtcTimeEventHourInterruptTrigged);
如果(val = 1)
{
mp_print (BACK_CHANNEL、"小时中断已触发\n\r\n);
/*
*让测试事件处理程序处理该事件
*
test_handleHourEvent();
}
/*
*检查事件中午是否被触发
*
Val = bit_CHK (eventBitmap、rtcTimeEventNoonInterruptTrigged);
如果(val = 1)
{
mp_print (BACK_CHANNEL、"已触发中午中断\n\r\n);
/*
*让测试事件处理程序处理该事件
*
test_handleNoonEvent();
}
/*
*检查是否触发了午夜事件
*
Val = bit_CHK (eventBitmap、rtcTimeEventMidnightInterruptTrigged);
如果(val = 1)
{
mp_print (BACK_CHANNEL、"已触发午夜中断\n\r\n);
/*
*让测试事件处理程序处理该事件
*
test_handleMidnightEvent();
}
}
log_print (log_always、"%s"完成\n\r\n、__function__);
返回;
}
======================================================================== calendarManager 代码========================================================
/*! 文件 calendarManager.c
简要实施日历管理模块
此文件包含用于实现的代码
MightyPuffer 器件的日历管理功能
*
/*
========================================================
* calendarManager.c
*
*创建日期:2020年1月30日
*作者:首先
========================================================
*
#include "calendarManager.h"/*!<日历管理器定义和函数原型*/
/*
*注意:
*
void CM_init (日历*cm)
{
log_print (log_always、"%s"、__function__);
RTC_C_initCalendar (RTC_C_base、cm、RTC_C_FORMAT_BINARY);
返回;
}
/*
*注意:
*
void CM_start (void)
{
log_print (log_always、"%s"、__function__);
RTC_C_startClock (RTC_C_base);
返回;
}
/*
*注意:
*
void CM_stop (void)(空)
{
log_print (log_always、"%s"、__function__);
RTC_C_HOLDClock (RTC_C_BASE);
返回;
}
/*
*注意
*
空 CM_getTime (日历*cm)
{
日历 wrkCm;
log_print (log_always、"%s"、__function__);
wrkCm = RTC_C_getCalendarTime (RTC_C_base);/*!<告诉 driverlib 模块 RTC_C 执行该操作*
cm->seconds = wrkCm.seconds;/*!<*/
CM->Minutes = wrkCm.Minutes;/*!<*/
CM->Hours = wrkCm.Hours;/*!<*/
CM->DayOfWeek = wrkCm.DayOfWeek;/*!<*
cm->dayofmonth = wrkcm.dayofmonth;/*!<*
cm->month=wrkcm.month;/*!<*/
Cm->年= wrkcm.Year;/*!<*
返回;
}
/*
*注意:
*
void CM_registerEvent (uint16_t eventToRegister)
{
log_print (log_always、"%s"、__function__);
RTC_C_setCalendarEvent (RTC_C_base、eventToRegister);/*!<告诉 driverlib 模块 RTC_C 执行该操作*
返回;
}
/*
*注意:
*
void CM_enableInterrupt (uint8_t interruptToEnable)
{
log_print (log_always、"%s"、__function__);
RTC_C_enableInterrupt (RTC_C_base、interruptToEnable);/*!<告知 driverlib 模块 RTC_C 执行此操作*
返回;
}
/*
*注意:
*
void CM_clearInterrupt (uint8_t interruptToClear)
{
log_print (log_always、"%s"、__function__);
RTC_C_clearInterrupt (RTC_C_base、interruptToClear);/*!<告知 driverlib 模块 RTC_C 执行该操作*
返回;
}
/*
*注意:
*
void CM_disableInterrupt (uint8_t interruptToDisable)
{
log_print (log_always、"%s"、__function__);
RTC_C_DisableInterrupt (RTC_C_base、interruptToDisable);/*!<告知 driverlib 模块 RTC_C 执行该操作*
返回;
}
/*
*注意:
*
void CM_registerAlarm (RTC_C_configureCalendarAlarmParam *警报)
{
log_print (log_always、"%s"、__function__);
RTC_C_configureCalendarAlarm (RTC_C_base、alarm);/*!<告诉 driverlib 模块 RTC_C 执行该操作*
返回;
}
/*
*注意:
*
cm_status_e cm_compareDate (mp_date_t * nowDate、mp_date_t * thenDate)
{
CM_STATUS_e 状态= CM_SUCCESS;
log_print (log_always、"%s"、__function__);
/*
*比较月份
*
if (nowDate->mp_mon == thenDate->mp_mon)
{
/*
*比较当天
*
if (nowDate->mp_mday == thenDate->mp_mday)
{
状态= CM_DATE_NOW _EQU_then;
}
其他
{
/*
*比较当天
*
if (nowDate->mp_mday < thenDate->mp_mday)
{
状态= CM_DATE_NOW _LE_then;
}
其他
{
状态= CM_DATE_NOW:GT_then;
}
}
}
其他
{
/*
*比较月份
*
if (nowDate->mp_mon < thenDate->mp_mon)
{
状态= CM_DATE_NOW _LE_then;
}
其他
{
状态= CM_DATE_NOW:GT_then;
}
}
退货状态;
}
/*
*注意:
*比较是在 HH:MM 上进行的
*在此比较中不考虑秒数
*但这是我们当前的方法
*
CM_STATUS_e CM_COMPARE 时间(MP_TIME_t * nowTime、MP_TIME_t * thenTime)
{
CM_STATUS_e 状态= CM_SUCCESS;
log_print (log_always、"输入:%s\n\r\n、__function__);
/*
*
*比较小时
*
if (nowTime->mp_hour =thenTime->mp_hour)
{
/*
*比较分钟
*
if (nowTime->mp_min =thenTime->mp_min)
{
状态= CM_TIME_Now_EQU_then;
}
其他
{
/*
*比较分钟
*
if (nowTime->mp_min < thenTime->mp_min)
{
状态= CM_TIME_Now_LE_Then;
}
其他
{
状态= CM_TIME_Now_LE_Then;
}
}
}
其他
{
/*
*比较小时
*
if (nowTime->mp_hour < thenTime->mp_hour)
{
状态= CM_TIME_Now_LE_Then;
}
其他
{
状态= CM_TIME_Now_GT_then;
}
}
退货状态;
}
/*
*注意:
*
空 CM_handleSecondEvent (空)
{
eventBitmap = bit_CLR (eventBitmap、rtcReadyInterruptTrigged);
}
/*
*注意:
*
void CM_handleMinuteEvent (void)
{
log_print (log_always、"输入:%s\n\r\n、__function__);
eventBitmap = bit_CLR (eventBitmap、rtcTimeEventMinutInterruptTrigged);
}
/*
*注意:
*
无效 CM_handleHourEvent (空)
{log_print (log_always、"输入:%s\n\r\n、__function__);
eventBitmap = bit_CLR (eventBitmap、rtcTimeEventHourInterruptTrigged);
}
/*
*注意:
*
*在午夜事件的处理中
*我们获取当前日期和时间
*并执行日期比较
*
*
void CM_handleMidnightEvent (void)
{
MP_STATUS_e 状态= MP_SUCCESS;/*!<*/
CM_STATUS_e compareStatus = CM_SUCCESS;/*!<*/
CM_STATUS_e compareStatus1 = CM_SUCCESS;/*!<*/
mp_date_t 激活日期={0};/*!<*
mp_date_t 当天日期={0};/*!<*
mp_date_t endOfSeasonDate ={0};/*!<*
日历现在={0};/*!<*/
uint16_t seasonWindow = 0;/*!<*
log_print (log_always、"输入:%s\n\r\n、__function__);
/*
*检索季节窗口
*
状态= PC_retrieSeasonWindow (季节性窗口);
if (status!= MP_SUCCESS)
{
log_print (log_always、"%s -检测到错误\n\r\n、__function__);
返回;
}
/*
*立即从 Calendar Manager 硬件获取时间
*我们可以将其更改为使用第二个中断
*立即捕获日期和时间
*
cm_getTime (&now);/*!<*/
/*
*仅获取日期部分
*
当天 Date.mp_year = Now.Year;
todayDate.mp_mon |= now月份;
todayDate.mp_mday |= now.dayofmonth;
/*
*从检索激活日期
*主动填充协议
*
状态= PC_retrieActivationDate (&activationDate);
如果(status == MP_SUCCESS)
{
/*
*将今天的日期与激活日期进行比较
*
CompareStatus = CM_compareDate (&todayDate、&activationDate);
开关(比较状态)
{
案例 CM_DATE_Now_EQU_then:
log_print (log_always、"%s"我们处于激活日期\n\r\n、__function__);
eventBitmap = bit_set (eventBitmap、activationDateRedached);
中断;
案例 CM_DATE_Now_LE_Then:
log_print (log_always、"%s"我们早于激活日期\n"r、__function__);
eventBitmap = bit_set (eventBitmap、activationDateNotYetReached);
中断;
案例 CM_DATE_Now_GT_Then:
log_print (log_always、"%s"我们在激活日期之后\n\r\n、__function__);
/*
*现在我们需要了解我们是否仍处于淡季
*的季节窗口。
*这是通过将今天的日期与进行比较来完成的
*按激活日期+季节计算的日期
*
addDays ((int) activationDate.mp_mday、
(int) activationDate.mp_mon、
(int) activationDate.mp_year、
SeasonWindow、
endOfSeasonDate.mp_mday、
endOfSeasonDate.mp_mon、
endOfSeasonDate.mp_year);
/*
*将今天的日期与季末日期进行比较
*
compareStatus1 = CM_compareDate (&T)、endOfSeasonDate (&endOfSeasonDate);
开关(compareStatus1)
{
案例 CM_DATE_Now_EQU_then:
/*
*我们刚刚结束了赛季
*
*
案例 CM_DATE_Now_GT_Then:
/*
*本赛季结束后,Whave 已过
*
eventBitmap = bit_set (eventBitmap、activationDatePassed);
/*
*
*我们需要通过增加来修改激活日期
*按今天到之间的年份数计算的年份
*季末后的一年
*
activationDate.mp_year ++;
状态= PC_AdjustActivationDate (&activationDate);
if (status!= MP_SUCCESS)
{
log_print (log_always、"%s -检测到错误\n\r\n、__function__);
返回;
}
中断;
案例 CM_DATE_Now_LE_Then:
/*
*我们仍在季中
*可以进行正常处理
*
*
eventBitmap = bit_set (eventBitmap、dataStillInSeason);
中断;
}
}
}
/*
*清除事件
*
eventBitmap = bit_CLR (eventBitmap、rtcTimeEventMidnightInterruptTrigged);
返回;
}
/*
*注意:
*
void CM_handleNoonEvent (void)
{
log_print (log_always、"输入:%s\n\r\n、__function__);
eventBitmap = bit_CLR (eventBitmap、rtcTimeEventNoonInterruptTrigged);
}
/*
*注意:
*
void CM_hanleAlarm (void)
{
log_print (log_always、"输入:%s\n\r\n、__function__);
eventBitmap = bit_CLR (eventBitmap、rtcAlarmInterruptTrigged);
}
/*
================================================================
*中断服务例程(ISR)
================================================================
*
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=RTC_vector
_interrupt
#Elif defined (_GNU_)
__attribute__((中断(RTC_Vector))
#endif
/**
*这是中断服务例程(ISR)
*表示内部 RTC_C 日历
*至少有六个中断源可用、即
*
* RT0PSIFG:
*====
* RT0PSIFG 可被用于生成可由 RT0IP 位选择的中断间隔。
* RT0PS 以32768Hz 的低频振荡器时钟作为时钟源、
*所以间隔为
* 16384Hz、
* 8192Hz、
* 4096 Hz、
* 2048Hz、
* 1024 Hz、
* 512Hz、
* 256Hz、
*或128Hz
*是可能的。
*将 RT0PSIE 位置位将启用中断。
*
* RT1PSIFG:
*====
* RT1PSIFG 可被用于生成可由 RT1IP 位选择的中断间隔。
* RT1PS 由 RT0PS 的输出提供、其频率为128Hz (32768/256Hz)。
*因此、间隔为
* 64Hz、
* 32Hz、
* 16Hz、
* 8Hz、
* 4Hz、
* 2Hz、
* 1Hz、
*或0.5Hz
*是可能的。
*将 RT1PSIE 位置位会启用中断。
*
*
* RTCRDYIFG:
*===========
*
* RTCRDY 位为实时时钟中断 RTCRDYIFG 供源、并且在同步时非常有用
*使用系统时钟读取时间寄存器。 将 RTCRDYIE 位置位将启用中断。
*
*安全读取实时时钟寄存器的一种简便方法是使用 RTCRDYIFG 中断标志。
*
*设置 RTCRDYIE 使能 RTCRDYIFG 中断。
*
*启用后、会根据 RTCRDY 位的上升沿生成中断、
*导致 RTCRDYIFG 被置位。
*
*此时、应用程序有将近一秒钟的时间来安全地读取任何或所有实时时钟寄存器。
*
*此同步过程可防止在转换期间读取时间值。
*当中断被处理时、RTCRDYIFG 标志会自动复位、也可以通过软件复位。
*
*
* RTCTEVIFG:
*
* RTCAIFG:
*
* RTCOFIFG:
*
*这些标志被优先化并被组合在一起以提供一个单一的标志
*中断矢量。
*中断向量寄存器(RTCIV)用于确定请求的标志
*中断。
*
空 RTC_ISR (空)
{
开关(__evo_in_range (RTCIV、RTCIV_RT1PSIFG))
{
/*
*矢量0
*无中断
*
案例 RTCIV_NONE:
{
RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
HWREG8 (RTC_C_BASE + OFS_RTCCTL0_L)&&~Ω RTCTEVIFG;
_no_operation();
}
中断;
/*
*矢量2
* RTCOFIFG
* 32kHz 晶体振荡器故障中断标志。
*此中断可用作 LPM3.5唤醒事件。
*它还指示备份操作期间的时钟故障。
* 0b =无中断挂起
* 1b =中断挂起。
*在最后一次复位后发生32kHz 晶体振荡器故障。
*
案例 RTCIV_RTCOFIFG:
{
RTC_C_clearInterrupt (RTC_C_base、RTC_C_osc_oscillator_FAULT_interrupt);
_no_operation();
}
中断;
/*
*矢量4
* RTCRDYIFG
*该矢量对应于
* RTC_C_CLOCK_READ_READY_INTERRUPT
*实时时钟就绪中断标志
* 0b =无法安全读取 RTC
* 1b = RTC 可被安全读取
*
*
案例 RTCIV_RTCRDYIFG:
{
/*
*每秒中断一次
*
eventBitmap = bit_set (eventBitmap、rtcReadyInterruptTrigged);
RTC_C_clearInterrupt (RTC_C_base、RTC_C_CLOCK_READ_READY_READY_INTERRUPT);
}
中断;
/*
*矢量6
* RTCEVIFG
*
案例 RTCIV_RTCTEVIFG:
{
/*
*实时时钟时间事件中断标志。
*在支持 LPM3.5的模块中、此中断
*可用作 LPM3.5唤醒事件。
* 0b =未发生时间事件
* 1b =发生了时间事件
*
/*
*我们使用日历模式(RTCMODE =1)
*
*读取寄存器控制1位0和1
* 1-0 RTCTEVx RW 0h 实时时钟时间事件
* 00b =分钟更改
* 01b =小时更改
* 10b =每天午夜(00:00)
* 11b =每天中午(12:00)
*
开关(HWREG8 (RTC_C_BASE + OFS_RTCCTL13_L)和 RTCTEV_3)
{
案例 RTCTEV__min:
{
/*
*每分钟中断一次
*
eventBitmap = bit_set (eventBitmap、rtcTimeEventMinutInterruptTrigged);
RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
}
中断;
案例 RTCTEV__Hour:
{
/*
*每小时中断一次
*
eventBitmap = bit_set (eventBitmap、rtcTimeEventHourInterruptTrigged);
RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
}
中断;
/*
*每天午夜中断
*
案例 RTCTEV__0000:
{
eventBitmap = bit_set (eventBitmap、rtcTimeEventMidnightInterruptTrigged);
RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
}
中断;
/*
*每天中午中断
*
RTCTEV__1200案例:
{
eventBitmap = bit_set (eventBitmap、rtcTimeEventNoonInterruptTrigged);
RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
}
中断;
默认值:
{
RTC_C_clearInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
RTC_C_DisableInterrupt (RTC_C_base、RTC_C_TIME_EVENT_INTERRUPT);
}
中断;
}
}
中断;
/*
*矢量8
* RTCAIFG
*
案例 RTCIV_RTCAIFG:
{
eventBitmap = bit_set (eventBitmap、rtcAlarmInterruptTrigged);
RTC_C_clearInterrupt (RTC_C_base、RTC_C_CLOCK_ALARM_INTERRUPT);
}
中断;
/*
*矢量 A
* RT0PSIFG
*
案例 RTCIV_RT0PSIFG:
{
_no_operation();
}
中断;
/*
*矢量 C
* RT1PSIFG
*
案例 RTCIV_RT1PSIFG:
{
_no_operation();
}
中断;
/*
*默认情况
*
默认值:
{
_no_operation();
}
中断;
}
}
/*模块结尾 calendarManager.c */
在下面的调试会话中、我们将进入 LPM3.5
在第138行放置断点并恢复执行
实际上会进入深度睡眠模式。
调试器指示
