STMicroelectronics / STM32CubeWL

STM32Cube MCU Full FW Package for the STM32WL series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on boards provided by ST (Nucleo boards)
Other
103 stars 53 forks source link

Custom sleep and wakeup system on the lora end node STM32WL #10

Closed CandraSN closed 3 years ago

CandraSN commented 3 years ago

Hi, I am a bit confused on the lora STM32WL sequence protocol system, I want my device to sleep and wakeup according to the periodic values I want. I have made my own sleep function (stop 2 mode & radio sleep) with wake up triggered using RTC (in seconds) and push button. Where can I put my function (PLB_SleepMode) into the sequencer utility lora end node STM32WL ?

Thank you

Here my code for custom sleep and wake up system:

void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *RtcHandle)
{
  //Clear wake up flag
  __HAL_PWR_CLEAR_FLAG( PWR_FLAG_WU );
}

void PLB_RtcWakeUpTimeSetting( RTC_HandleTypeDef *RtcHandle, unsigned int seconds )
{
  //Set wake up time
  /* Disable all used wakeup source */
  HAL_RTCEx_DeactivateWakeUpTimer( RtcHandle );

  __HAL_RCC_WAKEUPSTOP_CLK_CONFIG( RCC_STOP_WAKEUPCLOCK_MSI );
  HAL_RTCEx_SetWakeUpTimer_IT( RtcHandle, seconds - 1, RTC_WAKEUPCLOCK_CK_SPRE_16BITS );

}

RTC_HandleTypeDef *PLB_RtcPowerSavingConfig( void )
{
  //Set RTC Clock, Timer, Calendar. and return RTC_HandleTypeDef to wake up
  static RTC_HandleTypeDef RtcHandle;

  RTC_TimeTypeDef sTime;
  RTC_DateTypeDef sDate;

  RtcHandle.Instance            = RTC;
  RtcHandle.Init.HourFormat     = RTC_HOURFORMAT_24;
  RtcHandle.Init.AsynchPrediv   = 127;
  RtcHandle.Init.SynchPrediv    = 255;
  RtcHandle.Init.OutPut         = RTC_OUTPUT_DISABLE;
  RtcHandle.Init.OutPutRemap    = RTC_OUTPUT_REMAP_NONE;
  RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  RtcHandle.Init.OutPutType     = RTC_OUTPUT_TYPE_OPENDRAIN;
  HAL_RTC_Init( &RtcHandle );

  sTime.Hours          = 0x0;
  sTime.Minutes        = 0x0;
  sTime.Seconds        = 0x0;
  sTime.TimeFormat     = RTC_HOURFORMAT_24;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  HAL_RTC_SetTime( &RtcHandle, &sTime, FORMAT_BIN );

  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month   = RTC_MONTH_JANUARY;
  sDate.Date    = 0x1;
  sDate.Year    = 16;
  HAL_RTC_SetDate( &RtcHandle, &sDate, FORMAT_BIN );

  return &RtcHandle;
}

void PLB_RtcRccPowerSavingConfig( void )
{
  HAL_StatusTypeDef status = HAL_OK;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;
  RCC_OscInitTypeDef       RCC_OscInitStruct;

  /* Disable backup domeain protection */
  HAL_PWR_EnableBkUpAccess();

  /* Enable RTC APB clock gating */
  __HAL_RCC_RTCAPB_CLK_ENABLE();

  /* Disable the Wake-up Timer */
  __HAL_RTC_WAKEUPTIMER_DISABLE(RtcHandle);
  /* In case of interrupt mode is used, the interrupt source must disabled */ 
  __HAL_RTC_WAKEUPTIMER_DISABLE_IT(RtcHandle,RTC_IT_WUT);
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(RtcHandle,RTC_FLAG_WUTF);

  /* Get RTC clock configuration */
  HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInit);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;  
  PeriphClkInit.RTCClockSelection    = RCC_RTCCLKSOURCE_LSE;

  /* COnfigure oscillator */
  status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
  if(status == HAL_OK)
  {
    /* Configure RTC clock source */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);

    /* Enable RTC Clock */
    if(status == HAL_OK)
    {
      __HAL_RCC_RTC_ENABLE();
    }
  }
  HAL_NVIC_EnableIRQ( RTC_WKUP_IRQn );
  HAL_NVIC_SetPriority( RTC_WKUP_IRQn, 1, 0 );

}

void PLB_InitSystem(void)
{
  HAL_Init();
  PLB_SystemClock_Config( );
  SystemApp_Init();
  PLB_LED_Init(PLB_LED_MODE_RUN);
  PLB_LED_Init(PLB_LED_LORA_INDICATOR);
  PLB_LORA_Seq_Task();
}

void PLB_PowerSavingStopMode(RTC_HandleTypeDef *RtcHandle, unsigned int WakeUpTime, GPIO_TypeDef *WakeUpGPIO)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  Radio.Sleep();

  /* Enable GPIOs clock */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();

  /* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
  /* Note: Debug using ST-Link is not possible during the execution of this   */
  /*       example because communication between ST-link and the device       */
  /*       under test is done through UART. All GPIO pins are disabled (set   */
  /*       to analog input mode) including  UART I/O pins.           */
  GPIO_InitStructure.Pin = GPIO_PIN_All;
  GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStructure.Pull = GPIO_NOPULL;
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);

  //wake up pin setting
  GPIO_InitStructure.Pin   = PLB_WakeupPB_GPIO_Pin; // wakeup by PA.0
  GPIO_InitStructure.Mode  = GPIO_MODE_IT_RISING;
  GPIO_InitStructure.Pull  = GPIO_PULLDOWN;
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init( GPIOA, &GPIO_InitStructure );

  GPIO_InitStructure.Pin   = GPIO_PIN_9;
  GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStructure.Pull  = GPIO_NOPULL;
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.Pin = GPIO_PIN_8;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.Pin = GPIO_PIN_7;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); 
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); 
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); 

  HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(EXTI0_IRQn);

  /* Disable GPIOs clock */
  __HAL_RCC_GPIOA_CLK_DISABLE();
  __HAL_RCC_GPIOB_CLK_DISABLE();
  __HAL_RCC_GPIOC_CLK_DISABLE();
  __HAL_RCC_GPIOH_CLK_DISABLE();

  //Set power saving duration by RTC
  //  if(WakeUpTime < 5 ) WakeUpTime = WakeUpTime + 5;
  PLB_RtcWakeUpTimeSetting( RtcHandle, WakeUpTime );

  // HAL_RTCEx_WakeUpTimerIRQHandler(RtcHandle);
  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);

  //Clear wake up flag
  if( __HAL_PWR_GET_FLAG( PWR_FLAG_WU ) != RESET )
  {__HAL_PWR_CLEAR_FLAG( PWR_FLAG_WU ); }

  if(__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_0) != RESET)
  {__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0); }

  /* Enter STOP 2 mode */
  LL_PWR_ClearFlag_C1STOP_C1STB();
  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

  PLB_InitSystem();
  Radio.Standby();

  /*Disable all used wakeup sources: Pin1(PA.0)*/
  HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
}

void PLB_SleepMode(unsigned int wakeUpTime)
{
  RTC_HandleTypeDef *RtcHandle;

  APP_PRINTF("\nPowerSaving Mode - Start\n");

  //RCC Config for Power Saving
  PLB_RtcRccPowerSavingConfig();

  //RTC Config for Power Saving
  RtcHandle = PLB_RtcPowerSavingConfig();

  //Enter Stop Mode
  PLB_PowerSavingStopMode( RtcHandle, wakeUpTime, GPIOA );
  APP_PRINTF("\nPowerSaving Mode - End\n");
}
ASELSTM commented 3 years ago

Thank you for you contribution.

Please allow me to introduce @YoannBo who will comment your post and provide you with more details about this topic.

With regards,

YoannBo commented 3 years ago

Hello,

When the system has nothing to do, the system calls the idle task: UTIL_SEQ_Idle is located into sys_app.c. In the CubeWL package, the UTIL_SEQ_Idle calls directly UTIL_LPM_EnterLowPower

Functions in PWR_EnterStopMode, PWR_ExitStopModeand equivalent SleepMode (PWR_EnterSleepMode, PWR_ExitSleepMode) are defined in stm32_lpm_if.c. They can be re-written depending on the application.

Now in our system, this is already managed. If you want to periodically wake-up, you can create a timer, for instance toggling a LED

/**
  * @brief  User timer callback function
  * @param  context
  * @retval none
  */
static void OnUserTimerEvent(void *context);

/**
  * @brief Timer to handle the application Join Led to toggle
  */
static UTIL_TIMER_Object_t UserTimer;

void yourFunction(void)
{
  /*Create a UserTimer toggling every 5 seconds*/
  UTIL_TIMER_Create(&UserTimer, 5000, UTIL_TIMER_PERIODIC, OnUserTimerEvent, NULL);
  /* Starts UserTimer*/
  UTIL_TIMER_Start(&UserTimer);
}
/* OnUserTimerEvent */
static void OnUserTimerEvent(void *context)
{
  BSP_LED_Toggle(LED_RED) ;
}

Please be aware, that you should not call APP_PRINTF before entering to stop mode. Indeed, any time everything is printed out, it will wake up the system. and enter sleep/stop again. This will generate an infinite loop.

Best Regards

CandraSN commented 3 years ago

Hi @YoannBo

Thank you very much for this helpful instruction

Maybe, I want to tell in detail about the system work flow that I want is like this, when the node is turned on, it will join to the gateway/server the first time. After that, it will send the data frame 1 time. After sending the data frame, the node will enter stop 2 mode (Radio sleep too) for 30 minutes (can change) and then the system wake up (Radio standby too) via the RTC or get a trigger from the push button.

I'm little confused about where I can put the stop 2 mode function after node sends data frame to the gateway and then wake up ? Should I put my custom sleep system in the sequencer task ?

note: join -> send data frame -> sleep -> wake-up -> send data frame -> infinite loop until the system reset

Best Regards

YoannBo commented 3 years ago

Hello @CandraSN ,

from what I read, this is already done in the LoRaWAN_End_Node project : Join -> send data frame -> stop2-> wake-up -> send data frame -> stop2 by default, the LoRaWAN_End_Node project sends a Tx frame every 10 seconds (when Duty Cycle allows) Duty cycles can be updated in lora_app.h #define APP_TX_DUTYCYCLE 10000

Also, by default, a timer triggers the send_request. But it can also be triggered by nucleo button sw1 by change line 195 in lora_app.c from / send will be done if on timer/ static TxEventType_t EventType = TX_ON_TIMER; to / send will be done if you push sw1 / static TxEventType_t EventType = TX_ON_EVENT;

let me know

YoannBo commented 3 years ago

additionnal note:

The RTC is used (in binary mode new!) directly by the timer (stm32_timer.c) and used by the stack I would advise not to override it.

CandraSN commented 3 years ago

Hi @YoannBo

After I follow your instructions and did some little experiments, I understand how to modify the code based on my system. Thank you very much, your informations are very clear.

Best Regards

CandraSN commented 3 years ago

btw, sorry out of topic how can I print float/double data with APP_PRINTF ?

YoannBo commented 3 years ago

Hi @CandraSN

in file _utilitiesconf.h line #define UTIL_ADV_TRACE_VSNPRINTF(...) tiny_vsnprintf_like(__VA_ARGS__) Can you change tiny_vsnprintf_like to vsnprintf (bigger in size) from stdio.h ?

I believe it should be ok,

Best Regards

CandraSN commented 3 years ago

Hi @YoannBo Yes, problem solved using sprintf and transmit to serial with APP_PRINTF

Thank you

ASELSTM commented 3 years ago

Hi,

@YoannBo Thank you for these clarifications.

@CandraSN Since the issue is answered and the problem is solved, please allow me to close this thread. Thank you once more for your contribution.

With regards,

amanp7272 commented 1 year ago

Hi @YoannBo

Can we change " static TxEventType_t EventType = TX_ON_TIMER; " Line dynamically inside the code based on condition?

I want to make Node in sleep mode with respect to some condition and wakeup by external interrupt on GPIO Pin.

Flow : Join -> send data frame -> stop2-> wake-up -> send data frame -> backup mode condition trigger -> Set TX_ON_Event -> Wakeup on intruppt -> Set TX_ON_TIMER -> send data frame -> stop2

tcpipchip commented 11 months ago

thanks to this info. i can use in on st lorawan SDK

TiagoFernandes271089 commented 11 months ago

Hello,

Thanks to friends for sharing the information about the LoRaWAN_End_Node code. I am also using it to develop a project here at the company. I would like to ask some questions please... 1st Question: I am using this example to wake up the module in loop mode. I would like to exit the loop module by pressing a button and keep the module constantly awake. Could you help me with an example, please. 2nd Question: Being in loop mode, I would like to transmit (uplink) data to the network server each time the module wakes up. Could you also help me with an example, please.

Thank you!

tcpipchip commented 11 months ago

Tiago, your problem now is that 40uA consumption, right ?

TiagoFernandes271089 commented 11 months ago

Yes. In addition to these 2 questions above, I also have this problem with consumption remaining around 40uA.

e3dz commented 9 months ago

Hello @TiagoFernandes271089 and @tcpipchip , i have the same issue with stop2mode and consumption at around 40uA.

Did you manage to solve the current consumption problem?

My application is based on a Lora-E5 and i have verified with the factory firmware that it can run on approx. 3uA(@3.6V). When using following code below i reach a 40uA(@3.6V) current consumption.

#include "main.h"

#include "stm32wlxx_hal_pwr_ex.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();

  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

  while (1)
  {
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
                              |RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
                              |RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();

  GPIO_InitStruct.Pin = GPIO_PIN_All;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

  __HAL_RCC_GPIOA_CLK_DISABLE();
  __HAL_RCC_GPIOB_CLK_DISABLE();
  __HAL_RCC_GPIOC_CLK_DISABLE();
  __HAL_RCC_GPIOH_CLK_DISABLE();
}
TiagoFernandes271089 commented 9 months ago

Hello @e3dz ,

I managed to resolve it here. In my case, whenever I pressed the button (PA12), the module woke up and never returned to sleep mode (+/-5uA). I was calling the "void EXTI1_IRQHandler(void)" interrupt function. I modified my function to "void EXTI15_10_IRQHandler(void)"

/ EXTI interrupt initialization / HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI1_IRQn); HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

Also check if any portal is not connected in sleep mode. In my case, I had to call the function to disable UART2: HAL_UART_DeInit(&huart2);

tcpipchip commented 9 months ago

Thiago solved...i will ask him to see your question....

tcpipchip commented 9 months ago

haha...the answered when i was typing :)

e3dz commented 9 months ago

@TiagoFernandes271089 Thanks for the quick answer!

I am trying that but can't get it to work, would you mind sharing the example that works for you?

TiagoFernandes271089 commented 9 months ago

Hello,

Follows as requested:

include "main.h"

include "i2c.h"

include "app_lorawan.h"

include "tim.h"

include "gpio.h"

include "sys_app.h"

include "app_version.h"

include "stm32_lpm.h" //Include para a função "UTIL_LPM_EnterLowPower()" (Tiago)

include "utilities_conf.h"

include "stm32_lpm_if.h" //Include para a Função "PWR_EnterSleepMode()" (Tiago)

include "lora_app.h"

/ Private includes ----------------------------------------------------------/ / USER CODE BEGIN Includes / static void OnUserTimerEvent(void *context); static UTIL_TIMER_Object_t UserTimer;

/ USER CODE END Includes / extern void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);

extern UART_HandleTypeDef huart2;

void SystemClock_Config(void);

int main(void) { / Reset of all peripherals, Initializes the Flash interface and the Systick. / HAL_Init(); / Configure the system clock / SystemClock_Config(); / Initialize all configured peripherals / //MX_LoRaWAN_Init(); SystemApp_Init(); //Tiago: Aqui inicia o Hall MX_GPIO_Init(); MX_I2C1_Init(); MX_TIM16_Init(); HAL_TIM_Base_Start_IT(&htim16);

/* Infinite loop */
/* USER CODE BEGIN WHILE */

HAL_UART_DeInit(&huart2);

while (1)
{
        MX_LoRaWAN_Process();
}

}

void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure LSE Drive Capability
 */
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

/** Configure the main internal regulator output voltage
 */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/** Initializes the CPU, AHB and APB buses clocks
 */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;//RCC_MSIRANGE_8
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
    Error_Handler();
}

/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
 */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
        |RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
        |RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
// RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV10;//DIV10 = 4,8MHz
//RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
    Error_Handler();
}

}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim16) { //HAL_GPIO_TogglePin(DEF_LED_BLUE_GPIO_Port, DEF_LED_BLUE); if(St_Timer.t_200ms)St_Timer.t_200ms--; if(St_Timer.t_1s)St_Timer.t_1s--; if(St_Timer.t_3s)St_Timer.t_3s--; if(St_Timer.t_5s)St_Timer.t_5s--; if(St_Timer.t_6s)St_Timer.t_6s--; if(St_Timer.t_10s)St_Timer.t_10s--; if(St_Timer.t_out)St_Timer.t_out--;

}

}

/ USER CODE END 4 /

/**

ifdef USE_FULL_ASSERT

/**