EFM32PG1B关于RTCC和EM4的那些坑

   日期:2020-07-10     浏览:94    评论:0    
核心提示:EFM32PG1B关于RTCC和EM4的那些坑EFM32PG1B关于RTCC和EM4的那些坑坑一:RTCC初始化坑二:EM4低功耗模式的初始化坑三:EM4模式使能EFM32PG1B关于RTCC和EM4的那些坑坑一:RTCC初始化 对于RTC我们都比较熟悉,我这里一般不把他用作所谓的年月日计时功能,我一般将RTC用作设备的定时唤醒。那么EFM32PG1B的RTCC又该如何初始化呢?我总结下来有如下几点:1、时钟的选择2、计数模式的选择3、计数值设置4、中断开启 先说第一点:EFM32的时钟树刚

EFM32PG1B关于RTCC和EM4的那些坑

  • EFM32PG1B关于RTCC和EM4的那些坑
    • 坑一:RTCC初始化
    • 坑二:EM4低功耗模式的初始化
    • 坑三:EM4模式使能

EFM32PG1B关于RTCC和EM4的那些坑

坑一:RTCC初始化

 对于RTC我们都比较熟悉,我这里一般不把他用作所谓的年月日计时功能,我一般将RTC用作设备的定时唤醒。那么EFM32PG1B的RTCC又该如何初始化呢?我总结下来有如下几点:
1、时钟的选择
2、计数模式的选择
3、计数值设置
4、中断开启
 先说第一点:EFM32的时钟树刚上手的时候感觉比较复杂,但其实仔细地看一下,会感觉它的时钟树也就那样。话不多说,上图。

 从图中可以看出,RTCC的时钟源有三个:LFXO、LFRCO、ULFRCO。前两个是32768hz,后一个是1000hz。这里我们将LFECLK的时钟源选择为ULFRCO,之后再使能RTCC时钟源就搞定了,总之一句话,看着图、循着线、一条一条地配置。

	  CMU_ClockSelectSet(cmuClock_LFE, cmuSelect_ULFRCO);
	  CMU_ClockEnable(cmuClock_RTCC, true);

 时钟选择好就到了第二点:计数模式的选择,这里就选择常规地CNT计数模式就可以,这种模式下定时器会比较RTCC_CNT与RTCC_CC[x]_CCV,如果相等就触发RTCC中断。我选用的是通道1。

	  RTCC_Init_TypeDef rtccInit = RTCC_INIT_DEFAULT;
	  RTCC_CCChConf_TypeDef rtccInitCompareChannel = RTCC_CH_INIT_COMPARE_DEFAULT;
	  RTCC_ChannelInit(1, &rtccInitCompareChannel);
	  // Initialize and start counting
	  RTCC_Init(&rtccInit);
#define RTCC_INIT_DEFAULT \ { \ false,   \
  false,      \
  false,      \
  false,      \
  rtccCntPresc_1,   \
  rtccCntTickPresc,   \
  false,      \
  rtccCntModeNormal,   \
  false,      \
}
#define RTCC_CH_INIT_COMPARE_DEFAULT \ { \ rtccCapComChModeCompare,         \
  rtccCompMatchOutActionToggle,         \
  rtccPRSCh0,                          \
  rtccInEdgeNone,                      \
  rtccCompBaseCnt,                     \
  0,                                   \
  rtccDayCompareModeMonth                                   \
}

 第三点是计数值的设置,也就是多久触发RTCC中断,我们选用了1khz的超低频时钟源,CNT每加1用时为1毫秒。那么就比较简单了,假设我需要30s触发中断,那么:

	RTCC_CounterSet(0);//CNT清零
	RTCC_ChannelCCVSet(1, 30*1000-1);

 万事俱备,只差最后一步:使能所需要的中断,没啥技术含量,直接上代码,这里要着重说一点,我们使用RTCC的目的是将设备从EM4状态下唤醒。因此,下面这一句必须要加!!!

RTCC_EM4WakeupEnable(true);//使能EM4唤醒

 然后使能中断

	RTCC_IntClear(RTCC_IF_CC1);
	RTCC_IntEnable(RTCC_IEN_CC1);
	NVIC_ClearPendingIRQ(RTCC_IRQn);
	NVIC_EnableIRQ(RTCC_IRQn);
	RTCC_Enable(true);

 以上就是所有RTCC的初始化配置了,以上配置都是为了从EM4状态唤醒而服务的。

坑二:EM4低功耗模式的初始化

 这个可把我坑了好几天,因为网上关于这个板子的资料很少,仅有的资料也说这一系列的芯片在EM4模式下的唤醒只能通过Pin interrupt 。但我看参考手册上讲,EM4下RTCC的时钟和中断是可以触发且唤醒的。所以啥也不说了,一点儿一点儿看。

 对了,EM4有两个模式:EM4H和EM4S。我们不需要设备关机,所以,低功耗就足够了,选择EM4H。
 初始化的步骤是什么呢,其实比较简单,只需要配置一个寄存器就够了:EMU_EM4CTRL
具体每一bit的意思见下图

  	//进入EM4模式
  	EMU_EM4Init_TypeDef em4Init = EMU_EM4INIT_DEFAULT;
  	EMU_EM4Init(&em4Init);
#define EMU_EM4INIT_DEFAULT \ { \ false,         \
  false,                                    \
  false,                                    \
  emuEM4Hibernate,                                                \
  emuPinRetentionDisable,                                   \
}

有没有很简单呢?

坑三:EM4模式使能

 这一点是坑了我好几天的原因,原因就是偷了一下懒,这一步我直接使用了库函数而没有看库函数里的内容,导致走了好多弯路。

void EMU_EnterEM4H(void)
{
  BUS_RegBitWrite(&EMU->EM4CTRL, _EMU_EM4CTRL_EM4STATE_SHIFT, 1);
  EMU_EnterEM4();
}

 问题就处在里面的子函数EMU_EnterEM4();
 这个函数里面可能由于设备有一些BUG,里面增加了一些对项目无用的语句,比如:
__disable_irq();
这一句话直接导致我的RTCC中断一直都无法发挥作用,使设备进入EM4模式休眠后就变砖了,必须要重新上电POR才可以。
 其实进入EM4很简单,还是EMU_EM4CTRL寄存器,这个寄存器的17:16就是管这个事情的,只需要将这两个比特依次写入2、3、2、3、2、3、2、3、2就ok了

  int i;
  uint32_t em4seq2 = (EMU->EM4CTRL & (~0x30000))
                     | (2 << 16);
  uint32_t em4seq3 = (EMU->EM4CTRL & (~0x30000))
                     | (3 << 16);
  EMU_Unlock();
  for (i = 0; i < 4; i++)
  {
    EMU->EM4CTRL = em4seq2;
    EMU->EM4CTRL = em4seq3;
  }
  EMU->EM4CTRL = em4seq2;

 以上就是所有的内容了,希望有所帮助哦!!!我的风格从来都不是拿来主义,所以希望拿来主义的人可能拿我的代码也只能做个参考,真正的知识是需要自己付出心力去探求的,不要拿来主义哦。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服