Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

STM32F103 энергосберегающий режим STOP

Сб июл 14, 2018 00:29:50

Здравствуйте.
Помогите разобраться с энергосберегающими режимами микроконтроллера STM32F103. Нужно переходить в режим STOP и раз в секунду просыпаться для подсчета времени(пока просто светодиодом помигаем).
После чтения документов и поиска в интернете установлено следующее, в режим STOP контроллер переводится командой PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE); после чего его могут разбудить только внешние прерывания/события EXTI. В моем случае с будильником работает событие EXTI_Line17. Чтобы «завести» будильник нужно в регистры RTC->ALRH и ALRL записать число при достижении которого счетным регистром сработает будильник. Вроде все просто.
Проблема: контроллер не просыпается при наступлении события. Если остановить отладку, курсор буден находится на строке 228, а счетчик "утикал" далеко за установленное время.
Изображение
Если продолжить пошаговую отладку, то контроллер выполняет один цикл, уходит в спячку и останавливается на том же месте
Вопрос, что я делаю не так. Вот код проекта
Код:
#include "stm32f10x.h"                  // Device header
#include "stm32f10x_exti.h"             // Keil::Device:StdPeriph Drivers:EXTI
#include "stm32f10x_gpio.h"             // Keil::Device:StdPeriph Drivers:GPIO
#include "stm32f10x_pwr.h"              // Keil::Device:StdPeriph Drivers:PWR
#include "stm32f10x_rcc.h"              // Keil::Device:StdPeriph Drivers:RCC
#include "stm32f10x_rtc.h"              // Keil::Device:StdPeriph Drivers:RTC
#include "misc.h"                       // Keil::Device:StdPeriph Drivers:Framework
#include "stm32f10x_dbgmcu.h"           // Keil::Device:StdPeriph Drivers:DBGMCU
 
   GPIO_InitTypeDef  GPIO_InitStructure;
  EXTI_InitTypeDef EXTI_InitStruct;
/*
Инициализация RTC
*/
unsigned char RTC_Init(void)
{
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
   PWR_BackupAccessCmd(ENABLE);
   if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN)
   {
      RCC_BackupResetCmd(ENABLE);
      RCC_BackupResetCmd(DISABLE);

      RCC_LSEConfig(RCC_LSE_ON);
      while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY) {}
      RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

      /* Set prescaler */
      RTC_SetPrescaler(0x7FFF);

      /* Enable RTC */
      RCC_RTCCLKCmd(ENABLE);

      RTC_WaitForSynchro();

      return 1;
   }
   return 0;
}


int main(void)
{

  DBGMCU->CR |=(DBGMCU_CR_DBG_STOP  );//Чтобы работала отладка в режиме STOP
   
  /* Инициализация светодиода на PINB_12*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

//    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
//  /* Configure the GPIO_LED pin */
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GPIOC, &GPIO_InitStructure);
   
  RTC_Init();//Инициализация RTC

   /*Настраиваем событие по будильнику, линия EXTI_Line17 */
      EXTI_DeInit();
      EXTI_StructInit(&EXTI_InitStruct);
 
    EXTI_InitStruct.EXTI_Line = EXTI_Line17;
    /* Enable interrupt */
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    /* Interrupt mode */
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Event;
    /* Triggers on falling edge */
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//;EXTI_Trigger_Falling
    /* Add to EXTI */
      EXTI_Init(&EXTI_InitStruct);

         
  while (1)
  {      
   GPIOB->ODR ^= GPIO_Pin_12;//Дрыгаем ногой
         
      /*Настраиваем таймер для сна*/
RTC->CRL |= RTC_CRL_CNF;//Разрешаем запись
         RTC->CNTL = 0;//обнуляем счетчик, ну надо мне так..
       RTC->ALRL = 3;//заводим будильник на 3 мекунды
      RTC->CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF); //закрываем запись

     RTC_WaitForLastTask();

      PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);//Переводим контроллер в режим STOP
  }
}

Re: STM32F103 энергосберегающий режим STOP

Чт июл 19, 2018 23:02:18

Проблема решилась следующим образом:
Код:
/*Настраиваем таймер для сна*/
RTC->CRL |= RTC_CRL_CNF;//Разрешаем запись
RTC->CNTH = 0;//обнуляем счетчик
RTC->CNTL = 0;//обнуляем счетчик
RTC->ALRH = 0;
RTC->ALRL = 3;//заводим будильник на 3 мекунды
RTC->CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF); //закрываем запись
Ответить