2013-12-05 11:31 PM
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
2013-12-13 01:46 AM
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
2013-12-13 04:46 AM
Not sure you're using the same code as posted. Have you verified the periodicity with a scope? Is SystemCoreClock correct? Try making a simpler example toggling a GPIO with the systick timer.
Your formula here is problematicSecondFraction = (uint16_t) (((256 - (uint32_t)RTC_GetSubSecond()) * 1000) / 256);
There are situations where it will return 1000