Skocz do zawartości

Reset licznika RTC po każdym wyjściu z trybu StandBy - STM32L476RGT6


Emerid

Pomocna odpowiedź

Cześć,

Próbuję zrobić podlewanie ogródka przy pomocy STM32L476RGT6 z użyciem trybu Standby oraz z ustawianą godziną podlewania - niestety po każdym wybudzeniu program wykonywany jest od zera, przez co licznik RTC zaczyna od czasu 00:00:00, a czas, który upłynął przed wejściem w tryb Standby jest zapominany.

Wybudzenie realizowane jest poprzez Internal WakeUp związane z RTC, więc może da się jakoś zachować ten licznik - ktoś coś wie? 🙂 

Moim pomysłem na rozwiązanie tego przypadku jest zapis poszczególnych członków klasy RTC_TimeTypeDef w SRAM2 oraz przygotowanie algorytmu sumująco/inkrementującego co wyjście z trybu StandBy, ale może ktoś zna jakieś bardziej eleganckie rozwiązanie? (Lub może rozwiązaniem jest innym tryb pracy?)
Pozdrawiam.

Link do komentarza
Share on other sites

Wykorzystujesz tryb z aktywnym RTC?

image.thumb.png.ee936b28868d13e38bd5048398714fbe.png

Bo według dokumentacji są dwa, z czego jeden z wyłączonym RTC. To przekładałoby się na taki efekt. Bez kodu raczej nikt nie powie co robisz źle.

Link do komentarza
Share on other sites

15 godzin temu, Emerid napisał:

program wykonywany jest od zera, przez co licznik RTC zaczyna od czasu 00:00:00, a czas, który upłynął przed wejściem w tryb Standby jest zapominany

RTC Ci sie nie resetuje z powodu restartu programu (bo reset CPU nie resetuje domeny RTC), tylko dlatego, ze sam go gdzieś resetujesz podczas inicjalizacji.  

Link do komentarza
Share on other sites

@H1M4W4R1 @kaworu  Dziękuję za zainteresowanie.

Dnia 12.07.2021 o 19:51, H1M4W4R1 napisał:

Wykorzystujesz tryb z aktywnym RTC?

image.thumb.png.ee936b28868d13e38bd5048398714fbe.png

Bo według dokumentacji są dwa, z czego jeden z wyłączonym RTC. To przekładałoby się na taki efekt. Bez kodu raczej nikt nie powie co robisz źle.

Tak, RTC jest aktywne (chociaż przyznam, że niestety nie wiem, w którym dokładnie miejscu jest to aktywowane przez code generation w STM32CubeIDE)

 

9 godzin temu, kaworu napisał:

RTC Ci sie nie resetuje z powodu restartu programu (bo reset CPU nie resetuje domeny RTC), tylko dlatego, ze sam go gdzieś resetujesz podczas inicjalizacji.  

@kaworu  Chyba miałeś rację. Podejrzewam, że moim błędem w myśleniu jest poniższa linijka (gdzie całość programu załączam poniżej)

if(!HAL_RTC_GetState(&hrtc)) sram2_data->init_FLAG = 0;

Sądziłem, że jeśli RTC jest już zainicjowane, to HAL_RTC_GetState(&hrtc) będzie zwracać TRUE, ale chyba tak nie jest. Czy zna któryś z was jakiś rejestr, który inicjalizowany jest tylko przy pierwszym uruchomieniu i zachowany zostaje także po resecie/wyjściu ze Standby?

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct{
	uint8_t empty;
	uint8_t init_FLAG;
	uint8_t x;
	uint8_t RTC_hour;
	uint8_t RTC_minutes;
	uint8_t RTC_seconds;
	uint8_t y;
	char test[32];
}sram2_located_data;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
RTC_HandleTypeDef hrtc;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
void watering(uint8_t flag, uint8_t time_sec);
void start_measure(void);
void stop_measure(void);
int __io_putchar(int ch);
bool is_button_pressed(void);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
/*-------------------------------------------------------------------------------*/

/*----------------------------------------------------
 * 				Enable SRAM2 during Standby mode
 -----------------------------------------------------*/
	PWR->CR3 |= PWR_CR3_RRS;

/*----------------------------------------------------
 * 				PIM (Per Instance Memory)
 -----------------------------------------------------*/
	RTC_TimeTypeDef time = {0};
	RTC_DateTypeDef date = {0};

	sram2_located_data* sram2_data = (sram2_located_data*)SRAM2_BASE;
    uint8_t watering_FLAG = sram2_data->x;
	uint8_t tmp_Hours = sram2_data->y;

/*----------------------------------------------------
 * 					Calibrations
 -----------------------------------------------------*/
	uint8_t watering_HOUR = 10;
	uint8_t watering_TIME_sec = 0x2;


/*-------------------------------------------------------------------------------*/
  /* USER CODE END 1 */

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

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

  /* USER CODE BEGIN Init */
  if(!HAL_RTC_GetState(&hrtc)) sram2_data->init_FLAG = 0;
  /* 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_RTC_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
/*-----------------------------------------------------------------------------------------------------------*/
  /*
  	   * --------------------------------------------------------------------------------------
  	   * RTC Date and Time initialization
  	   * Year = 2000 + date.Year
  	   * Month = date.Month
  	   * Date = date.Date
  	   * WeekDay = date.WeekDay (Enum type)
  	   *
  	   *
  	   */


  	  printf("Init_FLAG: %d\n",sram2_data->init_FLAG);

  	  if(sram2_data->init_FLAG == 0){

  	  time.Hours = 9;
  	  time.Minutes = 59;
  	  time.Seconds = 30;
  	  HAL_RTC_SetTime(&hrtc, &time, FORMAT_BIN);

  	  date.Year = 21;
  	  date.Month = 07;
  	  date.Date = 2;
  	  date.WeekDay = RTC_WEEKDAY_FRIDAY;
  	  HAL_RTC_SetDate(&hrtc, &date, FORMAT_BIN);

  	  sram2_data->init_FLAG = 1;

  	  }

  	/*-------------------------------------------------------------------------------*/

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_RTC_GetTime(&hrtc, &time, FORMAT_BIN);
	  HAL_RTC_GetDate(&hrtc, &date, FORMAT_BIN);

	  if(!(tmp_Hours == watering_HOUR) && time.Hours == watering_HOUR) watering_FLAG = 1;
	  else watering_FLAG = 0;
	  tmp_Hours = time.Hours;

	  watering(watering_FLAG,watering_TIME_sec);

	  start_measure();
	  HAL_Delay(100);
	  stop_measure();

	  sram2_data->x = watering_FLAG;
	  sram2_data->y = tmp_Hours;

	  printf("Aktualny czas: %02d:%02d:%02d\n",time.Hours, time.Minutes, time.Seconds);
	  printf("Watering_FLAG: %d\n",sram2_data->x);
	  printf("Init_FLAG: %d\n\n",sram2_data->init_FLAG);
	  HAL_PWR_EnterSTANDBYMode();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure LSE Drive Capability
  */
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = 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;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable MSI Auto calibration
  */
  HAL_RCCEx_EnableMSIPLLMode();
}

/**
  * @brief RTC Initialization Function
  * @param None
  * @retval None
  */
static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable the WakeUp
  */
  if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 4, RTC_WAKEUPCLOCK_CK_SPRE_16BITS) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(RELAY_MODULE_IN1_GPIO_Port, RELAY_MODULE_IN1_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : USER_BUTTON_Pin */
  GPIO_InitStruct.Pin = USER_BUTTON_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USER_BUTTON_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : RELAY_MODULE_IN1_Pin */
  GPIO_InitStruct.Pin = RELAY_MODULE_IN1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(RELAY_MODULE_IN1_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */
void watering(uint8_t flag, uint8_t time_sec){
	if(flag){
			  HAL_GPIO_WritePin(RELAY_MODULE_IN1_GPIO_Port, RELAY_MODULE_IN1_Pin, GPIO_PIN_RESET);
			  HAL_Delay(time_sec*1000);
			  HAL_GPIO_WritePin(RELAY_MODULE_IN1_GPIO_Port, RELAY_MODULE_IN1_Pin, GPIO_PIN_SET);
		  }
}

void start_measure(void)
{
	// rozpoczęcie "pomiaru"
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
}

void stop_measure(void)
{
	// zakończenie "pomiaru"
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
}

int __io_putchar(int ch)
{
    if (ch == '\n') {
        uint8_t ch2 = '\r';
        HAL_UART_Transmit(&huart2, &ch2, 1, HAL_MAX_DELAY);
    }

    HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
    return 1;
}

bool is_button_pressed(void)
{
  if (HAL_GPIO_ReadPin(USER_BUTTON_GPIO_Port, USER_BUTTON_Pin) == GPIO_PIN_RESET) {
    return true;
  } else {
    return false;
  }
}
/* USER CODE END 4 */

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

10 godzin temu, Emerid napisał:

Czy zna któryś z was jakiś rejestr, który inicjalizowany jest tylko przy pierwszym uruchomieniu i zachowany zostaje także po resecie/wyjściu ze Standby?

Cały RTC tak działa. 😉 Ale jest jeszcze zestaw rejestrów RTC->BKPxR (zdaje sie 32 rejestry), do których możesz zapisać rzeczy i nie ulegagja skasowaniu przy resecie CPU (tylko jak robisz reset domeny RTC recznie) i są podtrzymywane przez VBAT po zaniku zasilania.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

@Emerid Moduł RTC działa nawet w trybie standby i nie musisz aktualnego czasu zapisywać w pamięci SRAM2 - tym bardziej, że wówczas czas spędzony w uśpieniu nie byłby liczony, więc sam "zegarek" pewnie zbyt dokładny by nie był.

Problem wynika chyba z nieporozumienia. Na początku programu wywołujesz funkcję HAL_RTC_GetState, która zwraca stan HAL_RTC_STATE_RESET co oznacza, że moduł RTC nie został jeszcze zainicjalizowany. Musisz więc najpierw wywołać HAL_RTC_Init, albo raczej MX_RTC_Init.

Warto popatrzeć jak wygląda kod HAL_RTC_GetState:

HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc)
{
  /* Return RTC handle state */
  return hrtc->State;
}

Ta funkcja nie zwraca wartości pobranych z rejestrów RTC, ale stan przechowywany w zwykłej zmiennej hrtc. Ponieważ jest to zmienna globalna, więc po resecie jej zawartość jest zerowana, dlatego pole State ma wartość 0, co odpowiada stałej HAL_RTC_STATE_RESET.

Proponuję zrobić następujący test - zakomentuj kod sprawdzający stan oraz ustawiający czas, czyli wywołania HAL_RTC_SetTime i HAL_RTC_SetDate. Teraz RTC powinien działać poprawnie, bez resetowania w trybie Standby.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

@Elvis Tak, zakomentowanie części kodu pokazało, że RTC działa poprawnie
@kaworu Bardzo dziękuję za tą wskazówkę, zapisałem swoją Flagę właśnie w tym rejestrze i program działa jak chciałem 😄 (Niestety wartości startowe SRAM2 są losowe, czego chciałem uniknąć, natomiast wszystkie bity rejestrów RTC BKPxR po zapewnieniu zasilania mają ustawioną wartość 0, o co właśnie mi chodziło 🙂).

Kod programu wrzuciłem poniżej, natomiast jeśli jeszcze mogę, to moglibyście wskazać, gdzie zdefiniowane są struktury RTC->BKPxR i inne podobne. Próbowałem ręcznie ustawić te bity/rejestry na podstawie adresów, ale nie potrafię sobie z tym poradzić. Poniżej zamieszczam komendy, może wskażecie mi, gdzie popełniam błąd.

Komendy:

1)

READ_BIT(RTC_BASE+RTC_BKP0R,0x1UL);


2)

READ_REG(RTC_BASE+0x50);


3)

WRITE_REG(RTC_BASE+0x50UL,0x1UL);


4)

(RTC_BASE+0x50UL) += 0x1UL;


5)

MODIFY_REG(RTC_BASE+0x50UL,0x0UL,0x1UL);

 

Kod programu:

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct{
	uint8_t SRAM2_tmp_Hours;
	uint8_t SRAM2_watering_FLAG;
}sram2_located_data;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
RTC_HandleTypeDef hrtc;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
void watering(uint8_t flag, uint8_t time_sec);
void start_measure(void);
void stop_measure(void);
int __io_putchar(int ch);
bool is_button_pressed(void);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
/*-------------------------------------------------------------------------------*/



/*----------------------------------------------------
 * 				PIM (Per Instance Memory)
 -----------------------------------------------------*/
	RTC_TimeTypeDef time = {0};
	RTC_DateTypeDef date = {0};

	sram2_located_data* sram2_data = (sram2_located_data*)SRAM2_BASE;
    uint8_t watering_FLAG = sram2_data->SRAM2_watering_FLAG;
	uint8_t tmp_Hours = sram2_data->SRAM2_tmp_Hours;

/*----------------------------------------------------
 * 					Calibrations
 -----------------------------------------------------*/
	uint8_t watering_HOUR = 10;
	uint8_t watering_TIME_sec = 0x2;


/*-------------------------------------------------------------------------------*/
  /* 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 */
  /*-------------------------------------------------------------------------------*/

  /*----------------------------------------------------
   * 				Enable SRAM2 during Standby mode
   -----------------------------------------------------*/
  /*
   * ------------------ Description --------------------
   * To enable SRAM2 during Standby mode the RRS bit in PWR_CR3 register must be SET.
   * The bit must be enabled each time before uC enter Standby mode, as PWR_CR3 is reset after each Standby WakeUp
   */
  	PWR->CR3 |= PWR_CR3_RRS;

  	/*-------------------------------------------------------------------------------*/
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  MX_RTC_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
/*-----------------------------------------------------------------------------------------------------------*/

  /*--------------------------------------------------------------------------------------
     * 				RTC Date and Time initialisation after Power Up
     --------------------------------------------------------------------------------------*/
    /*
     * ------------------ Description --------------------
     * The function initialises RTC Date and Time after Power Up.
     * The function is called only once after Power Up and then a bit in RTC Backup Register is set, blocking it from further call.
     *
  	 * RTC Date and Time initialisation
  	 * Year = 2000 + date.Year
  	 * Month = date.Month
  	 * Date = date.Date
  	 * WeekDay = date.WeekDay (Enum type)
  	 *
  	 *
  	 */

  	if(!RTC->BKP0R){
  	  time.Hours = 9;
  	  time.Minutes = 59;
  	  time.Seconds = 30;
  	  HAL_RTC_SetTime(&hrtc, &time, FORMAT_BIN);

  	  date.Year = 21;
  	  date.Month = 07;
  	  date.Date = 2;
  	  date.WeekDay = RTC_WEEKDAY_FRIDAY;
  	  HAL_RTC_SetDate(&hrtc, &date, FORMAT_BIN);

  	  RTC->BKP0R |= 0x1UL;
  	  }

  	/*-------------------------------------------------------------------------------*/

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_RTC_GetTime(&hrtc, &time, FORMAT_BIN);
	  HAL_RTC_GetDate(&hrtc, &date, FORMAT_BIN);

	  if(!(tmp_Hours == watering_HOUR) && time.Hours == watering_HOUR) watering_FLAG = 1;
	  else watering_FLAG = 0;
	  tmp_Hours = time.Hours;

	  watering(watering_FLAG,watering_TIME_sec);

	  start_measure();
	  HAL_Delay(100);
	  stop_measure();

	  sram2_data->SRAM2_watering_FLAG = watering_FLAG;
	  sram2_data->SRAM2_tmp_Hours = tmp_Hours;

	  printf("Aktualny czas: %02d:%02d:%02d\n",time.Hours, time.Minutes, time.Seconds);
	  HAL_PWR_EnterSTANDBYMode();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure LSE Drive Capability
  */
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = 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;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable MSI Auto calibration
  */
  HAL_RCCEx_EnableMSIPLLMode();
}

/**
  * @brief RTC Initialization Function
  * @param None
  * @retval None
  */
static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable the WakeUp
  */
  if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 4, RTC_WAKEUPCLOCK_CK_SPRE_16BITS) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(RELAY_MODULE_IN1_GPIO_Port, RELAY_MODULE_IN1_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : USER_BUTTON_Pin */
  GPIO_InitStruct.Pin = USER_BUTTON_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USER_BUTTON_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : RELAY_MODULE_IN1_Pin */
  GPIO_InitStruct.Pin = RELAY_MODULE_IN1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(RELAY_MODULE_IN1_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */
void watering(uint8_t flag, uint8_t time_sec){
	if(flag){
			  HAL_GPIO_WritePin(RELAY_MODULE_IN1_GPIO_Port, RELAY_MODULE_IN1_Pin, GPIO_PIN_RESET);
			  HAL_Delay(time_sec*1000);
			  HAL_GPIO_WritePin(RELAY_MODULE_IN1_GPIO_Port, RELAY_MODULE_IN1_Pin, GPIO_PIN_SET);
		  }
}

void start_measure(void)
{
	// rozpoczęcie "pomiaru"
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
}

void stop_measure(void)
{
	// zakończenie "pomiaru"
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
}

int __io_putchar(int ch)
{
    if (ch == '\n') {
        uint8_t ch2 = '\r';
        HAL_UART_Transmit(&huart2, &ch2, 1, HAL_MAX_DELAY);
    }

    HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
    return 1;
}

bool is_button_pressed(void)
{
  if (HAL_GPIO_ReadPin(USER_BUTTON_GPIO_Port, USER_BUTTON_Pin) == GPIO_PIN_RESET) {
    return true;
  } else {
    return false;
  }
}
/* USER CODE END 4 */

 

Link do komentarza
Share on other sites

Jaki edytor na tym forum jest upośledzony...

8 godzin temu, Emerid napisał:

natomiast jeśli jeszcze mogę, to moglibyście wskazać, gdzie zdefiniowane są struktury RTC->BKPxR

W CMSIS, gdzieś tam na dysku masz plik stm32l476.h, stm32l4xx.h czy cos takiego.

8 godzin temu, Emerid napisał:

Próbowałem ręcznie ustawić te bity/rejestry na podstawie adresów, ale nie potrafię sobie z tym poradzić

Bo usiłujesz zapisać coś do stałej, co z definicji może się nie udać. 😉

*(volatile uint32_t*)(RTC_BASE+0x50UL) += 0x1UL;

No tylko po co tak, skoro masz RTC->BKP0R?

  • Pomogłeś! 1
Link do komentarza
Share on other sites

14 godzin temu, kaworu napisał:

No tylko po co tak, skoro masz RTC->BKP0R?

Tylko i wyłącznie po to, żeby sprawdzić, czy rozumiem jak to działa 😄 

Dziękuję wszystkim za pomoc, z mojej strony temat uważam za zamknięty, pozdrawiam. 😉 

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.