#c #clock #stm32f4discovery #real-time-clock
Вопрос:
В настоящее время я пытаюсь отобразить время и дату с помощью микроконтроллера STM32F407VGTX, однако у меня возникли некоторые проблемы. Основная проблема возникает при переключении с напряжения VDD на напряжение VBAT. Часы сбрасываются, когда этого не должно быть. Действительно, в таблице данных нам сказано, что регистры RTC сбрасываются только в том случае, если два напряжения VBAT и VDD выключены. Я инициализировал время с помощью EtatClock_t RTC_init(void)
функции, затем, когда я понижаю напряжение питания, часы автоматически сбрасываются. Тем не менее я следовал порядку запуска часов. Вы нашли решения?
typedef enum
{
FirstInit,
KO,
AlreadyInit
} EtatClock_t;
typedef struct {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday; //date
int tm_mon; //month
int tm_year; //year
int tm_wday;
}rtc_time_t;
EtatClock_t RTC_init(void)
{
uint32_t reg32;
// Enable the PWR peripheral
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// Access to RTC, RTC Backup and RCC CSR registers enabled
PWR->CR |= PWR_CR_DBP;
if(RTC->ISR amp; RTC_ISR_INITS)
return AlreadyInit;
// Turn on LSE and wait until it become stable
// Reset LSEON and LSEBYP bits before configuring the LSE ------------------
// Reset LSEON bit
reg32 = RCC->BDCR;
reg32 amp;= ~(RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL | RCC_BDCR_LSERDY | RCC_BDCR_LSEON);
reg32 |= (1<<RCC_BDCR_RTCSEL_Pos); // Select LSE as clock source
RCC->BDCR = reg32 | RCC_BDCR_BDRST; // BDRST reset
RCC->BDCR = reg32; // end of reset
reg32 |= RCC_BDCR_LSEON;
RCC->BDCR = reg32; // external low-speed oscillator enable
while(!(RCC->BDCR amp; RCC_BDCR_LSERDY)); // wait for oscillator ready
RCC->BDCR = reg32 | RCC_BDCR_RTCEN; // RTC clock enable
// Disable the write protection for RTC registers
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Wait for the RTC APB registers synchronization
if (RTC_WaitForSynchro() != SUCCESS) {
// Enable the write protection for RTC registers
RTC->WPR = 0xFF;
// Access to RTC, RTC Backup and RCC CSR registers disabled
PWR->CR amp;= ~PWR_CR_DBP;
return KO;
}
// Enter the RTC initialization mode
if (RTC_EnterInitMode() != SUCCESS) {
// Enable the write protection for RTC registers
RTC->WPR = 0xFF;
// Access to RTC, RTC Backup and RCC CSR registers disabled
PWR->CR amp;= ~PWR_CR_DBP;
return KO;
}
// Clear RTC CR FMT Bit (24-hour format)
RTC->CR amp;= ~RTC_CR_FMT;
// Configure the RTC prescaler
RTC->PRER = 0x007f00ff; // Asynch = 128, Synch = 256
// Exit the RTC Initialization mode
RTC->ISR amp;= ~RTC_ISR_INIT;
// Enable the write protection for RTC registers
RTC->WPR = 0xFF;
// Access to RTC, RTC Backup and RCC CSR registers disabled
PWR->CR amp;= ~PWR_CR_DBP;
return FirstInit;
}
Я использую эти две функции ErrorStatus RTC_WaitForSynchro(void)
и ErrorStatus RTC_EnterInitMode(void)
.
ErrorStatus RTC_WaitForSynchro(void)
{
// Clear the RSF flag
RTC->ISR amp;= ~RTC_ISR_RSF;
// Wait the registers to be synchronized
while (!(RTC->ISR amp; RTC_ISR_RSF));
return (RTC->ISR amp; RTC_ISR_RSF) ? SUCCESS : ERROR;
}
// Enters the RTC Initialization mode
// return: SUCCESS if RTC is in initialization mode, ERROR otherwise
// note: write protection to RTC registers must be disabled (RTC_WPR = 0xCA,0x53)
// note: access to the RTC registers must be enabled (bit DBP set in PWR_CR register)
ErrorStatus RTC_EnterInitMode(void) {
if (!(RTC->ISR amp; RTC_ISR_INITF)) {
// Set the initialization mode
RTC->ISR = RTC_ISR_INIT;
// Wait till RTC is in INIT state or timeout
while (!(RTC->ISR amp; RTC_ISR_INITF));
return (RTC->ISR amp; RTC_ISR_INITF) ? SUCCESS : ERROR;
}
Для отображения времени и даты я использую эти две функции ErrorStatus RTC_SetDateTime(rtc_time_t *time)
и void RTC_GetDateTime(rtc_time_t *time)
ErrorStatus RTC_SetDateTime(rtc_time_t *time)
{
uint32_t TR,DR;
// Calculate value for time register
TR = (((time->tm_hour / 10) << 20) ((time->tm_hour % 10) << 16)
((time->tm_min / 10) << 12) ((time->tm_min % 10) << 8)
((time->tm_sec / 10) << 4) (time->tm_sec % 10)) ;
// (time->RTC_H12 << 12)) amp; RTC_TR_RESERVED_MASK;
// Calculate value for date register
DR = ((((time->tm_year-2000) / 10) << 20) (((time->tm_year-2000) % 10) << 16)
((time->tm_mon / 10) << 12) ((time->tm_mon % 10) << 8)
((time->tm_mday / 10) << 4) (time->tm_mday % 10));
// Access to RTC, RTC Backup and RCC CSR registers enabled
PWR->CR |= PWR_CR_DBP;
// Disable the write protection for RTC registers
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Enter the RTC initialization mode
if (RTC_EnterInitMode() == SUCCESS) {
// Write date and time to the RTC registers
RTC->TR = TR;
RTC->DR = DR;
// Exit the RTC Initialization mode
RTC->ISR amp;= ~RTC_ISR_INIT;
// Wait for synchronization if BYPSHAD bit is not set in the RTC_CR register
TR = SUCCESS;
if (!(RTC->CR amp; RTC_CR_BYPSHAD)) {
TR = RTC_WaitForSynchro();
}
} else TR = ERROR;
// Enable the write protection for RTC registers
RTC->WPR = 0xFF;
// Access to RTC, RTC Backup and RCC CSR registers disabled
PWR->CR amp;= ~PWR_CR_DBP;
return TR;
}
// Get current date and time
// input:
// Time - pointer to RTC time structure
// Date - pointer to RTC date structure
// return: date and time in Time and Date structures
void RTC_GetDateTime(rtc_time_t *time)
{
uint32_t TR,DR;
// Get date and time (clear reserved bits just for any case)
TR = RTC->TR amp; RTC_TR_RESERVED_MASK;
DR = RTC->DR amp; RTC_DR_RESERVED_MASK;
// Convert BCD to human readable format
time->tm_hour = (((TR >> 20) amp; 0x03) * 10) ((TR >> 16) amp; 0x0f);
time->tm_min = (((TR >> 12) amp; 0x07) * 10) ((TR >> 8) amp; 0x0f);
time->tm_sec = (((TR >> 4) amp; 0x07) * 10) (TR amp; 0x0f);
time->tm_year = (((DR >> 20) amp; 0x03) * 10) (((DR >> 16) amp; 0x0f) 2000);
time->tm_mon = (((DR >> 12) amp; 0x01) * 10) ((DR >> 8) amp; 0x0f);
time->tm_mday = (((DR >> 4) amp; 0x03) * 10) (DR amp; 0x0f);
time->tm_wday = (DR amp; RTC_DR_WDU) >> 13;
}
Комментарии:
1. Возможно, вы захотите вместо этого спросить об обмене стеком электротехники , так как это больше похоже на проблему с оборудованием, а не с программированием.