Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32L151 режим STOP
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
data_stack
Мозг дымится, прям беда какая то, никак не приручить 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 не помогло. Ввожу в стоп не в прерывании.
AlanDrakes
В прерывании нельзя засыпать.
Но есть возможность заснуть по выходе из прерывания.
Вам потребуется бит SLEEPONEXIT: SCB->SCR |= SCB_SCR_SLEEPONEXIT;
Эта инструкция должна быть максимально последней перед завершением обработчика прерывания.
Проверьте.
data_stack
Специально же написал: Ввожу в стоп не в прерывании.
AlanDrakes
Тогда вариант более простой - на обработчике событий.
Создаёте глобальную переменную. В прерывании кнопки устанавливаете её в, допустим, 1.
В бесконечном цикле проверяете, равна ли переменная единице и если так - усыпляете кристалл. От прерывания отвязались.

Переменная, кстати, volatile? Можете проверить в отладчике, меняется ли она вообще. И посмотреть дизассемблированный код, который был сгенерирован.
Некоторые переменные порой... выбрасываются.
data_stack
Цитата(AlanDrakes @ Feb 16 2016, 15:14) *

Вы издеваетесь надо мной? Так и сделано stop_enable глобальная переменная, если 1 уходим в стоп, проблема в том, что не уходит он так в стоп. Переменная volatile.
AlanDrakes
У меня работает отлично вот такой код:
Код
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(); и ждёт ближайшего следующего прерывания.
data_stack
Поднимаю тему, перетестил много раз - не работает. Упростил задачу, нужно включить контроллер и уйти сразу в standby, если wakeup нажат, то проснуться пересброситься и снова уйти в сон.
Код
int main()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    PWR_WakeUpPinCmd(PWR_WakeUpPin_3, ENABLE);
  
    delay_ms(5000);
    PWR_EnterSTANDBYMode();
}


Что выходит на деле: в первый раз все по феньшую - контроллер уходит в сон, жмакаем wakeup и все ломается, контроллер просыпается, тут же засыпает, тут же снова пересбрасывается и так до бесконечности, пока не ресетнешь. Такое впечатление что после того как нажат wakeup нужно сбросить некий бит, что он отработал. Перерыл референс мануал но ничего не нашел похожего
adnega
Цитата(data_stack @ Mar 4 2016, 13:32) *
Упростил задачу

Лихо упростили.
while(1){} не забыли?
data_stack
Цитата(adnega @ Mar 4 2016, 11:39) *
Лихо упростили.
while(1){} не забыли?

не забыл, в любом случае после входа в стендбай контроллер перезагружается
veteq
Цитата(data_stack @ Mar 4 2016, 14:46) *
не забыл, в любом случае после входа в стендбай контроллер перезагружается


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

И да, там есть какая-то еррата насчет режима standby...
data_stack
чутье не подвело, существует флаг, который нужно очищать, иначе каждый раз после входа в standby сразу же из него выходит. В SPL делаю так: PWR_ClearFlag(PWR_FLAG_WU);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.