Здравствуйте.
Помогите разобраться с энергосберегающими режимами микроконтроллера 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
}
}