Перейти к содержанию
    

STM32L151 режим STOP

Мозг дымится, прям беда какая то, никак не приручить STOP режим

Есть кнопка 1, на которую нужно однократно нажать и ввести мк в стоп. Будить планирую другой кнопкой.

void EXTI2_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line2) != RESET)
    {       
        NVIC_DisableIRQ(EXTI2_IRQn);        
        stop_enable = 1;
        LED1_TOGGLE();
        EXTI_ClearITPendingBit(EXTI_Line2);        
    } 
}

 

В основном цикле чекаю флаг кнопки. После его срабатывания ухожу в стоп. Но беда в том, что контроллер не засыпает. Детектирую это светодиодом 2.

while(1) {                      
       if(stop_enable == 1)  { 
           PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
           stop_enable = 0;
           LED2_TOGGLE(); 
           NVIC_EnableIRQ(EXTI2_IRQn);       
       }           
}

 

Если вводить в сон не по кнопке, то все ок, но нужно именно по кнопке. Создалось впечатление что NVIC_DisableIRQ(EXTI2_IRQn) не отрабатывает, проверил отдельно от этого куска кода - работает. По отдельности все работает, сама проблема в том что именно этот кусок не работает, как сделать по другому не понятно.

ЗЫ видел аналогичные темы, выдергивание swd не помогло. Ввожу в стоп не в прерывании.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В прерывании нельзя засыпать.

Но есть возможность заснуть по выходе из прерывания.

Вам потребуется бит SLEEPONEXIT: SCB->SCR |= SCB_SCR_SLEEPONEXIT;

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

Проверьте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда вариант более простой - на обработчике событий.

Создаёте глобальную переменную. В прерывании кнопки устанавливаете её в, допустим, 1.

В бесконечном цикле проверяете, равна ли переменная единице и если так - усыпляете кристалл. От прерывания отвязались.

 

Переменная, кстати, volatile? Можете проверить в отладчике, меняется ли она вообще. И посмотреть дизассемблированный код, который был сгенерирован.

Некоторые переменные порой... выбрасываются.

Изменено пользователем AlanDrakes

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы издеваетесь надо мной? Так и сделано stop_enable глобальная переменная, если 1 уходим в стоп, проблема в том, что не уходит он так в стоп. Переменная volatile.

Изменено пользователем data_stack

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня работает отлично вот такой код:

volatile char test = 0;

void EXTI2_IRQHandler(void) {
    test = 1;
    EXTI->PR = 4; // Очищаем бит ожидающего прерывания
};
(В main())
<...>
    EXTI->RTSR |= 4; // По фронту импульса
    EXTI->IMR |= 4; // Разрешить генерировать прерывание
    NVIC_EnableIRQ(EXTI2_IRQn); // Разрешить само прерывание
    while (1) {
        if (test == 1) {
            test = 0;
            PWR->CR |= PWR_CR_PDDS | PWR_CR_LPSDSR; // Маломощный сон
            SCB->SCR |= SCB_SCR_SLEEPDEEP; // Последний бит, позволяющий именно STOP
            __WFI();
        };
    };
<...>

 

Буквально только что заставил работать код на реальном железе. Да, у меня есть плата с этим кристаллом.

Останавливается именно после команды __WFI(); и ждёт ближайшего следующего прерывания.

Изменено пользователем AlanDrakes

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поднимаю тему, перетестил много раз - не работает. Упростил задачу, нужно включить контроллер и уйти сразу в standby, если wakeup нажат, то проснуться пересброситься и снова уйти в сон.

int main()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    PWR_WakeUpPinCmd(PWR_WakeUpPin_3, ENABLE);
  
    delay_ms(5000);
    PWR_EnterSTANDBYMode();
}

 

Что выходит на деле: в первый раз все по феньшую - контроллер уходит в сон, жмакаем wakeup и все ломается, контроллер просыпается, тут же засыпает, тут же снова пересбрасывается и так до бесконечности, пока не ресетнешь. Такое впечатление что после того как нажат wakeup нужно сбросить некий бит, что он отработал. Перерыл референс мануал но ничего не нашел похожего

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Лихо упростили.

while(1){} не забыли?

не забыл, в любом случае после входа в стендбай контроллер перезагружается

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не забыл, в любом случае после входа в стендбай контроллер перезагружается

 

Насколько я помню выход из режима standby сопровождается запуском программы сначала... Сохраняются только регистры бэкапа

 

И да, там есть какая-то еррата насчет режима standby...

Изменено пользователем veteq

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

чутье не подвело, существует флаг, который нужно очищать, иначе каждый раз после входа в standby сразу же из него выходит. В SPL делаю так: PWR_ClearFlag(PWR_FLAG_WU);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...