реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Как правильно выйти из "спящего режима"
Jagupop
сообщение Jul 2 2007, 21:17
Сообщение #1


Участник
*

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



Махаюсь со своим первым проектом - возникает уйма вопросов, большинство из которых решается не без помощи настоящего форума.
Есть задача. ATTINY2313 "спит". По приходу лог. "0" (хотя, схемотехнически несложно поменять и на "1") на INT0 проц должен проснуться и выполнять определенные функции. В дальнейшем, этот же вывод процессора должен уже будет для этого же сигнала использоваться как вход порта. Вот кусок программы:

sei();
set_sleep_mode (SLEEP_MODE_IDLE);
cli ();
....

Процессор, вроде как не просыпается... хотя не уверен. А как определить? Подскажите, что неправильно в исходнике?

Спасибо!!!

Сообщение отредактировал Jagupop - Jul 2 2007, 21:18
Go to the top of the page
 
+Quote Post
Snaky
сообщение Jul 3 2007, 02:45
Сообщение #2


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.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 3 2007, 18:03
Сообщение #3


кекс
******

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



Цитата(Snaky @ Jul 3 2007, 05:45) *
а лучше поставить NOP.

Лучше ничего не ставить, а просто правильно построить программу:

Код
main()
{
   set_sleep_mode(xx)
   sei();

   for(;;)
   {
       do_smth();
       sleep();
   }

}
Go to the top of the page
 
+Quote Post
Jagupop
сообщение Jul 3 2007, 21:44
Сообщение #4


Участник
*

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



Цитата
main()
{
set_sleep_mode(xx)
sei();

for(;;)
{
do_smth();
sleep();
}


Прошу прощения... А можно "разжевать" построчно - что для чего? Чтой-то недопонимаю. Маловато еще знаний. Спасибо.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 3 2007, 22:01
Сообщение #5


кекс
******

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



Цитата
А можно "разжевать" построчно - что для чего?

можно.

Код
начало программы

    настроить периферию (порты, ацп, uart и т.п. все с чем собираетесь работать)
    разрешить режим сна (bit SE в MCUCR)
    разрешить прерывания (sei)
    
    Далее бесконечный цикл
10:
         Выполнить какие-то поточные действия
         Уснуть до следующего прерывания
goto 10


При старте программы настраивается периферия, разрешается режим сна и прерывания, выполняются какие-то рутинные действия и проц засыпает на команде sleep.
При возникновении любого прерывания (в режиме Idle) проц проснется, первой инструкцией которую он выполнит будет GOTO 10, потом он войдет в обработчик прерывания которое его пробудило, выполнит обработку прерывания, потом вернется к строчке 10: - выполнит какие-то поточные действия и на команде sleep() снова уснет... и так по кругу.
Go to the top of the page
 
+Quote Post
MSprut
сообщение Jul 5 2007, 13:38
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 225
Регистрация: 25-04-06
Из: Украина, Луганск
Пользователь №: 16 476



Вообще даташиты рекомендуют выбирать и разрешать режим сна непосредственно перед командой SLEEP.
Go to the top of the page
 
+Quote Post
Jagupop
сообщение Jul 5 2007, 18:34
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 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 светодиодом. В чем ошибка?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 5 2007, 22:38
Сообщение #8


кекс
******

Группа: Свой
Сообщений: 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 не уснет.
Go to the top of the page
 
+Quote Post
Jagupop
сообщение Jul 6 2007, 06:38
Сообщение #9


Участник
*

Группа: Новичок
Сообщений: 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;
}
Go to the top of the page
 
+Quote Post
acex2
сообщение Jul 6 2007, 12:13
Сообщение #10


Адепт
****

Группа: Свой
Сообщений: 520
Регистрация: 15-02-05
Пользователь №: 2 656



Цитата(defunct @ Jul 6 2007, 02:38) *
Вообще нет таких рекомендаций в даташитах и быть не может.


Datasheet ATMega88, стр.43:
"To avoid the MCU entering the sleep mode unless it is the programmer’s purpose, it is recommended to write the Sleep Enable (SE) bit to one just before the execution of the SLEEP instruction and to clear it immediately after waking up"
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 8 2007, 12:59
Сообщение #11


кекс
******

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



Jagupop
Проэмулировал вашу программу в железе.
Чип пробуждается по 0 на INT0 и прыгает по адресу 0x0001, оттуда в "аварийный" обработчик, который отправляет его уже по RESET вектору адрес 0x0000, далее повторный запуск main и все. Дальше иструкции sleep естессно код не исполняется, и со стороны видно как-будто чип не пробуждается.

чтобы все работало добавьте в программу хотя бы пустой обработчик Int0
Цитата
SIGNAL (INT0_vect)
{
}


Еще, Int0 - у вас настроен "по уровню", а лучше настроить "по фронту".
Go to the top of the page
 
+Quote Post
Jagupop
сообщение Jul 9 2007, 23:50
Сообщение #12


Участник
*

Группа: Новичок
Сообщений: 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 должен загореться светодиод. Пробую по-разному. Или не загорается вовсе или загорается сам по себе. Уже махаюсь немеряно времени. Что не так? Не пинайте сильно - учусь, учусь...
Спасибо.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2007, 10:03
Сообщение #13


кекс
******

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



Цитата(Jagupop @ Jul 10 2007, 02:50) *
Ну нихрена не пойму - что не так?

Я вам написал "что не так" в вашей программе. Вы пост то предыдущий хоть прочитали, прежде чем крик души изливать?
Go to the top of the page
 
+Quote Post
Jagupop
сообщение Jul 12 2007, 17:03
Сообщение #14


Участник
*

Группа: Новичок
Сообщений: 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

А результат - тот же.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 12 2007, 20:22
Сообщение #15


кекс
******

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



Цитата(Jagupop @ Jul 12 2007, 20:03) *
defunct, я Вас пыталсявыловить в ICQ - все безрезультатно.

bb-offtopic.gif
Я только дома аську читаю, уже вам отписал.

Цитата
при трансляции появляются такие 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()
{
..
}
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 15:11
Рейтинг@Mail.ru


Страница сгенерированна за 0.01479 секунд с 7
ELECTRONIX ©2004-2016