Skip to main content
klemen
Associate III
December 6, 2013
Question

RTC Time on Discovery L152

  • December 6, 2013
  • 11 replies
  • 2170 views
Posted on December 06, 2013 at 08:31

Dear Sir/Madam,

I am a novice ARM programmer, trying to get the hang of things. It's a bit more complex than programming an 8-bit AVR controller... Anyway I was wondering, why I cannot read the time from the RTC_TimeTypeDef structure. Here is my main code, where the LCD display shows only SecondFraction (loops from 0 to 1000 in one second): I need also the seconds...

#include <
stdio.h
>
#include ''stm32l1xx.h''
#include ''main.h''
#include ''LED.h''
#include ''stm32l_discovery_lcd.h''
#include ''discover_functions.h''
#include ''discover_board.h''
// DECLARATION OF FUNCTION PROTOTYPES
void Init_GPIO(void);
void RCC_Configuration(void);
void RTC_Configuration(void);
void RTC_TamperConfiguration(void);
void Delay(__IO uint32_t nTime);
void TimingDelay_Decrement(void);
// DECLARATION OF VARIABLES
RTC_InitTypeDef RTC_InitStructure;
RTC_TimeTypeDef RTC_TimeStruct;
static __IO uint32_t TimingDelay;
__IO uint16_t MillisecondTimer = 0;
// FUNCTION DECLARATION
// CRC_16 calculation
int16_t i;
uint16_t crc_16_update(uint16_t crc, uint8_t *data) { 
crc = crc ^ *data; 
for(i=0;i<
8
;i++) {
if(crc & 0001)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
return crc;
}
// Get current time in seconds + second fraction (RTC_TimeStructure)
// pointer to a RTC_TimeTypeDef structure that contains the current time values
uint16_t RTC_Get_Time(RTC_TimeTypeDef *RTC_TimeStructure) {
uint16_t SecondFraction = 0;
uint16_t Second = 0;
Second = (uint16_t) ((RTC_TimeStructure->RTC_Seconds)*1000);
SecondFraction = (uint16_t) (((256 - (uint32_t)RTC_GetSubSecond()) * 1000) / 256);
return (Second + SecondFraction);
}
// TEST
// crc test
uint16_t testCRC = 0x25FA;
uint16_t CRC_init = 0xFFFF;
uint16_t crc_16;
uint8_t *pD;
uint16_t crc_display[5];
// timer test
uint32_t Timer;
uint16_t TimerStr[5];
//**********************************************************************************************//
// MAIN
//**********************************************************************************************// 
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{ 
/*!< At this stage the microcontroller clock setting is already configured, 
this is done through SystemInit() function which is called from startup
file (startup_stm32l1xx_md.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32l1xx.c file
*/
RTC_TimeTypeDef RTC_TimeStruct;
// Configure Clocks for Application need
RCC_Configuration();
// Configure the RTC peripheral by selecting the clock source
RTC_Configuration();
// Configure the RTC tamper register : To Clear all the Backup data register
RTC_TamperConfiguration();
// SysTick 1 msec interrupts (1000 = 1ms, 100 = 10 ms ...) 
if(SysTick_Config(SystemCoreClock / 1000))
{
// capture error
while(1); 
}
// Initialize GPIO
Init_GPIO (); 
// Initialize LCD
LCD_GLASS_Configure_GPIO();
LCD_GLASS_Init();
LCD_ContrastConfig(LCD_Contrast_Level_7);
// Initialize LED
LED_Init();
// Initialize time Stucture
RTC_TimeStructInit(&RTC_TimeStruct);
//CRC CALCULATION AND DISPLAY TEST
// crc_16 = CRC_init;
// pD = (uint8_t*) &testCRC;
// crc_16 = crc_16_update(crc_16,pD);
// pD++;
// crc_16 = crc_16_update(crc_16,pD); 
// convert_into_char((uint32_t) crc_16,crc_display); 
// LCD_GLASS_DisplayStrDeci(crc_display);
while(1) { 
// Get milisecond timer
MillisecondTimer = (uint16_t) RTC_Get_Time(&RTC_TimeStruct);
convert_into_char((uint32_t) MillisecondTimer,TimerStr);
LCD_GLASS_DisplayStrDeci(TimerStr);
} 
//COUNTDOWN DISPLAY TEST
// Timer = 10;
// LED_Off(0x00);
// LED_Off(0x01);
// while(1) {
// LED_On(0x00);
// LED_On(0x01);
// convert_into_char((uint32_t) Timer,TimerStr);
// LCD_GLASS_Clear(); 
// LCD_GLASS_DisplayStrDeci(TimerStr);
// Delay(1000); 
// if(Timer == 0) {
// break;
// } 
// Timer--; 
// }
// LED_Off(0x00);
// LED_Off(0x01);
}
/**
* @brief Configures the different system clocks.
* @param None
* @retval None
*/
void RCC_Configuration(void)
{ 
// Enable HSI Clock
RCC_HSICmd(ENABLE);
// Wait till HSI is ready
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET) {}
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
RCC_MSIRangeConfig(RCC_MSIRange_6);
// Enable the GPIOs Clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC| RCC_AHBPeriph_GPIOD| RCC_AHBPeriph_GPIOE| RCC_AHBPeriph_GPIOH, ENABLE); 
// Enable comparator clock LCD and PWR mngt
RCC_APB1PeriphClockCmd(RCC_APB1Periph_COMP | RCC_APB1Periph_LCD | RCC_APB1Periph_PWR,ENABLE);
// Enable ADC clock & SYSCFG
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_SYSCFG , ENABLE);
// Allow access to the RTC
PWR_RTCAccessCmd(ENABLE);
// Reset Backup Domain
RCC_RTCResetCmd(ENABLE);
RCC_RTCResetCmd(DISABLE);
// LSE Enable
RCC_LSEConfig(RCC_LSE_ON);
// Wait till LSE is ready
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {}
RCC_RTCCLKCmd(ENABLE);
// LCD Clock Source Selection
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_HSEConfig(RCC_HSE_OFF);
if(RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET )
{
while(1);
}
}
/**
* @brief Configures the different RTC clocks.
* @param None
* @retval None
*/
void RTC_Configuration(void)
{ 
RTC_InitTypeDef RTC_InitStructure;
RTC_TimeTypeDef RTC_TimeStruct;
// Enable the PWR clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
// Allow access to the RTC
PWR_RTCAccessCmd(ENABLE);
// Reset Backup Domain
RCC_RTCResetCmd(ENABLE);
RCC_RTCResetCmd(DISABLE);
// LSE Enable
RCC_LSEConfig(RCC_LSE_ON);
// Wait till 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);
// Enable the RTC Clock
RCC_RTCCLKCmd(ENABLE);
// Wait for RTC APB registers synchronisation
RTC_WaitForSynchro();
}
/**
* @brief RTC Tamper Configuration..
* @param None
* @retval None
*/
void RTC_TamperConfiguration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// EXTI configuration
EXTI_ClearITPendingBit(EXTI_Line19);
EXTI_InitStructure.EXTI_Line = EXTI_Line19;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Enable RTC_TAMP_STAMP_IRQn
NVIC_InitStructure.NVIC_IRQChannel = TAMPER_STAMP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// determines the number of active pulse for the specific level
RTC_TamperFilterConfig(RTC_TamperFilter_2Sample);
// Determines the frequency at which each of the tamper inputs are sampled
RTC_TamperSamplingFreqConfig(RTC_TamperSamplingFreq_RTCCLK_Div32768);
RTC_TamperPullUpCmd(DISABLE);
// Select the tamper 1 with High level
RTC_TamperTriggerConfig(RTC_Tamper_2, RTC_TamperTrigger_HighLevel );
// Clear tamper 1 flag
RTC_ClearFlag(RTC_FLAG_TAMP2F);
}
/**
* @brief To initialize the I/O ports
* @caller main
* @param None
* @retval None
*/
void Init_GPIO(void)
{ 
} 
/**
* @brief Inserts a delay time.
* @param nTime: specifies the delay time length, in 1 ms.
* @retval None
*/
void Delay(__IO uint32_t nTime)
{
// delay 1000 ms introduces 2000 ms delay (don't know why)
// to compensate for this, divide argument by 2
TimingDelay = (uint32_t) nTime/2;
while(TimingDelay != 0); 
}
/**
* @brief Decrements the TimingDelay variable.
* @param None
* @retval None
*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{ 
TimingDelay--;
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{ 
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */
// Infinite loop
while (1)
{
}
}
#endif

Please point me in the right direction. Thank you very much and best regards, K #one-question-per-thread
    This topic has been closed for replies.

    11 replies

    klemen
    klemenAuthor
    Associate III
    December 6, 2013
    Posted on December 06, 2013 at 14:18

    klemen
    klemenAuthor
    Associate III
    December 6, 2013
    Posted on December 06, 2013 at 14:23

    Hello,

    sorry for the post. I forgot to call

    void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct)

    I seem to have another problem with the delay function:

    if I call Delay(1000), the pause is 2000 ms long. So I modified the delay function and divided the argument to get the right time (please see the code from my previous post). But I do not understand why?

    (Sorry for posting on the same thread, but I figured that it would be a waste of space if I had opened another thread).

    Thank you and best regards,

    K

    Andrew Neil
    Super User
    December 6, 2013
    Posted on December 06, 2013 at 16:13

    I don't see anywhere any call to TimingDelay_Decrement() ?

    ''Sorry for posting on the same thread, but I figured that it would be a waste of space if I had opened another thread''

    On the contrary - it is far better to keep just one question per thread - you can always paste a link for cross-reference, if appropriate...

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    Tesla DeLorean
    Guru
    December 6, 2013
    Posted on December 06, 2013 at 16:28

    Ok, you'll need to pay attention to what SystemInit() in system_stm32l1xx.c is doing, and the hard coded value in SystemCoreClock.

    Then review what HSI (16MHz) is at, and that you're switching to it. HSE is 8 MHz, supplied via the MCO pin of the ST-LINK's F103 chip
    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    December 6, 2013
    Posted on December 06, 2013 at 16:32

    Consider also the appropriate use of local/auto variables?

    // FUNCTION DECLARATION
    // CRC_16 calculation
    int16_t i;
    uint16_t crc_16_update(uint16_t crc, uint8_t *data) { 
    crc = crc ^ *data; 
    for(i=0;i<
    8
    ;i++) {
    if(crc & 0001)
    crc = (crc >> 1) ^ 0xA001;
    else
    crc = (crc >> 1);
    }
    return crc;
    }

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    klemen
    klemenAuthor
    Associate III
    December 9, 2013
    Posted on December 09, 2013 at 14:24

    Thank you for pointing it out. How did it get up there? :)

    Also I will take a look at the SystemInit() in more detail to figure it out!

    Thank you and best regards,

    K

    klemen
    klemenAuthor
    Associate III
    December 9, 2013
    Posted on December 09, 2013 at 14:27

    Thank you for the answer,

    the TimingDelay_Decrement() is called in System Tick handler located in ''stm32l1xx_it.c''.

    Best regards,

    K

    Tesla DeLorean
    Guru
    December 9, 2013
    Posted on December 10, 2013 at 00:51

    uint16_t crc16fast(uint16_t crc, uint8_t data)
    {
    static const uint16_t crctbl[] = { // Nibble Table 0xA001 Polynomial - sourcer32@gmail.com
    0x0000,0xCC01,0xD801,0x1400,0xF001,0x3C00,0x2800,0xE401,
    0xA001,0x6C00,0x7800,0xB401,0x5000,0x9C01,0x8801,0x4400 };
    crc = crc ^ data;
    crc = (crc >> 4) ^ crctbl[crc & 0xF]; // Process 4-bits at a time
    crc = (crc >> 4) ^ crctbl[crc & 0xF]; // Right Shifting
    return(crc);
    }

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    klemen
    klemenAuthor
    Associate III
    December 13, 2013
    Posted on December 13, 2013 at 10:22

    Thank you for the optimized crc calculation.

    Right now, the standard (no LUT) crc works ok (the refresh rate of the data is not very high), but I will perhaps use the code in future more time-critical implementations.

    Best regards,

    K

    klemen
    klemenAuthor
    Associate III
    December 13, 2013
    Posted on December 13, 2013 at 10:46

    Hello Mr.clive1,

    i have tested that my SYSCLKSource is HSI (using the RCC_GetSYSCLKSource() returns 0x04, which is by documentation the HSI). I have also checked the HSI value (in stm32l1xx.h) and its:

    #if !defined (HSI_VALUE)
    #define HSI_VALUE ((uint32_t)16000000)

    I still need to divide the delay value by two in order to get the correct delay (please see the code previously attached)... Best regards, K