cstm32microcontrollerstm32f4discovery

How to display time on stm32-discovery


I've been experimenting with the STM32-DISCOVERY a lot lately, but I'm not sure how to get started with an application for this board.

I want to show the time of the RTC on the stm32's display.

How do I get started with this? I have already installed the libraries for the STM32.


Solution

  • I'm not sure what exactly you mean by 'display' (i.e., is it an LCD screen, a serial output-terminal, etc?).

    In any case, the RTC is typically connected to the STM32 through an I2C bus, so you will need to initialize both controllers (RTC and I2C) before you can get/set the date and the time on the RTC.

    Here is how you can initialize the RTC controller:

    void rtc_init()
    {
        RTC_InitTypeDef RTC_InitStructure;
        RTC_TimeTypeDef RTC_TimeStruct;
    
        /* Enable the PWR clock */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
    
        /* Allow access to RTC */
        PWR_BackupAccessCmd(ENABLE);
    
        /* Reset RTC Domain */
        RCC_BackupResetCmd(ENABLE);
        RCC_BackupResetCmd(DISABLE);
    
        /* Enable the LSE OSC */
        RCC_LSEConfig(RCC_LSE_ON);
    
        /* Wait until LSE is ready */
        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
    
        /* Select the RTC Clock Source */
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    
        /* Configure the RTC data register and RTC prescaler */
        RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
        RTC_InitStructure.RTC_SynchPrediv  = 0xFF;
        RTC_InitStructure.RTC_HourFormat   = RTC_HourFormat_24;
        RTC_Init(&RTC_InitStructure);
    
        /* Set the time to 00h 00mn 00s AM */
        RTC_TimeStruct.RTC_H12     = RTC_H12_AM;
        RTC_TimeStruct.RTC_Hours   = 0x00;
        RTC_TimeStruct.RTC_Minutes = 0x00;
        RTC_TimeStruct.RTC_Seconds = 0x00;
        RTC_SetTime(RTC_Format_BCD,&RTC_TimeStruct);
    }
    

    And here is how you can get/set the date and the time on the RTC, excluding day-of-the-week:

    In the header file:

    typedef struct
    {
        unsigned char second;
        unsigned char minute;
        unsigned char hour;
        unsigned char day;
        unsigned char month;
        unsigned char year;
    }
    rtc_data_t;
    
    void rtc_get(rtc_data_t* rtc_data);
    void rtc_set(rtc_data_t* rtc_data);
    

    In the source file:

    #define SENSOR_ADDRESS 0xD0 // or set this according to your HW configuration
    
    #define HEX_2_DEC(val) (((val)/16)*10+((val)%16))
    #define DEC_2_HEX(val) (((val)/10)*16+((val)%10))
    
    typedef struct
    {
        unsigned char second;
        unsigned char minute;
        unsigned char hour;
        unsigned char weekday;
        unsigned char day;
        unsigned char month;
        unsigned char year;
    }
    raw_data_t;
    
    void rtc_get(rtc_data_t* rtc_data)
    {
        raw_data_t raw_data;
        i2c_polling_read(SENSOR_ADDRESS,0x00,sizeof(raw_data),(char*)&raw_data);
        rtc_data->second = HEX_2_DEC(raw_data.second);
        rtc_data->minute = HEX_2_DEC(raw_data.minute);
        rtc_data->hour   = HEX_2_DEC(raw_data.hour  );
        rtc_data->day    = HEX_2_DEC(raw_data.day   );
        rtc_data->month  = HEX_2_DEC(raw_data.month );
        rtc_data->year   = HEX_2_DEC(raw_data.year  );
    }
    
    void rtc_set(rtc_data_t* rtc_data)
    {
        raw_data_t raw_data;
        raw_data.second = DEC_2_HEX(rtc_data->second);
        raw_data.minute = DEC_2_HEX(rtc_data->minute);
        raw_data.hour   = DEC_2_HEX(rtc_data->hour  );
        raw_data.day    = DEC_2_HEX(rtc_data->day   );
        raw_data.month  = DEC_2_HEX(rtc_data->month );
        raw_data.year   = DEC_2_HEX(rtc_data->year  );
        raw_data.weekday = RTC_Weekday_Monday; // or calculate the exact day
        i2c_polling_write(SENSOR_ADDRESS,0x00,sizeof(raw_data),(char*)&raw_data);
    }
    

    In addition to the initialization of the I2C controller, you will also need to implement the read/write routines.

    UPDATE:

    Given rtc_data_t* rtc_data, here is a Segger-GUI code for displaying HH:MM:SS on the LCD:

    char text[16] = {0};
    sprintf(text,"%.2u:%.2u:%.2u",rtc_data->hour,rtc_data->minute,rtc_data->second);
    GUI_RECT gui_rect = {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};
    GUI_DispStringInRect(text,&gui_rect,GUI_TA_HCENTER|GUI_TA_VCENTER);
    

    Of course, you will have to initialize the LCD controller itself...