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-06 05:18 AM
2013-12-06 05:23 AM
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, K2013-12-06 07:13 AM
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...2013-12-06 07:28 AM
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 chip2013-12-06 07:32 AM
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;
}
2013-12-09 05:24 AM
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, K2013-12-09 05:27 AM
Thank you for the answer,
the TimingDelay_Decrement() is called in System Tick handler located in ''stm32l1xx_it.c''. Best regards, K2013-12-09 03:51 PM
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);
}
2013-12-13 01:22 AM
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