How can I toggle an LED at 5th second of each minute with RTC Alarm?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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.
- Labels:
-
RTC
-
STM32F7 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-10 3:18 AM
As first normal peaple dont waste capacity for learn every bits in ARM registers...
My tip only you dont setup mask seconds for alarm
// 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);
try use LL STM32F439xx HAL User Manual: stm32f4xx_ll_rtc.h File Reference (upv.es)
#define LL_RTC_ALMA_MASK_NONE 0x00000000U
#define LL_RTC_ALMA_MASK_DATEWEEKDAY RTC_ALRMAR_MSK4
#define LL_RTC_ALMA_MASK_HOURS RTC_ALRMAR_MSK3
#define LL_RTC_ALMA_MASK_MINUTES RTC_ALRMAR_MSK2
#define LL_RTC_ALMA_MASK_SECONDS RTC_ALRMAR_MSK1
#define LL_RTC_ALMA_MASK_ALL (RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 | RTC_ALRMAR_MSK1)
usw
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-10 4:53 PM
It's better to use normal register names and definitions, not LL, because using LL doubles the amount of work. When reading reference manual and looking at registers with a debugger, one has to translate LL names to register names and back all the time. In the end it's just a useless waste of time and adds another layer of potential bugs and inefficiency...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-10 5:22 PM
Rewrite the code using normal register defines.
And for a start - all modifications of registers RTC_ISR and EXTI_PR are broken.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-11 12:46 AM
> Rewrite the code using normal register defines.
+1
> And for a start - all modifications of registers RTC_ISR and EXTI_PR broken.
... in the interrupt (setting of INIT bit in RTC_ISR isOK), because status flags are not to be cleared by RMW operation.
> RTC->PRER |= ((2U << 7) - 1) << 16;
> RTC->PRER |= (2U << 8) - 1;
This is wrong, because
- the reset value of RTC_PRER is nonzero (OK in this particular case it does not matter, but generally it's wrong)
- this value results in RTC to run half as fast as it should, when using the standard 32.768kHz crystal - and this maybe is why you see LED blink once in 2.5sec rather than once in 5sec (I haven't checked rest of the code)
I wonder where do you have these values from, as I've seen them in other confused post, too.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-11 7:43 AM
RTC_ISR flag clearing code is broken because it will also clear other flags which are set by hardware (interrupts become pending) during the RMW operation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-12 8:03 AM
@Community member​ I am using a book for these purposes(low-level coding), and it is best practice to use LSE clock, which has 32768 Hz frequency, or 32kHz. To have 1Hz signal, I adjusted the PRER value as in the book.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-12 8:06 AM
Why RTC_ISR and EXTI_PR broken? Because I set and reset the specific bits, and didn't make a change on any other bits?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-12 8:41 AM
Well doing a RMW action on EXTI_PR is apt to clear things unrelated to the bits you want.
Just write the mask for the bit(s) you actually own/manage at that point.
With register level code you likely need to own all the debugging, as very few want to spend hours walking thru others buggy code.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-09-12 8:45 AM
The LSI tends to be very unstable, and not suitable for powered down operation. Certainly in older STM32 the LSI was typically in the 37 KHz realm
A properly implemented LSE circuit with an appropriated loaded crystal should be a lot closer to 32.768 KHz and you'd pick the appropriate prescalers. The LSE should be testable via the export of the signal via a TAMPER or PA8/MCO pin, or via a TIM clocking via a different/better clock.
Up vote any posts that you find helpful, it shows what's working..
