freetech

ADC模块在低功耗设计中的一个特殊应用

0
阅读(22960)

一般大家使用单片机中的ADC模块无非是用来进行模拟输入信号的测量,这是每个人都能想到并能理解的。最近研究一个低功耗设计,需要验证功耗极限,尝试了很多种方法,最后另类使用了ADC模块,得到不错的效果。


该设计是这样的:单片机为9S08QG4,外面接加速度传感器MMA7360,其供电电源由单片机的一个IO引脚控制。这是一个类似于计步器的应用,整个系统工作时要求平均功耗小于100uA。设计思路大概是这样:QG4进入STOP3休眠模式,每隔8ms左右由RTI模块唤醒一次;每唤醒3次即间隔时间为24ms就接通传感器的电源让其工作并采样当前加速度值,然后对采样到的AD值作算法运算实现特定功能。看似简单,但有一个问题必须考虑,就是传感器通电后并不是立即就能工作的,它必须在上电后1ms左右才能进入稳定的工作状态。所以一个简单直观的工作过程看起来应该是这样的:

24ms间隔唤醒->启动传感器电源->软件延时1ms->AD采样->关闭传感器电源->算法计算并显示结果->进入STOP3休眠。

但这样的一个流程单片机在进行1ms软件延时时什么事情也不干但在消耗大量电流,实在太浪费。稍微改动一下流程如下:

24ms间隔唤醒—>启动传感器电源->算法计算上次保存的AD值并显示结果(约500uS)->软件延时500us->AD采样并保存给下次用->关闭传感器电源->进入STOP3休眠。

这样改动后单片机无所事事的等待时间缩短为500us,平均电流大大降低,但还是远远超过100uA的指标要求。
现在问题的关键是如何让单片机在实现这500uS延时的同时消耗最小的电流?让单片机在这段时间进入休眠似乎是不二的选择,但如何让其在500us左右能自己醒过来就要费点心思了:RTI唤醒最短时间间隔为8ms,其它唤醒的手段似乎都没有定时的功能。想了老半天,最后瞄上了ADC模块。

S08系列单片机的ADC模块自带有一个独立的低频振荡时钟源。当单片机处于STOP模式下休眠时,ADC模块还可以基于该时钟独立进行ADC转换,并在转换结束时唤醒单片机。虽然该时钟的频率没有明确标定,但每做一次ADC所需的时钟节拍数是固定的(如果结果位数固定),因此每次做ADC所需的时间基本一致。现在将该ADC内部时钟的分频系数设成最大,让其以最慢的速度进行AD转换,虽然此时AD转换的结果是不准确的(时钟速度太慢,超出了正常ADC所要求的时钟频率范围),但我们对AD值的大小并不感兴趣,而在乎它转换所需的时间长短。尽管以最慢的数度做一次AD的时间也大大小于500us,但我们可以重复做几次AD,以实现大约500us的延时时间,同时在该延时过程中尽量让单片机进入休眠。最后实测的数据平均电流小于100uA,安全满足要求。


部分测试代码如下:

//初始化系统配置寄存器
SOPT1 = 0b11110011; //STOP enabled, RESET pin applied
SPMSC1 = 0b00000000; //disable LVD for everything
SPMSC2 = 0b101; //set for entering STOP3 mode

//初始化ADC模块
ADCSC1 = 0b01000111; //one-shot ADC on ADCH7
ADCSC2 = 0b00000000; //ADC software trigger
ADCCFG = 0b11111011; //low power, long sampling time, 10 bit, Asynchronous clock

//产生约500us延时

ADCSC1 = 0b01000111; //triger an ADC
asm("stop"); //ADC启动后立即进入休眠
//AD结束时唤醒单片机,程序从这里继续往下运行
//一次AD所产生的延时为250us左右

//重复进行一次250us左右的延时
ADCSC1 = 0b01000111; //triger an ADC
asm("stop");