|
Как правильно выйти из "спящего режима" |
|
|
|
Jul 2 2007, 21:17
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 15-05-07
Пользователь №: 27 727

|
Махаюсь со своим первым проектом - возникает уйма вопросов, большинство из которых решается не без помощи настоящего форума. Есть задача. ATTINY2313 "спит". По приходу лог. "0" (хотя, схемотехнически несложно поменять и на "1") на INT0 проц должен проснуться и выполнять определенные функции. В дальнейшем, этот же вывод процессора должен уже будет для этого же сигнала использоваться как вход порта. Вот кусок программы:
sei(); set_sleep_mode (SLEEP_MODE_IDLE); cli (); ....
Процессор, вроде как не просыпается... хотя не уверен. А как определить? Подскажите, что неправильно в исходнике?
Спасибо!!!
Сообщение отредактировал Jagupop - Jul 2 2007, 21:18
|
|
|
|
|
Jul 3 2007, 02:45
|

Mute Beholder
  
Группа: Свой
Сообщений: 260
Регистрация: 4-04-07
Из: Третья планета от Солнца
Пользователь №: 26 754

|
Цитата(Jagupop @ Jul 3 2007, 04:17)  sei(); set_sleep_mode (SLEEP_MODE_IDLE); cli (); ....
Процессор, вроде как не просыпается... хотя не уверен. А как определить? Подскажите, что неправильно в исходнике? Видимо WinAVR? Если так, то set_sleep_mode() выбирает режим "сна", но еще не загоняет процессор в сон. Делать надо так: Код set_sleep_mode(SLEEP_MODE_IDLE); // выбираем "тип сна" sleep_enable(); // разрешаем "засыпать" ... // код до засыпания sleep_cpu(); // заснуть .... // код после просыпания И еще. Когда прерывание выводит процессор из спящего режима, то прежде чем перейти к обработчику прерывания, процессор выполнит сначала следующую за командой SLEEP команду. Поэтому следующей командой не стоит сразу ставить CLI, если хотите обеспечить обработку прерывания, а лучше поставить NOP.
--------------------
Common sense is not so common.
|
|
|
|
|
Jul 3 2007, 21:44
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 15-05-07
Пользователь №: 27 727

|
Цитата main() { set_sleep_mode(xx) sei();
for(;;) { do_smth(); sleep(); } Прошу прощения... А можно "разжевать" построчно - что для чего? Чтой-то недопонимаю. Маловато еще знаний. Спасибо.
|
|
|
|
|
Jul 3 2007, 22:01
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата А можно "разжевать" построчно - что для чего? можно. Код начало программы
настроить периферию (порты, ацп, uart и т.п. все с чем собираетесь работать) разрешить режим сна (bit SE в MCUCR) разрешить прерывания (sei) Далее бесконечный цикл 10: Выполнить какие-то поточные действия Уснуть до следующего прерывания goto 10 При старте программы настраивается периферия, разрешается режим сна и прерывания, выполняются какие-то рутинные действия и проц засыпает на команде sleep. При возникновении любого прерывания (в режиме Idle) проц проснется, первой инструкцией которую он выполнит будет GOTO 10, потом он войдет в обработчик прерывания которое его пробудило, выполнит обработку прерывания, потом вернется к строчке 10: - выполнит какие-то поточные действия и на команде sleep() снова уснет... и так по кругу.
|
|
|
|
|
Jul 5 2007, 18:34
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 15-05-07
Пользователь №: 27 727

|
Прям не знаю...
GIMSK = 0b01000000; set_sleep_mode (SLEEP_MODE_IDLE); sleep_enable (); sei(); sleep_cpu (); sleep_disable (); PORTB = 0xFF; // проверяю подключенным светодиодом.
На INT0 появляестя лог. "1" . Не пойму то ли не "засыпает" то ли не "просыпается". Контролирую подключенным к порту B светодиодом. В чем ошибка?
|
|
|
|
|
Jul 5 2007, 22:38
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(MSprut @ Jul 5 2007, 16:38)  Вообще даташиты рекомендуют выбирать и разрешать режим сна непосредственно перед командой SLEEP. Давайте еще и уарт будем инициализировать перед отправкой каждого байта. Вообще нет таких рекомендаций в даташитах и быть не может. Цитата(Jagupop @ Jul 5 2007, 21:34)  На INT0 появляестя лог. "1" . Не пойму то ли не "засыпает" то ли не "просыпается". Контролирую подключенным к порту B светодиодом. В чем ошибка? Обработчик INT0 у вас есть? Полный код приведите. sleep_disable() - делать не нужно. сам по себе mcu не уснет.
|
|
|
|
|
Jul 6 2007, 06:38
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 15-05-07
Пользователь №: 27 727

|
Ну вот полный...
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <util/delay.h>
#define Freq 4000000
unsigned char z;
int zaziganie (z) { char i; z = 0; for (i=0; i<60; i+=1) { if ((PIND & 0x04) == 0); else z += 1; _delay_loop_2 (100); } return z; }
//void presskey (void)
int main (void) { DDRD = 0x00; PORTD = 0xFF; DDRB = 0b11111100; PORTB = 0b00000000; ACSR = 0b00000000; GIMSK = 0b01000000; label1: set_sleep_mode (SLEEP_MODE_IDLE); sleep_enable (); sei(); sleep_cpu (); sleep_disable (); PORTB = 0xFF; zaziganie (z); if (z < 30) goto label1; _delay_loop_2 (1000); PORTB = (PINB^0b10010000); //presskey (); label2: zaziganie (z); if (z > 30) goto label2; else goto label1; }
|
|
|
|
|
Jul 8 2007, 12:59
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
JagupopПроэмулировал вашу программу в железе. Чип пробуждается по 0 на INT0 и прыгает по адресу 0x0001, оттуда в "аварийный" обработчик, который отправляет его уже по RESET вектору адрес 0x0000, далее повторный запуск main и все. Дальше иструкции sleep естессно код не исполняется, и со стороны видно как-будто чип не пробуждается. чтобы все работало добавьте в программу хотя бы пустой обработчик Int0 Цитата SIGNAL (INT0_vect) { } Еще, Int0 - у вас настроен "по уровню", а лучше настроить "по фронту".
|
|
|
|
|
Jul 9 2007, 23:50
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 15-05-07
Пользователь №: 27 727

|
ЛЮДИ!!! ЧЕЛОВЕКИ!!! Помогите!!! Задолбался совсем. Ну нихрена не пойму - что не так?
GIMSK = 0b01000000; //разрешение прерываний по входу INT0 for (a=0; a<100; a+=1)
{ _delay_loop_2 (30000); //задержка }
set_sleep_mode (SLEEP_MODE_IDLE); //выбор типа SLEEP MODE sleep_mode (); // спи, гад! sei (); //глобальное разрешение прерываний ISR (INT0_vect); PORTB = (PINB^0x08); //включить светодиод 1 cli (); label1: goto label1;
С появлением лог. "0" на INT0 должен загореться светодиод. Пробую по-разному. Или не загорается вовсе или загорается сам по себе. Уже махаюсь немеряно времени. Что не так? Не пинайте сильно - учусь, учусь... Спасибо.
|
|
|
|
|
Jul 12 2007, 17:03
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 15-05-07
Пользователь №: 27 727

|
defunct, я Вас пыталсявыловить в ICQ - все безрезультатно. В общем, когда вставляю в программу:
SIGNAL (INT0_vect) { }
при трансляции появляются такие warning'и:
main.c: In function `main': main.c:43: warning: static declaration of '__vector_1' follows non-static declaration main.c:42: warning: previous declaration of '__vector_1' was here
А результат - тот же.
|
|
|
|
|
Jul 12 2007, 20:22
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Jagupop @ Jul 12 2007, 20:03)  defunct, я Вас пыталсявыловить в ICQ - все безрезультатно. Я только дома аську читаю, уже вам отписал. Цитата при трансляции появляются такие warning'и: main.c: In function `main': main.c:43: warning: static declaration of '__vector_1' follows non-static declaration main.c:42: warning: previous declaration of '__vector_1' was here Вынесите обработчик прерывания из main(): SINGAL (INT0_vect) { } main() { .. }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|