Jump to content
-=FISHER=-

Спящий режим МК AVR

Recommended Posts

Сегодня пошаманю со спящими режимами. Возможно, это глюк протеуса.

Цитата

if (!(PIND&0x4)) //обработка нажатия основной кнопки

Лучше использовать сдвиг и именованную константу, иначе можно подумать что кнопка висит на PD4, а не на PD2:
 

#define BTN 2

if(! (PIND & (1<<BTN)) )
Цитата

FRONT_LAMP_MODE++; //увеличиваем значение переменной режима

В Си принято капсом обозначать константы, а не переменные.

Цитата

PORTB=0x00; //выключаем все светодиоды
                        STROB_MODE=0; //отключаем режим стробоскопа
                        OCR1A=128; //переводим яркость переднего фонаря в режим "БЛИЖНИЙ СВЕТ"
                        FRONT_LAMP_MODE=0; //устанавливаем нулевой режим
                        sleep_cpu(); //отправляем МК в СОН
                        break;

не увидел запрещения-разрешения прерывания INT0. Без этого оно будет вызываться постоянно пока кнопка нажата.

Цитата

sei(); //глобально разрешаем прерывания
    counter_init(); //инициализируем счетчик    
    port_init(); //инициализируем порты
    PWM_timer_init(); //инициализируем ШИМ
    int_init(); //инициализируем прерырвания
    sleep_init(); //инициализируем режим сна
    sleep_cpu(); //засыпаем

разрешать прерывания стоит после настроек а не до них. Еще неплохо бы явным образом сбросить флаги прерываний.


Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Share this post


Link to post
Share on other sites
55 минут назад, COKPOWEHEU сказал:

Сегодня пошаманю со спящими режимами. Возможно, это глюк протеуса.

Было бы здорово! Заранее спасибо!

55 минут назад, COKPOWEHEU сказал:

не увидел запрещения-разрешения прерывания INT0. Без этого оно будет вызываться постоянно пока кнопка нажата.

Поправил, правда это делается в регистре GICR, то есть

GICR |= (1<<INT0) //разрешаем прерывания

GICR &= ~(1<<INT0) //запрещаем прерывания

При включении прерываний, по умолчанию включено прерывание именно по низкому уровню на INT0, остальные виды прерываний уже настраиваются в регистре  MCUCR.

Так же учту все остальные поправки. Спасибо!

55 минут назад, COKPOWEHEU сказал:

не увидел запрещения-разрешения прерывания INT0. Без этого оно будет вызываться постоянно пока кнопка нажата.

Правда всё равно немного не понимаю, выглядит это всё вот так:

GICR |= (1<<INT0) //разрешаем прерывания
sleep_cpu(); //отправляем МК в сон
GICR &= ~(1<<INT0) //запрещаем прерывания

а как же же МК должен проснуться, если прерывания мы запретили?...Вот сейчас проэксперементировал и сначала запретил прерывания, а потом разрешил, после чего МК у меня успешно заснул. Но теперь не хочет просыпаться, сколько кнопку не тыкай...

GICR &= ~(1<<INT0) //запрещаем прерывания
sleep_cpu(); //отправляем МК в сон
GICR |= (1<<INT0) //разрешаем прерывания

 

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Заметил интересную особенность, в Протеусе у меня МК просыпается даже если я вообще никак не инициализирую прерывания!

То есть даже если закомментировать эти строчки. МК всё равно просыпается при появлении "ЛОГ.0" на PD2.

//GICR |=(1<<INT0);
//sei();

Теоретически это ведь не возможно?

А я понял почему! У меня в процедуре инициализации таймера-счетчика есть вот такая строчка SREG = (0x80), которая устанавливает в единичку бит I, регистра SREG, который в свою очередь и включает глобальные прерывания.

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Драйверы MOSFET/IGBT Infineon – силой нужно управлять!

Специалисты Infineon усовершенствовали традиционные кремниевые MOSFET и IGBT и выпустили компоненты на базе принципиально иных материалов – нитрида галлия и карбида кремния. Мы создали подборку полезных материалов, чтобы вы разобрались во всех тонкостях и стали экспертом по управлению силовыми приборами нового поколения CoolMOS, CoolGaN, CoolSiC!

Подробнее

Проверил. Вот этот набросок работает нормально. Единственное что по низкому уровню протеус генерирует всего одно прерывание, хотя должен постоянно. В моем коде используется файл pinmacro.h, это макросы для удобной работы с портами. Он есть по ссылке в моей подписи, но и без того несложно понять.

Прерывание разрешаем только перед уходом в сон. Иначе оно будет отъедать 90% скорости на постоянный вызов пустого обработчика. А после выхода из сна - запрещаем. Грубо говоря, не акцентируясь на конкретном прерывании, так

	sei(); //разрешаем прерывание только когда оно нужно.
	sleep_cpu(); //эта команда не завершится пока контроллер не проснется
	cli(); //и уже когда он проснулся, снова запрещаем прерывание
	

sleep_my.c


Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Share this post


Link to post
Share on other sites

Снижена цена на DC/DC и AC/DC преобразователи Mornsun в Компэл!

Компэл снизил цены на всю продукцию Mornsun. В ассортименте – как широко известные и популярные позиции, так и новинки. Доступны AC/DC, неизолированные DC/DC-преобразователи или импульсные стабилизаторы (семейство K78/R3), изолированные DC/DC, и новейшее поколение R4.

Подробнее

7 часов назад, -=FISHER=- сказал:

Сразу после выхода из сна убеждаемся что кнопка ТОЧНО нажата а не была короткая помеха, иначе снова уходим в сон(цикл постоянного входа в сон, пока не будет установлен фак

Подскажите пожалуйста, как лучше и проще это сделать в моем случае?


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Новинки гибридных конденсаторов: преимущества технологии

Гибридные конденсаторы унаследовали от полимерных конденсаторов такие достоинства как устойчивость к импульсам тока, повышенную надежность и низкое собственное сопротивление, а также высокую емкость и низкий ток утечки, как у алюминиевых электролитов. Благодаря этому гибридные конденсаторы могут с успехом заменить традиционные алюминиевые конденсаторы.

Подробнее

Цикл на 10 итераций, внутри задержка на 2..4мс и считывание кнопки - если минимум 5 раз подряд кнопка нажата, то засчитать нажатие иначе - переходим к команде входа в спящий режим.


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites
1 час назад, Alexeyslav сказал:

Цикл на 10 итераций, внутри задержка на 2..4мс и считывание кнопки

Цикл for как я понимаю?

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Можешь и for, в языке множество способов организовывать циклы, вплоть до разворачивания в линейный код...


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites
11 час назад, Alexeyslav сказал:

Можешь и for

Этот цикл лучше записать вначале main не трогая весь остальной код что у меня есть уже?


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

А смысл тогда? Проверка нужна везде где ждёшь нажатия а не только на старте...


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites
2 минуты назад, Alexeyslav сказал:

А смысл тогда?

Плоховато понял, не могли бы Вы хотя бы в общих чертах набросать эту мысль в коде?

Edited by -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Если у тебя проверка на нажатие только в начале цикла, то туда и ставь. А смысл такой проверки - чтобы отсеять ложные срабатывания и не реагировать на дребезг. Иначе, контроллер же очень быстрый - воспримет дребезг как сотню нажатий и за это время 100 раз успеет поспать и что-то сделать согласно алгоритму. В принципе, может хватить лишь одной проверки спустя 20-40 мс после первой регистрации нажатия(срабатывание прерывания и выход из сна), но к хорошему надо привыкать и стараться делать как надо - потом этот алгоритм ещё в какой проект утащишь и т.д.


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites
11 час назад, Alexeyslav сказал:

 но к хорошему надо привыкать и стараться делать как надо - потом этот алгоритм ещё в какой проект утащишь и т.д.

Вчера набросал, вроде работает как надо, когда красиво допишу, здесь выложу для проверки, если вас не затруднит.


Мы все учились по-немногу, чему-нибудь и как-нибудь...

Share this post


Link to post
Share on other sites

Здравствуйте! Пишу программу для Atmega8a на Atmel Studio 7, эмулирую на Proteus 8. Решил ввести режим СНА так называемый  POWER DOWN для остановки тактового генератора (внутреннего или внешнего- без разницы).  Накидал строки для подготовки, сна и выхода из сна... Но! некорректно работает выход из сна. Родной атмеловский сайт и прочие мурзилки говорят, что при выходе из сна МК должен ПРОДОЛЖИТЬ работу с места спячки, а у меня чего-то поучается сон-и сразу после выхода из сна - в начало заголовка main по коду. Да, еще, выход из сна обеспечивается по INT0- так мне нужно.

Код ниже:

***************

// ATmega8a
#define F_CPU 1000000UL // частота МК 1МГц

#include <avr/interrupt.h>
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/io.h>  //  Подключили описание контроллера
#include <util/delay.h> // Подключили библиотеку задержек

int main(void)
{
    DDRD = 0b00000000;
    DDRC = 0b00110000; 
    PORTC |= (1 << PC4); 
    _delay_ms(1000);
    PORTC &= ~(1 << PC4);
    _delay_ms(1000);
    PORTC |= (1 << PC4);

                                     // set sleep mode
        GICR|=(1<<6);               //разрешаем прерывание по INT0
        GIFR|=(1<<6);
        MCUCR|=((0<<1)|(0<<0));     //прерывание по 0 сигнала на INT0
        sei();                      // разрешаем прерывания глобальные
        
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        cli();
    while(1)
    {
            if (PINC &= 1<<PC0) 
            {
                            // плюс внутри while планируется писат сой код....
                            // sleep_mode() has a possible race condition
        sleep_enable();
        sei();
        _delay_ms(1000);
        sleep_cpu();        // тут засыпаем и с этой же точки проснемся (по идее???   и дальше продолжить вниз по коду, зажечь диод на PC5)
    
        sleep_disable();
        GICR|=(0<<6);       // отключить прерывание по инт0
        GIFR|=(0<<6);
        
        PORTC |=(1<<PC5);     // идентификатор того что программа после сна выполняется дальше не перескакует в начало на main                     
            }
        sei(); 
      }
}

************************************************

Просто нужно именно, чтобы код продолжал выполняться дальше после сна, т.е.  не блымал светодиод на РС5, а не перескакивал на main в начало.

son.c

proteus.PNG

SLEPP_MODE.pdsprj

SLEPP_MODE.pdsprj.AdminPC.Admin.workspace

Share this post


Link to post
Share on other sites

А обработчик прерывания вы написали? При возникновении прерывания идет прыжок именно в обработчик и только после него обратно в программу. Если прерывание не нужно, объявите его как EMPTY_INTERRUPT(INT0_vect); вместо обычного ISR();


Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения


  • Блок питания 12В для светодиодных лент, 18-100 Вт

×
×
  • Create New...