Bhoy67 Napisano Marzec 19, 2020 Udostępnij Napisano Marzec 19, 2020 (edytowany) 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 Marzec 19, 2020 przez Bhoy67 Cytuj Link do komentarza Share on other sites More sharing options...
Zealota Marzec 19, 2020 Udostępnij Marzec 19, 2020 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. 2 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
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!