Skocz do zawarto┼Ťci

Problem z RTC- Nucleo F103RB


Bhoy67

Pomocna odpowied┼║

Witam ­čÖé

Mam problem z dzia┼éaniem RTC na p┼éytce Nucleo (tej, kt├│ra by┼éa u┼╝yta w kursie Forbota jak wida─ç z tytu┼éu w─ůtku). Pisa┼éem program w SW4STM (bez u┼╝ycia CubeMX), kt├│ry mia┼é wy┼Ťwietla─ç aktualn─ů godzin─Ö na LCD tym samym, co we wspomnianym kursie (Nokia 5110). Z obs┼éug─ů wy┼Ťwietlacza nie ma ┼╝adnych problem├│w. Gdy to pisa┼éem zacz─ů┼éem od wy┼Ťwietlenia trzech liczb dwucyfrowych (godzina:minuta:sekunda) i dzia┼éa┼éo dobrze. Teraz, gdy RTC czasem odpali, to godzin─Ö te┼╝ pokazuje ok. Kod main wstawiam poni┼╝ej.

#include "stm32f1xx.h"
#include "font.h"
#include "lcd.h"

TIM_HandleTypeDef tim;
TIM_OC_InitTypeDef channel;
UART_HandleTypeDef uart;


void send_char(char c) {
	HAL_UART_Transmit(&uart, (uint8_t*)&c, 1, 1000);
}

int __io_putchar(int c) {
	if (c=='\n') {
		send_char('\r');
	}
	send_char(c);
	return c;
}

void Error_Handler(void) {
  printf("Error Handler!\n");
}

int main(void)
{
	HAL_Init();

	//konfiguracja zegar├│w- HSE + LSE- do RTC
	RCC_OscInitTypeDef osc;
	osc.OscillatorType=RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSI;
	osc.HSEState=RCC_HSE_ON;
	osc.HSEPredivValue=RCC_HSE_PREDIV_DIV1;
	osc.LSEState=RCC_LSE_OFF;
	osc.HSIState=RCC_HSI_OFF;
	osc.HSICalibrationValue=RCC_HSICALIBRATION_DEFAULT;
	osc.LSIState=RCC_LSI_ON;
	osc.PLL.PLLState=RCC_PLL_ON;
	osc.PLL.PLLSource=RCC_PLLSOURCE_HSE;
	osc.PLL.PLLMUL=RCC_PLL_MUL2;
	HAL_RCC_OscConfig(&osc);
	RCC_ClkInitTypeDef clk;
	clk.ClockType=RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
	clk.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;  //16MHz SYS;
	clk.AHBCLKDivider=RCC_SYSCLK_DIV1;
	clk.APB2CLKDivider=RCC_HCLK_DIV1;
	clk.APB1CLKDivider=RCC_HCLK_DIV2;  //8MHz- APB1
	HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_1);

	__HAL_RCC_BKP_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_TIM4_CLK_ENABLE();
	__HAL_RCC_SPI1_CLK_ENABLE();
	__HAL_RCC_USART2_CLK_ENABLE();

	RCC_PeriphCLKInitTypeDef periphCLK;
	periphCLK.PeriphClockSelection=RCC_PERIPHCLK_RTC;
	periphCLK.RTCClockSelection=RCC_RTCCLKSOURCE_LSI;  //taktowanie RTC z LSI
	if (HAL_RCCEx_PeriphCLKConfig(&periphCLK) != HAL_OK) {
	    Error_Handler();
	}

	//konfiguracja GPIO
	GPIO_InitTypeDef gpio;
	gpio.Pin=LCD_Clk|LCD_Din;  //PA5- SPI1:SCK, PA7- MOSI
	gpio.Mode=GPIO_MODE_AF_PP;
	gpio.Pull=GPIO_NOPULL;
	gpio.Speed=GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA, &gpio);
	gpio.Pin=GPIO_PIN_6;  //PB6- do pod┼Ťwietlenia z PWM
	HAL_GPIO_Init(GPIOB, &gpio);
	gpio.Pin=LCD_RST|LCD_DC|LCD_CE|GPIO_PIN_0;
	gpio.Mode=GPIO_MODE_OUTPUT_PP;
	HAL_GPIO_Init(GPIOC, &gpio);
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);  //testowy LED
	gpio.Pin=GPIO_PIN_2;  //PA2- Tx
	gpio.Mode=GPIO_MODE_AF_PP;
	HAL_GPIO_Init(GPIOA, &gpio);
	gpio.Pin=GPIO_PIN_3;  //PA3-Rx
	gpio.Mode=GPIO_MODE_AF_INPUT;
	HAL_GPIO_Init(GPIOA, &gpio);

	//konfiguracja UART
	uart.Instance=USART2;
	uart.Init.BaudRate=9600;
	uart.Init.WordLength=UART_WORDLENGTH_8B;
	uart.Init.StopBits=UART_STOPBITS_1;
	uart.Init.Parity=UART_PARITY_NONE;
	uart.Init.Mode=UART_MODE_TX_RX;
	uart.Init.HwFlowCtl=UART_HWCONTROL_NONE;
	uart.Init.OverSampling=UART_OVERSAMPLING_16;
	HAL_UART_Init(&uart);

	//konfiguracja timera TIM4:
	tim.Instance=TIM4;  //TIM4Ch1- PB6- pod┼Ťwietlacz
	tim.Init.Prescaler=160-1;  //16MHz na wej┼Ťciu
	tim.Init.Period=100-1;  //PWM freq = 1kHz
	tim.Init.CounterMode=TIM_COUNTERMODE_UP;
	tim.Init.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE;
	tim.Init.ClockDivision=1-1;
	HAL_TIM_PWM_Init(&tim);
	channel.OCMode=TIM_OCMODE_PWM1;
	channel.Pulse=100;
	channel.OCPolarity=TIM_OCPOLARITY_HIGH;
	channel.OCFastMode=TIM_OCFAST_DISABLE;
	HAL_TIM_PWM_ConfigChannel(&tim, &channel, TIM_CHANNEL_1);

	HAL_TIM_PWM_Start(&tim, TIM_CHANNEL_1);

	//konfiguracja SPI1 do obs┼éugi wy┼Ťwietlacza:
	spi.Instance=SPI1;
	spi.Init.Mode=SPI_MODE_MASTER;
	spi.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4;  //4MHz (max)
	spi.Init.Direction=SPI_DIRECTION_2LINES;
	spi.Init.DataSize=SPI_DATASIZE_8BIT;
	spi.Init.CLKPolarity=SPI_POLARITY_LOW;
	spi.Init.CLKPhase=SPI_PHASE_1EDGE;
	spi.Init.NSS=SPI_NSS_SOFT;
	spi.Init.FirstBit=SPI_FIRSTBIT_MSB;
	spi.Init.TIMode=SPI_TIMODE_DISABLE;
	spi.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;
	spi.Init.CRCPolynomial=7;
	HAL_SPI_Init(&spi);

	__HAL_SPI_ENABLE(&spi);

	HAL_GPIO_WritePin(GPIOC, LCD_CE, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC, LCD_DC, GPIO_PIN_RESET);  //cmd (a nie data)

	lcd_setup();  //config

	/*lcd_draw_text(0,4,"Press button");
	lcd_draw_text(2,37,"to");
	lcd_draw_text(4,10,"START GAME!");
	lcd_copy();*/

	//konfiguracja RTC
	RTC_HandleTypeDef rtc;
	rtc.Instance=RTC;
	rtc.Init.AsynchPrediv=RTC_AUTO_1_SECOND;
	rtc.Init.OutPut=RTC_OUTPUTSOURCE_NONE;
	if (HAL_RTC_Init(&rtc) != HAL_OK) {
	    Error_Handler();
	}
	printf("Stan RTC: %i!\n", HAL_RTC_GetState(&rtc));
	
	RTC_TimeTypeDef time;
	time.Hours=11;  //13:34:50
	time.Minutes=17;
	time.Seconds=50;
	if (HAL_RTC_SetTime(&rtc, &time, RTC_FORMAT_BIN) != HAL_OK) {
		Error_Handler();
	}
	
	RTC_DateTypeDef date;
	date.WeekDay=RTC_WEEKDAY_THURSDAY;
	date.Month=RTC_MONTH_MARCH;
	date.Date=19;  //18.03.2020
	date.Year=20;
	if (HAL_RTC_SetDate(&rtc, &date, RTC_FORMAT_BIN) != HAL_OK) {
		Error_Handler();
	}

	while(1) {
		//wy┼Ťwietlanie zegara
		RTC_TimeTypeDef timeWyn;
		HAL_RTC_GetTime(&rtc, &timeWyn, RTC_FORMAT_BIN);
		printf("%i : %i : %i\n", timeWyn.Hours, timeWyn.Minutes, timeWyn.Seconds);
		/*lcd_draw_time(&time);
		lcd_copy();*/
		HAL_Delay(1000);
	}
}

W terminalu otrzymuj─Ö wiadomo┼Ť─ç wys┼éan─ů przez UART, ┼╝e stan RTC to┬áHAL_RTC_STATE_ERROR (czyli kod 4). Nie wiedzia┼éem co z tym zrobi─ç i napisa┼éem program w CubeMX, kt├│ry tylko wysy┼éa przez UART aktualn─ů godzin─Ö i tam wszystko dzia┼éa. Zajrza┼éem do konfiguracji i widz─Ö, ┼╝e mam j─ů zrobion─ů identycznie chyba, ┼╝e czego┼Ť nie mog─Ö dostrzec... Ju┼╝ nie b─Öd─Ö spamowa┼é kodami, wy┼Ťl─Ö teraz tylko odpowiedni fragment tego kodu z CubeMX.

static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef DateToUpdate = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only 
  */
  hrtc.Instance = RTC;
  hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
  hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */
    
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date 
  */
  sTime.Hours = 10;
  sTime.Minutes = 10;
  sTime.Seconds = 10;

  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
  DateToUpdate.Month = RTC_MONTH_JANUARY;
  DateToUpdate.Date = 1;
  DateToUpdate.Year = 20;

  if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

A w funkcji main jedyny autorski fragment:

printf("Hello World!\n");
  while (1)
  {
	  RTC_TimeTypeDef time;
	  HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
	  int h=time.Hours, m=time.Minutes, s=time.Seconds;
	  printf("%i : %i : %i\n", h,m,s);
	  HAL_Delay(1000);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

 

No i teraz tak.

1. Ten kod z CubeMX dzia┼éa bezb┼é─Ödnie. Resetuj─Ö- zaczyna si─Ö wykonywa─ç od nowa. Odcinam zasilanie (przez port USB) i pod┼é─ůczam ponownie- te┼╝ dzia┼éa.

2. Z kodem, kt├│ry pisa┼éem w samym Workbenchu jest natomiast tak, ┼╝e zadzia┼éa┼é po raz pierwszy po wcze┼Ťniejszym wgraniu programu 1. ^^ Resetuj─Ö przyciskiem- te┼╝ wszystko by┼éo dobrze i program wykonywa┼é si─Ö od pocz─ůtku. Natomiast, gdy wy┼é─ůcz─Ö zasilanie i w┼é─ůcz─Ö to od nowa to samo-┬áHAL_RTC_STATE_ERROR i godzina 00:00:00 ­čś× Jak pr├│bowa┼éem debuggowa─ç to wydaje mi si─Ö, ┼╝e problem jest w funkcji HAL_RTC_Init, gdy wywo┼éywana jest funkcja HAL_RTC_WaitForSynchro(hrtc).

Czy kto┼Ť bardziej obeznany m├│g┼éby rzuci─ç okiem? Mo┼╝e dla kogo┼Ť b─Ödzie oczywiste co ja tu zepsu┼éem, a ja tymczasem siadam do kolejnych pr├│b. Widz─Ö, ┼╝e w tych kodach zapomnia┼éem doda─ç funkcji "lcd_draw_time", ale ju┼╝ nie b─Öd─Ö wyd┼éu┼╝a─ç tego postu... Jak m├│wi┼éem z wy┼Ťwietlaczem nie ma k┼éopot├│w i dzia┼éa dobrze.

PS: Uprzedz─Ö niekt├│re mo┼╝liwe odpowiedzi w stylu "jak wspania┼éy i wygodny jest CubeMX, po co r─Öcznie wystukiwa─ç konfiguracj─Ö" ­čśä Temat za┼éo┼╝y┼éem z ciekawo┼Ťci, ┼╝eby dowiedzie─ç si─Ö co tutaj zrobi┼éem ┼║le, ┼╝e RTC nie dzia┼éa jak nale┼╝y ­čśĽ

Edytowano przez Bhoy67
Link do komentarza
Share on other sites

Bezpo┼Ťrednio raczej nie pomog─Ö, ale zagl─ůdnij tutaj:

https://msalamon.pl/

Masz tam kilka poradnik├│w tycz─ůcych si─Ö F101 i w┼éa┼Ťnie RTC.┬á Jest tam kilka istotnych porad tycz─ůcych tego zagadnienia.

Og├│lnie bardzo interesuj─ůca strona, kt├│ra dotyczy STM32, polecam.

  • Lubi─Ö! 2
Link do komentarza
Share on other sites

B─ůd┼║ aktywny - zaloguj si─Ö lub utw├│rz konto!

Tylko zarejestrowani u┼╝ytkownicy mog─ů komentowa─ç zawarto┼Ť─ç tej strony

Utw├│rz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj si─Ö ┬╗

Zaloguj si─Ö

Posiadasz własne konto? Użyj go!

Zaloguj si─Ö ┬╗
×
×
  • 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.