|
2 страниц
1 2 >
|
 |
Ответов
(1 - 20)
|
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() { .. }
|
|
|
|
|
Jul 17 2007, 11:09
|
Участник

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

|
С прерываниями разобрался - проц. по приходу сигнала на INT0 "просыпается", выполняет поставленную задачу и снова "засыпает". Все красиво. Спасибо конференции. НО (!). Есть несколько другая задача, которую я не знаю как решить из-за небольшого опыта. В общем, проц. "спит". На INT0 постоянно сидит лог. 1. При появлении лог. 0 проц должен проснуться и выполнять, что ему указано. При этом на INT0 - лог. 0 держится постоянно. Лишь с появлением на INT0 лог.1 проц. должен выполнить определенные предпмсания и "заснуть" в ожидании очередного лог. 0 на INT0. Вот как это реализовать? Я так понимаю, в процессе работы INT0 должен "превращаться" в PD2? Спасибо.
|
|
|
|
|
Jul 17 2007, 11:34
|

Профессионал
    
Группа: Свой
Сообщений: 1 751
Регистрация: 4-08-05
Из: Великие Луки
Пользователь №: 7 360

|
Цитата При появлении лог. 0 проц должен проснуться и выполнять, что ему указано. Прерывание по спаду уровня(falling edge). перестраиваем Перенастроить прерывание по фронту(rising edge) и вот Цитата Лишь с появлением на INT0 лог.1 проц. должен выполнить определенные предпмсания и "заснуть" в ожидании очередного лог. 0 на INT0.
--------------------
Андрей Смирнов
|
|
|
|
|
Jul 19 2007, 12:26
|
Участник

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

|
Чуток не так... По falling edge проц выходит из спящего режима уходит на подпрограмму обработки прерывания. На INT0 все это время "сидит" лог. 0. Тут все хорошо. Но "заснуть"снова он должен после прихода на INT0 логической единицы! А не перед этим. Как это осуществить? Спасибо.
|
|
|
|
|
Jul 19 2007, 12:43
|

Профессионал
    
Группа: Свой
Сообщений: 1 751
Регистрация: 4-08-05
Из: Великие Луки
Пользователь №: 7 360

|
если так? Цитата По falling edge проц выходит из спящего режима уходит на подпрограмму обработки прерывания. Цитата На INT0 все это время "сидит" лог. 0. Залетаем в прерывание и анализируем наличие"0", если, верно, делаем что либо. Заодно перенастраиваем прерывание по фронту. При появлении фронта, залетаем в прерывание и снова проверяем наличие "0", его нет соответственно, делаем другое, то есть отправляем спать. В прерывании лучше много не делать, а устанавливать флаги. Их обрабатывать а программе.
--------------------
Андрей Смирнов
|
|
|
|
|
Jul 19 2007, 13:17
|
Участник

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

|
Цитата Залетаем в прерывание и анализируем наличие"0", А разве можно в прерывании процессор снова заставить "уснуть"? А куда процессор уйдет после просыпания в этом случае? Разве не на эту же самую подпрограмму обработки прерывания, в которой он и так уже находится?
Сообщение отредактировал Jagupop - Jul 19 2007, 13:18
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|