我的孤独 发表于 2019-9-21 18:46:52

关于省电模式的探索以及ACD、ADC配置说明

本帖最后由 我的孤独 于 2019-9-21 19:17 编辑

前言
资料来源:
(1)2月2号-外置采集温度_让arduino用2颗5号电池运行1年以上                                 
(2)C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\avr目录下的sleep.h里的例程
(3)ATMEGA328P详细资料数据手册(提取码:qft2),第302页(ACSR寄存位配置)和第319页(ADCSRA寄存位配置)
(4)ACSRACSR寄存位配置中文翻译

因为本人在做一个便携的自动浇水系统,只用电池和太阳能板供电,所以不浇水时需要用到休眠模式,以增加续航。
浇水部分已经完成,休眠部分完成一半还未整合进浇水系统,先上浇水系统给大家看看,看视频点这里。
本文使用干掉电源指示灯的arduino pro mini进行测试。
https://www.geek-workshop.com/forum.php?mod=image&aid=48450&size=300x300&key=bc70ba2931fc501b&nocache=yes&type=fixnone
https://www.geek-workshop.com/forum.php?mod=image&aid=48451&size=300x300&key=6f553938ef56e491&nocache=yes&type=fixnone
ACD、ADC的开关配置
接下来是本篇文章的重点之一,ACD、ADC的配置。
我查询了ATMEGA328P详细资料数据手册以及网上的其他文章,得知:
休眠前关闭ACD和ADC更省电,0.12ma,不关ACD和ADC就休眠,0.26ma,这样我们又省了一半的电。
但是不知道关闭ACD和ADC后会不会对后续的外部中断的唤醒休眠有影响,有待测试。
接下来我们看一下如何开启和关闭ACD、ADC,代码如有错误请指出。
//ON ACD
ACSR &= ~_BV(ACIE);   //禁止模拟比较器中断后再对ACD位操作,否则ACD位变化会发生中断,写入0关闭
ACSR &= ~_BV(ACD);    //开启模拟比较器
ACSR |= _BV(ACIE);    //开启模拟比较器中断
//ON ADC
ADCSRA |= _BV(ADEN);   //ADC使能开启
ADCSRA |= _BV(ADIF);   //ADC中断使能开启

//OFF ACD
ACSR &= ~_BV(ACIE);    //禁止模拟比较器中断后再对ACD位操作,否则ACD位变化会发生中断,写入0关闭
ACSR |= _BV(ACD);      //关闭模拟比较器 ,写入1关闭
//OFF ADC
ADCSRA |= _BV(ADIF);   //清除标志,写1清除
ADCSRA &= ~_BV(ADIE);//ADC中断使能关闭
ADCSRA &= ~_BV(ADEN);//ADC使能关闭,写入0关闭这段代码,也就是ACD、ADC的配置说明可以从手册里查出。
第302页(ACSR寄存位配置)和第319页(ADCSRA寄存位配置)。
https://www.geek-workshop.com/forum.php?mod=image&aid=48453&size=300x300&key=9d208892a81a411a&nocache=yes&type=fixnonehttps://www.geek-workshop.com/forum.php?mod=image&aid=48452&size=300x300&key=e71798b2baffcf7e&nocache=yes&type=fixnone

休眠模式
接下来是休眠模式,我直接使用了文章2月2号-外置采集温度_让arduino用2颗5号电池运行1年以上里的部分代码,并做了一下改进和注释。原文章把休眠模式已经说的很清楚了,我就不多做介绍了。需要注意的地方是sleep_mode()这个API,根据sleep.h文件里的说明使用sleep_mode()可能会在某些状态下失效。所以,根据例程,我将进入休眠模式的步骤改成:cli();                              //关闭全局中断,防止中断引起意外set_sleep_mode(SLEEP_MODE_PWR_DOWN);//这里设置睡眠模式sleep_enable();                     //开启休眠功能sei();                              //开启全局中断sleep_cpu();                        //进入休眠sleep_disable();                      //关闭休眠功能sei();                              //开启全局中断
所以,在休眠前是否要开关ADC/ACD,进入休眠的方式是否要使用sleep_mode()或者我的分步进入,看个人所需。





页: [1]
查看完整版本: 关于省电模式的探索以及ACD、ADC配置说明