2022-09-10 12:34 AM
I am working STM32F746-Disco Board, and trying to implement an Alarm in register level. I am trying to implement a system such that it toggles the user led at 5th second of each minute. However, my program toggles differentially. For now, I can notice that it toggles for 2 seconds, but I don't know at which second, or minute?
My codes are below:
RTC_Utils.c
/*
* RTC_Utils.c
*
* Created on: Sep 8, 2022
*/
#include "RTC_utils.h"
#include "stm32f746xx.h"
void RTC_Init(void) {
uint32_t readBit;
// __HAL_RCC_RTC_ENABLE();
// Enable write access to the backup domain
if(((RCC->APB1ENR) & (1U << 28)) == 0) {
// Enable power interface clock
RCC->APB1ENR |= (1U << 28);
readBit = RCC->APB1ENR;
//UNUSED(readBit);
}
// Select LSE as RTC clock source
if(((PWR->CR1) & (1U << 8)) == 0) {
PWR->CR1 |= (1U << 8);
// Wait until the backup domain write protection has been disabled
while(((PWR->CR1) & (1U << 8)) == 0);
}
// Reset LSEON and LSEBY before configuring
RCC->BDCR &= ~((1U << 0) | (1U << 2));
RCC->BDCR |= (1U << 16);
RCC->BDCR &= ~(1U << 16);
// Wait until LSE clock is ready
// while(((RCC->BDCR) & (1U << 1)) == 0);
RCC->BDCR |= (1U << 0);
// Select LSE as RTC clock source
RCC->BDCR |= 1U << 8;
RCC->BDCR &= ~(1U << 9);
// Disable power interface clock
RCC->APB1ENR &= ~(1U << 28);
RCC->BDCR |= 1U << 15;
// Remove Write Protection
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Set INIT bit to 1 in the RTC_ISR register to enter initialization mode
RTC->ISR |= 1U << 7;
// Poll INITF bit of in the RTC_ISR register
while((RTC->ISR & (1U << 6)) == 0);
RTC->CR &= (1U << 6);
// program both the prescaler factors to generate 1 Hz clock
RTC->PRER |= ((2U << 7) - 1) << 16;
RTC->PRER |= (2U << 8) - 1;
// Load the initial time and date values in the shadow registers
RTC->TR |= (1U << 22) | (1U << 21) | (8U << 16) | (4U << 12) | (5U << 8);
RTC->DR |= (2U << 20) | (2U << 16) | (5U << 13) | (0U << 12) | (9U << 8) | (0U << 4) || (8U << 0);
// configure the time format (12 or 24 hours)
RTC->CR &= ~(1U << 6);
// Disable Initialization
RTC->ISR &= ~(1U << 7);
// Enable WPR
RTC->WPR = 0xFF;
}
void RTC_Set_Alarm(void) {
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Clear ALRAE in RTC_CR to disable Alarm A
RTC->CR &= ~(1U << 8);
// Set off alarm A if the second is 5
RTC->ALRMAR |= 0x5;
// Program the Alarm A registers (RTC_ALRMASSR/RTC_ALRMAR).
// Mask every second option
RTC->ALRMAR |= (1U << 23) | (1U << 15) | (1U << 31);
RTC->ALRMAR &= ~(1U << 7);
RTC->CR |= (1U << 8);
RTC->CR |= 1U << 12;
RTC->WPR = 0xFF;
}
void RTC_Alarm_Enable(void) {
RTC_Init();
RTC_Set_Alarm();
// Configure EXTI17
// Select Triggering Edge
EXTI -> RTSR |= EXTI_RTSR_TR17;
// Interrupt Mask Register
EXTI -> IMR |= EXTI_IMR_IM17;
// Event Mask Register
EXTI -> EMR |= EXTI_EMR_EM17;
// Interrupt Pending Register
EXTI -> PR |= EXTI_PR_PR17;
// Set It Priority Most Urgent
NVIC_EnableIRQ(RTC_Alarm_IRQn);
NVIC_SetPriority(RTC_Alarm_IRQn, 0);
}
void RTC_Alarm_IRQHandler(void) {
if (RTC->ISR & (1U << 8)) {
GPIOI->ODR ^= (1U << 1);
RTC->ISR &= ~(1U << 8); // Clear the flag
}
EXTI -> PR |= EXTI_PR_PR17; // Clear pending interrupt flag
}
What is wrong with my code and what to do to toggle led at the 5th second of each minute? Furthermore, I have some doubts about RTC->TR and RTC->DR registers. What happened if I don't make any adjustments on them and how do they work? When and why we should use them? Thx in advance for your response.
2022-09-12 10:52 AM
Maybe better is ask, what you need? 5s toggle LED or RTC Alarm.
5s toggle LED can be more effective handled with PWM TIM = complete MCU offload = no one instruction after start required.
2022-09-13 01:24 AM
2U << 7 = 256
2U << 8 = 512
32768Hz / (256 * 512) = 0.25Hz
I don't think this is what you wanted.
It's in fact 0.5Hz, because the asynchronous prescaler has only 7 bits.
JW