无法让RTC工作

时间:2013-05-09 18:50:41

标签: c++ stm32

我正在尝试创建一个读取RTC时钟值并将其打印到串行监视器的简单程序。 USART工作正常,但我无法弄清楚RTC有什么问题。它给我的所有时间都与setuRTC()中设置的值相同。第二个中断也不起作用。编辑:我使用的是STM32f1开发板,与this

相同

这是我的RTC设置:

void setupRTC(void){
    RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); //Enable the power and backup interface clocks by setting the PWREN and BKPEN bitsin the RCC_APB1ENR register
    PWR->CR |= PWR_CR_DBP;                     //Enable access to the backup registers and the RTC.
    RCC->BDCR |= RCC_BDCR_LSEON;               //External Low Speed oscillator enable 
    while((RCC->BDCR & RCC_BDCR_LSERDY) == 0); //Wait until external oscillisator is stabilised
    RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
    sendstr(textlse);
    RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;          //Select Source (LSE oscillator clock used as RTC clock )
    RCC->BDCR &= ~((1 << 8) | (1 << 9));       //Unusable clock source, here to prevent warnings, turn off clock sources to RTC.
    RCC->BDCR = RCC_BDCR_RTCEN;                //RTC clock enable
    RTC->CRL &= ~RTC_CRL_RSF;                  //Clear registers Synchronized Flag
    while(!(RTC->CRL & RTC_CRL_RSF));          //Wait for the RSF bit in RTC_CRL to be set by hardware

    while((RTC->CRL & RTC_CRL_RTOFF) == 0);    //Wait for RTOFF It is not possible to write to the RTC_CR register while the peripheral is completing a previous write operation
    RTC->CRL |= RTC_CRL_CNF;                   //Set the CNF bit to enter configuration mode


    /* Set RTC COUNTER MSB word */
    RTC->CNTH = (12*3600 + 40*60 + 00) >> 16;  //Random time
    /* Set RTC COUNTER LSB word */
    RTC->CNTL = ((12*3600 + 40*60 + 00)& 0x0000FFFF);
    RTC->CRH |= RTC_CRH_SECIE;                 //Second Interrupt Enable
    RTC->CRL &= ~RTC_CRL_CNF;                  //Exit configuration mode
    while((RTC->CRL & RTC_CRL_RTOFF) == 0);    //Wait for RTOFF 
    sendstr(textconf);
}

以下是整个计划:

#include "stm32f10x.h"
#include <stdio.h>

uint8_t text[] = {"\nSTM32 USART test ä ö \n"};
uint8_t textlse[] = {"LSE ready\n"};
uint8_t textconf[] = {"Configuration complete\n"};
char str[32]; // buffer for text

uint8_t RxBuffer[1024];
int rxcount = 0;
// Private function prototypes
void sendstr(uint8_t * str);
void sendChar(uint8_t ch);
void sendTime(uint32_t ch);
void setupRTC(void);
void setupUSART(void);
u32 rtc_get_counter_val(void);



void setupRTC(void){
    RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); //Enable the power and backup interface clocks by setting the PWREN and BKPEN bitsin the RCC_APB1ENR register
    PWR->CR |= PWR_CR_DBP;                     //Enable access to the backup registers and the RTC.
  RCC->BDCR |= RCC_BDCR_LSEON;               //External Low Speed oscillator enable 
    while((RCC->BDCR & RCC_BDCR_LSERDY) == 0); //Wait until external oscillisator is stabilised
    RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
    sendstr(textlse);
    RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;          //Select Source (LSE oscillator clock used as RTC clock )
  RCC->BDCR &= ~((1 << 8) | (1 << 9));       //Unusable clock source, here to prevent warnings, turn off clock sources to RTC.
    RCC->BDCR = RCC_BDCR_RTCEN;                //RTC clock enable
    RTC->CRL &= ~RTC_CRL_RSF;                  //Clear registers Synchronized Flag
    while(!(RTC->CRL & RTC_CRL_RSF));          //Wait for the RSF bit in RTC_CRL to be set by hardware

    while((RTC->CRL & RTC_CRL_RTOFF) == 0);    //Wait for RTOFF It is not possible to write to the RTC_CR register while the peripheral is completing a previous write operation
    RTC->CRL |= RTC_CRL_CNF;                   //Set the CNF bit to enter configuration mode


    /* Set RTC COUNTER MSB word */
  RTC->CNTH = (12*3600 + 40*60 + 00) >> 16;  //Random time
  /* Set RTC COUNTER LSB word */
  RTC->CNTL = ((12*3600 + 40*60 + 00)& 0x0000FFFF);
    RTC->CRH |= RTC_CRH_SECIE;                 //Second Interrupt Enable
    RTC->CRL &= ~RTC_CRL_CNF;                  //Exit configuration mode
    while((RTC->CRL & RTC_CRL_RTOFF) == 0);    //Wait for RTOFF 
    sendstr(textconf);
}

void setupUSART(void){
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
    USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
    USART1->BRR = (SystemCoreClock / 115200);
    GPIOA->CRH &= 0xFFFFF00F;                                 //Set RX(PA10) and TX(PA9) pins
    GPIOA->CRH |= 0x000008A0;                                 //In TTL communication, TX pin must be conficured as pushpull
    NVIC_EnableIRQ(USART1_IRQn);
    USART1->CR1 |= USART_CR1_RXNEIE;                          //Enable USART interrupt
}

int main(void)
{
    vu32 dly;
    uint32_t time;
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;                       //Enable clock for PC pins
  GPIOC->CRL &= 0x00FFFFFF;                                 //Setup PC6 and PC6 leds
    GPIOC->CRL |= 0x33000000;
    setupUSART();
    setupRTC();
    sendstr(text);


    while (1)
  {
        time = rtc_get_counter_val();
        sprintf(str, "%10d\n", time);
        sendstr(str);
        for(dly = 0; dly < 1000000; dly++);
  }
}

void sendChar(uint8_t ch){
    while(!(USART1->SR & USART_SR_TXE));
        USART1->DR = ch;

}

void sendTime(uint32_t ch){
    while(!(USART1->SR & USART_SR_TXE));
        USART1->DR = ch;

}


void sendstr(uint8_t * str){
    while(*str != 0){
        sendChar(*str);
        str++;
    }
}


void USART1_IRQHandler(void){
    if(USART1->SR & 0x0020){ //content of the shift register is transferred to the RDR RXNE bit.
        GPIOC->BSRR = (1 << 7);
        RxBuffer[rxcount++] = (uint8_t)(USART1->DR & (uint8_t)USART_DR_DR);
        USART1->SR = (uint16_t)~0x0020;
        sendstr(RxBuffer);
  }
}


void RTC_IRQHandler(void){
    if(RTC->CRL & RTC_CRL_SECF){
        GPIOC->BSRR = (1 << 7);
        RTC->CRL &= ~RTC_CRL_SECF;
    }
}



u32 rtc_get_counter_val(void)
{
    return (RTC->CNTH << 16) | RTC->CNTL;
}

1 个答案:

答案 0 :(得分:3)

Mayby为时已晚,但问题是您没有为RTC设置任何时钟源。

需要交换以下几行:

RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
RCC->BDCR &= ~((1 << 8) | (1 << 9));

为:

RCC->BDCR &= ~((1 << 8) | (1 << 9));
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;

在您首次正确设置时钟源之前的方式,然后再次清除这些位,使RTC无需计时。