|
Снова про пониженного энергопотребления в AVR |
|
|
|
Nov 12 2013, 07:44
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 18-09-12
Из: Орёл
Пользователь №: 73 591

|
Здравствуйте. Я понимаю что данная тема многократно поднималась и документации должно быть много. Я просто хотел уточнить, правильно ли я всё делаю. Имеется AVR Studio 6. И tiny2313 Рабочая частота - 8 МГц. Напряжение - 5 В. Надо его на время переводить его в режим пониженного энергопотребления. Имеются разрешённые и используемые внешние прерывания. Собственно, говоря, внутри ISR этих прерываний вся программа и работает. Почитав даташит, сделал так: Код unsigned long m_sleep_counter = 0;
... ... ...
main() { ..... ..... .....
while(1){ if (++m_sleep_counter > 10000){ m_sleep_counter = 0; sleep_enable(); set_sleep_mode(0);
} ..... } К сожалению сейчас скорость выхода из спящего режима на макете оценить сложно. Поэтому имеются вопросы: Ток потребления при переходе из активного режима в спящий (IDLE) падает с 12 до 5 мА. Как-то много остаётся, или я ошибаюсь? Какая скорость выхода из спящего режима (IDLE)? Надо ли что-то конфигурировать для определения условия выхода из спящего режима?
|
|
|
|
|
 |
Ответов
(1 - 8)
|
Nov 12 2013, 09:44
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 18-09-12
Из: Орёл
Пользователь №: 73 591

|
Да, спасибо, есть ноги на ввод с PullUpom. Попробую. Скажите, а если придётся в режим power down переводить, какие возможные сложности могут возникнуть? И скажите. На этом форуме нашёл подобную тему ( Как правильно выйти из "спящего режима"). Там, в частности, написано: Цитата И еще. Когда прерывание выводит процессор из спящего режима, то прежде чем перейти к обработчику прерывания, процессор выполнит сначала следующую за командой SLEEP команду. Поэтому следующей командой не стоит сразу ставить CLI, если хотите обеспечить обработку прерывания, а лучше поставить NOP. Это может влиять на что-либо ещё?
|
|
|
|
|
Nov 12 2013, 10:20
|
Гуру
     
Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295

|
О сложностях вы лучше в даташите прочтите, я делал это давно, деталей не помню и вводить вас в заблуждение не хочу. Цитата(vladimir_orl @ Nov 12 2013, 13:44)  Когда прерывание выводит процессор из спящего режима, то прежде чем перейти к обработчику прерывания, процессор выполнит сначала следующую за командой SLEEP команду. Поэтому следующей командой не стоит сразу ставить CLI, если хотите обеспечить обработку прерывания, а лучше поставить NOP. Там неправильно написано. Правильно - в документации (сначала выполняется обработчик, а затем - команда): Цитата If an enabled interrupt occurs while the MCU is in a sleep mode, the MCU wakes up. The MCU is then halted for four cycles in addition to the start-up time, executes the interrupt routine, and resumes execution from the instruction following SLEEP. Чуть ниже в том же документе рассказано, какие узлы и как влияют на потребление в спящем режиме. Вам придется все это изучить ...
|
|
|
|
|
Nov 14 2013, 06:36
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 18-09-12
Из: Орёл
Пользователь №: 73 591

|
Разобрался с режимом Idle. Там всё просто: Код #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h>
unsigned long m_value = 0; unsigned long m_counter = 0;
void my_delay(){ for (m_value = 0; m_value < 300; ++m_value){ asm("nop"); } }
ISR(INT1_vect) // Выставление данных { asm("nop"); m_counter = 0; sleep_disable(); }
ISR(INT0_vect) // Чтение данных { asm("nop"); m_counter = 0; sleep_disable(); }
int main(void) { cli(); MCUCR = 0x0B; GIMSK = 1 << INT0 | 1 << INT1; DDRB = 0xFF; asm("sei"); while(1){ my_delay(); PORTB = 0; my_delay(); PORTB = 0xFF; if (++m_counter > 5){ // sleep_enable(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); set_sleep_mode(SLEEP_MODE_IDLE); asm("sleep"); } } } Светодиод помигал 5 раз, МК остановился. Кнопочку нажали - обработка прерывания, опять работаем. А вот с режимом Power Down как-то сложнее. Засыпает, но просыпаться не хочет. Где-то читал, что внешние прерывания только по уровню должны быть. Думаю, как бы их переключить. Точнее там в коде так: Код sleep_enable(); // set_sleep_mode(SLEEP_MODE_PWR_DOWN); set_sleep_mode(SLEEP_MODE_IDLE);
|
|
|
|
|
Nov 14 2013, 07:02
|
Гуру
     
Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295

|
Цитата(vladimir_orl @ Nov 14 2013, 10:36)  Где-то читал, что внешние прерывания только по уровню должны быть. В даташите написано: Цитата Only an External Reset, a Watchdog Reset, a Brown-out Reset, USI start condition interrupt, an external level interrupt on INT0, or a pin change interrupt can wake up the MCU. This sleep mode basically halts all generated clocks, allowing operation of asynchronous modules only. Note that if a level triggered interrupt is used for wake-up from Power-down mode, the changed level must be held for some time to wake up the MCU. Т.е., или прерывание по уровню (не по фронту !), или "pin change interrupt" ...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|