STM32L010 Sleep / Stop / Standbyの使い方


低消費電力モードであるSleep / Stop / Standbyを試してみます。

1. デバイスの設定

1.1. 入力ポートの設定

PA0 をEXTI、PA7を入力ポートとして設定します。
PA0はSleep / Stop Mode からのWakeup要因として使用します。




PA0をWakeup要因として使用するのでGPIO modeExternal Event Mode with Rising edge trigger detectionに設定します。


2. コーディング

2.1. Sleep Mode

動作確認の為、文字列送信関数を作成しておきます。
/* USER CODE BEGIN 0 */
void	UsartTransmitStrings(UART_HandleTypeDef *huart, char *pMsg)
{
	HAL_UART_Transmit_IT(huart, (uint8_t *)pMsg, strlen(pMsg));
	while ((*huart).gState != HAL_UART_STATE_READY);
}

/* USER CODE END 0 */
				
HAL_PWR_EnterSLEEPModeでSleep Modeに遷移します。
HAL_PWR_EnterSLEEPMode実行前にHAL_SuspendTickを呼び出しTick Timerを停止しておきます。
停止しないとTick Timerの割込みでWakeUpしてしまうためです。
    /* USER CODE BEGIN 3 */
	  if (HAL_GPIO_ReadPin(SW_GPIO_Port, SW_Pin) == GPIO_PIN_RESET) {
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
		  sprintf(msg, "Enter Sleep Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);

		  HAL_SuspendTick();
		  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFE);
		  HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);

		  HAL_ResumeTick();
		  sprintf(msg, "Leave Sleep Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);
	  }
				
PA7を押下するとSleep Modeに入ります。
PA0を押下するとSleep ModeからWakeUpします。


2.2. Stop Mode

Stop Modeになると、内部クロック(HSI / HSE / MSI)は停止されます。
よってWakeUpさせるためにRTCが必要となります。
コーディング前にRTCを有効にし、LSIを選択します。
確認の為、MSOを有効にしておきます。




HAL_PWR_EnterSTOPModeでStop Modeに遷移します。
内部クロックが停止しているので、WakeUp後RCCを再初期化する必要があります。
    /* USER CODE BEGIN 3 */
	  if (HAL_GPIO_ReadPin(SW_GPIO_Port, SW_Pin) == GPIO_PIN_RESET) {
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
		  sprintf(msg, "Enter Stop Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);

		  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFE);
		  HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);

		  SystemClock_Config();
		  sprintf(msg, "Leave Stop Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);
	  }
				


2.3. Standby Mode

次にStandby Modeを試してみます。
Standby中は内部クロックが停止するだけでなく、VCoreもOFFとなるため、RAMやレジスタが保持されません。
WakeUp後はリセットと同じ動作となります。
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
		  sprintf(msg, "Enter Standby Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);

		  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_PWR_EnterSTANDBYMode();
		  		



最後にmain関数全体を記します。
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
  char	msg[64];

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
  sprintf(msg, "Sleep/Stop/Standby Test %08lX\r\n", PWR->CSR);
  UsartTransmitStrings(&huart2, msg);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if (HAL_GPIO_ReadPin(SW_GPIO_Port, SW_Pin) == GPIO_PIN_RESET) {
#if 1
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
		  sprintf(msg, "Enter Sleep Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);

		  HAL_SuspendTick();
		  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFE);
		  HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_ResumeTick();

		  sprintf(msg, "Leave Sleep Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);
#endif

#if 0
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
		  sprintf(msg, "Enter Stop Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);

		  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFE);
		  HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);

		  SystemClock_Config();

		  sprintf(msg, "Leave Stop Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);
#endif

#if 0
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
		  sprintf(msg, "Enter Standby Mode %08lX\r\n", PWR->CSR);
		  UsartTransmitStrings(&huart2, msg);

		  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
		  HAL_PWR_EnterSTANDBYMode();
#endif
	  }
  }
  /* USER CODE END 3 */
}
		  		
リファレンスマニュアルには記載が見当たらないのですが、PA0 の内蔵PullUpは無効になるようで、外部にPullUp抵抗を接続しておかなければなりません。
Standby Modeだけならわかりますが、Sleep / Stop Mode も同じなのは何故?