EFM32PG1B关于RTCC和EM4的那些坑

EFM32PG1B关于RTCC和EM4的那些坑

坑一:RTCC初始化

 对于RTC我们都比较熟悉,我这里一般不把他用作所谓的年月日计时功能,我一般将RTC用作设备的定时唤醒。那么EFM32PG1B的RTCC又该如何初始化呢?我总结下来有如下几点:
1、时钟的选择
2、计数模式的选择
3、计数值设置
4、中断开启
 先说第一点:EFM32的时钟树刚上手的时候感觉比较复杂,但其实仔细地看一下,会感觉它的时钟树也就那样。话不多说,上图。
RTCC时钟树
 从图中可以看出,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,     /* Start counting when init done.                           */  \
  false,    /* Disable RTCC during debug halt.                          */  \
  false,    /* Disable precounter wrap on ch. 0 CCV value.              */  \
  false,    /* Disable counter wrap on ch. 1 CCV value.                 */  \
  rtccCntPresc_1, /* 977 us per tick.                                  */  \
  rtccCntTickPresc, /* Counter increments according to prescaler value. */  \
  false,    /* No RTCC oscillator failure detection.                    */  \
  rtccCntModeNormal, /* Normal RTCC mode.                               */  \
  false,    /* No leap year correction.                                 */  \
}
#define RTCC_CH_INIT_COMPARE_DEFAULT                                        \
{                                                                           \
  rtccCapComChModeCompare,     /* Select output compare mode.     */        \
  rtccCompMatchOutActionToggle, /* Create pulse on compare match.  */        \
  rtccPRSCh0,                  /* PRS channel 0 (not used).       */        \
  rtccInEdgeNone,              /* No edge detection.              */        \
  rtccCompBaseCnt,             /* Counter comparison base.        */        \
  0,                           /* No compare mask bits set.       */        \
  rtccDayCompareModeMonth      /* Don't care */                             \
}

 第三点是计数值的设置,也就是多久触发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,                             /* Retain LFXO configuration upon EM4 entry */        \
  false,                             /* Retain LFRCO configuration upon EM4 entry */       \
  false,                              /* Retain ULFRCO configuration upon EM4 entry */      \
  emuEM4Hibernate,                     /* Use EM4 shutoff state */                           \
  emuPinRetentionDisable,            /* Do not retain pins in EM4 */                       \
}

有没有很简单呢?

坑三: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;

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值