一、前言
由于前段时间,一直有一位老哥一直在问s12zvm的休眠怎么做。私聊的问题有时间看到才会回复。但是断断续续的回复又说不清楚。于是就打算写这一片文章。
二、正文
第一步还是要去看数据手册对于stop mode的描述。如下图:
如上图,mcu有两种stop mode ,一个是伪stop。在这个mode中,系统时钟会停掉,但是晶振,RTI,COP和一些API可以被使能。缺点就是比stop mode电流大一点,但是唤醒速度比较快。另一种就是全stop了。
由于这款芯片主要是用于电机控制。所以在进入stop mode前一定要确保PMF,GDU,ADC模块的安全,这点在手册的85页有说明。一般来说,可以直接禁用所有的中断就行。
其次就是怎么去唤醒,端口AD, S, P和L提供引脚中断和键唤醒功能。相关的中断使能(PIE)以及上升或下降边缘的灵敏度(PPS)可以在每个引脚的基础上单独配置。端口中的所有位/引脚共享相同的中断向量。中断可以与引脚配置为输入或输出。当设置了端口中断标志(PIF)和相应的端口中断使能(PIE)中的一位时,就会产生中断。当CPU处于停止或等待模式(key-wakeup)时,引脚中断功能也能够唤醒CPU。
特别说明,在手册的293页有对这两种模式的详细说明。理解能力强的可以仔细去看看。
下面就讲讲我是怎么做的,先上代码:
DisableInterrupts;
CPMUCLKS_PSTP=0;
asm CLI;
asm NOP;
asm ANDCC #0x7F;
LP0CR_LPWUE = 1;
SCI0SR2_AMAP = 1; // alternate SCI0 registers Connect HV Input to SCI
SCI0ASR1_RXEDGIF = 1; /* clear flag*/
SCI0ACR1_RXEDGIE = 1; /* edge interrupt enabled for wake up*/
EnableInterrupts;
asm STOP;
首先就是禁用所有中断,CPMUCLKS_PSTP=0,就以为是要进入FULL stop mode。
接下来的 asm CLI 指的是:执行汇编指令 CLI CLI 指令禁用中断,以防止当前执行的程序被中断(interrupt) 打断;
asm NOP指的是: 执行的是一条空指令(单周期指令);
asm ANDCC #0x7F: 清除CCR中的s位以启用STOP指令;
由于我做的是lin休眠,所以接下来的操作就是对lin引脚的外部中断设置。
最后的ASM stop 才是真正的进入stop mode。
特别注意的是,当进入休眠模式时,程序是运行到ASM stop 就不再运行了。只有被唤醒时才会由asm stop继续运行下去。所以在唤醒时原有的时钟以及外设最好重新初始化一下。因为上面也提到当进入休眠时所有外设会失效。这种情况下,原有寄存器的配置可能会出现错误。
接下来我在重新初始化后又加了下面这一段代码:
CPMUCLKS_COPOSCSEL1 = 1; /* COP clock source is ACLK derived from a trimmable internal RC-Oscillator. In this case COPOSCSEL0 has no effect */
CPMUCLKS_CSAD = 1; /* COP is stopped in Stop Mode */
CPMUCLKS_PCE = 0; /* COP is stopped in Pseudo Stop Mode */
CPMUCOP = (0b011 & CPMUCOP_CR_MASK) | (0 & CPMUCOP_WRTMASK_MASK) | CPMUCOP_RSBCK_MASK | (0 & CPMUCOP_WCOP_MASK);
可能是由于我用lin唤醒的原因,需要加上上面那一段才能成功唤醒。但是问我的那位老哥用PS0端口的外部中断成功唤醒。至于为什么加上那一段我也忘了。
三、小结
在做休眠时,还是需要仔细的去看数据手册。特别要注意,所选用的端口是否可以用于唤醒。其次,上面只是我提供的一种方法,休眠时的电流大概在60~70uA 左右。那位老哥要求是在100以内,从他口吻中可以看出他也成功了。
由于也是很久之前做的了,好多细节也记不太清楚了。有错误的地方还请大佬能够指出。
谢谢。