jicheng0622

【原创】分享飞思卡尔KL25使用UART通信唤醒低功耗模式代码

0
阅读(6395)

    飞思卡尔基于ARM Cortex-M0+内核的Kinetis L系列的低功耗特性被广泛使用在可穿戴设备、智能水电气表类及移动手持设备等等需要电池供电的对功耗敏感的应用领域。而我们在低功耗应用过程中,通常来说主要会考量三个重要的指标,即低功耗模式下的最低电流、低功耗模式被唤醒到运行模式下的唤醒时间和低功耗模式的唤醒源,下一篇我会重点聊聊前两者,本篇的主要目的是第三个指标即唤醒源问题。

    在低功耗模式中,唤醒源通常有很多,包括外部IO中断唤醒(这个是最常用的,比如按键唤醒)、定时器唤醒(周期性的唤醒工作)或者通信接口唤醒(通过地址匹配或者边沿触发唤醒)等等(不多说了,都放在等等里面吧,呵呵),其中本篇博客就说说Kinetis L系列UART通信接口唤醒的方式。

    Kinetis KL25有三个UART接口即UART0、UART1和UART2,其中UART1和UART2的时钟源是固定的只能选择Busclock,而UART0的时钟源则比较灵活,可选择Busclock、晶振电路OSC的输出时钟或者芯片内部自带的低速或者高速时钟,这也就决定了在进入低功耗模式下UART1和UART2则无法保证模块继续工作(因为Busclock已经停止),而UART0则可以通过选择内部时钟源来保证其在低功耗模式下可以继续保持接收数据的standby,然后通过对UART0发送数据来唤醒CPU到运行模式而且用来唤醒的数据也可以被接收过来,但是这种方法在低功耗模式下会给整个系统带来额外功耗(相当于UART0一直在低功耗模式下运行着),我测算过大概有60uA左右,这就需要折衷根据自己的应用来考量,这种方法可以保证第一个数据不丢失,保证实时性,在某些应用中可能第一发送过来的就是有效数据。但是在大多数应用中,我觉着这种方法带来的功耗增加是得不偿失的,对功耗非常敏感的应用这个额外的电流是不可接受的,而这种应用又对实时性没有要求那么高,这样该怎么办呢?

    放心好了,飞思卡尔当然替我们想好了。KL25这三个UART接口除了UART0可以支持低功耗模式下运行保证接收数据的实时性之外,它们三个还都支持边沿唤醒能力,即UART模块在低功耗模式下也进入休眠状态(不消耗额外的电流),也就是即使是UART0我们也可以通过配置让其在低功耗模式下不再工作,而当芯片的对应这三个模块的RxD管脚有数据到达的时候会将CPU唤醒到运行态(因为RS232协议start位是一个低跳变)。

    当然,这两种方法都是可以在KL25上支持的,具体选用哪种方法还是要看我们大家的具体需求了,总之衡量着使用就是了,或者将两者结合起来使用也不失一种良策。全部代码我就不上传了,只贴出这两种方式对UART初始化的部分,其他的只需要自己去写好UART的中断服务函数就好了,如下:

(1)UART0在低功耗模式下保持低功耗standby,当数据到达时唤醒CPU并保存该数据:

void uart_lowpower_configure(void)
{
      SIM_SOPT2 &= ~SIM_SOPT2_UART0SRC_MASK;
      SIM_SOPT2 |= SIM_SOPT2_UART0SRC(3); // select the MCGIRCLK as UART0 clock source
      
      MCG_C2 |= MCG_C2_IRCS_MASK;
      MCG_C1 |= MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK; // enable the IRCLK
      MCG_SC &= ~MCG_SC_FCRDIV_MASK;
      MCG_SC |= MCG_SC_FCRDIV(0);
      
      uart0_clk_khz = (fast_irc_freq / 1000); // UART0 clock frequency will equal the OSCERCLK frequency
     
      uart0_init (UART0_BASE_PTR, uart0_clk_khz, TERMINAL_BAUD); 
      
      UART0_C3 |= UART0_C3_NEIE_MASK | UART0_C3_ORIE_MASK  | UART0_C3_FEIE_MASK; 
      UART0_C2 |= UART0_C2_RIE_MASK;  // enable receive interrupt
      enable_irq (UART0SE_irq_no);
}


(2)UART0/1/2在低功耗模式下休眠,第一个到达RxD的数据唤醒CPU,不保证这个数据被接收:

void uart_lowpower_configure(void)
{

      UART0_BDH |= UART0_BDH_RXEDGIE_MASK; //edge triger
      enable_irq (UART0SE_irq_no);
}


好了,这部分就写这些了,可能文字性的东西比较多,如果有博友还不能理解欢迎博客下面留言。

未完待续~

附近为参考代码kinetis_kl46_sc_LowPower - UART0_WakeUp.zip