2015-03-22 03:15 PM
Hi,
I am trying to timestamp my frequency capture module with the systick register value but everytime, the systick register gets reloaded with a new value during a frequency capture. as shown below. I have loaded it with a large value as previously the systick was just setup as 1ms timer but the issue still occurs. 940518 940273 940019939751
1001952
1001712 I am using g++ and the code are shown below. Regards Paul#include ''freqcounter.h''
#include ''stm32f10x.h''
#include <stdlib.h>
static
uint16_t IC2Value = 0;
static
freq_cnt_callback registered_callback = NULL;
static
void
RCC_Configuration(
void
);
static
void
GPIO_Configuration(
void
);
static
void
NVIC_Configuration(
void
);
void
init_freqcounter(
void
)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
// Use the 36 MHz clock for the timer by setting the prescaler to 2.
// Lowest frequency it can measured is 36 MHz / 65535 = 5325 Hz.
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = 65535;
// Full range
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM2 configuration: PWM Input mode ------------------------
The external signal is connected to TIM2 CH2 pin (PA.01),
The Rising edge is used as active edge,
The TIM2 CCR2 is used to compute the frequency value
------------------------------------------------------------ */
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
// /* Select the TIM2 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE);
}
void
register_freqcnt_callback(freq_cnt_callback callback_func) {
registered_callback = callback_func;
}
uint32_t get_system_clock(
void
) {
return
SystemCoreClock;
}
static
void
RCC_Configuration(
void
)
{
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
static
void
GPIO_Configuration(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
}
static
void
NVIC_Configuration(
void
)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void
TIM2_IRQHandler(
void
)
{
if
(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)
{
/* Clear TIM2 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
/* Get the Input Capture value */
IC2Value = TIM_GetCapture2(TIM2);
if
(registered_callback != NULL) {
registered_callback(IC2Value);
}
}
}
#include ''stm32f10x.h''
#include <string.h>
#include ''timer.h''
/*-------------------------------Global Variables-----------------------------*/
/*--------------------------------Module Setup--------------------------------*/
// Called before the main loop
void
initialise_timer(
void
)
{
milliSeconds = 0;
microSeconds = 0;
sysTickMicroValue = 0;
prevMicroSeconds = 0;
sysTickHandlerIndex = 0;
// Set the systick for 1ms interrupts.
SysTick_Config(2500000);
//set systick interrupt priority
//4 bits for preemp priority 0 bit for sub priority
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//i want to make sure systick has highest priority amount all other interrupts
NVIC_SetPriority(SysTick_IRQn, 4);
}
/*------------------------------External Functions----------------------------*/
uint32_t get_systick(
void
)
{
return
SysTick->VAL;
}
#include ''driver_adaptors/FreqCounterAdaptor.h''
namespace
cfreqcounter {
extern
''C''
{
#include ''freqcounter.h''
}
}
Queue <FreqLists> FreqCounterAdaptor::rxFifo;
ITimer * FreqCounterAdaptor::system_timer = 0;
FreqCounterAdaptor::FreqCounterAdaptor(ITimer &timer) {
this
->system_timer = &timer;
cfreqcounter::init_freqcounter();
cfreqcounter::register_freqcnt_callback(interrupt_callback);
}
bool
FreqCounterAdaptor::get_last_freqlist(FreqLists * item) {
if
(rxFifo.isEmpty())
{
return
false
;
}
*item = rxFifo.dequeue();
return
true
;
}
void
FreqCounterAdaptor::interrupt_callback(uint16_t cnt_value) {
FreqLists newData;
newData.data = cnt_value;
newData.timestamp = system_timer->get_systick();
rxFifo.enqueue(newData);
}
int
main(
void
) {
TimerAdaptor timer_adaptor;
FreqCounterAdaptor frequency_counter(timer_adaptor);
UsartAdaptor usart;
while
(1) {
FreqLists newData;
if
(frequency_counter.get_last_freqlist(&newData))
{
char
freq_string[10] = { 0 };
snprintf(freq_string, 10,
''%lu,''
, frequency_counter.get_system_clock()/newData.data);
while
(!usart.transmit_data(std::string(freq_string)));
snprintf(freq_string, 10,
''%lu,''
, newData.microseconds_stamp);
while
(!usart.transmit_data(std::string(freq_string)));
}
}
}
2015-03-22 06:49 PM
Well that and it counts down as I recall. I'd probably look to use the DWT_CYCCNT, which counts up, and takes about a minute to wrap. Then I'd confirm if the delay between samples actually large enough to be causing the SysTick number to wrap.
2015-03-22 07:45 PM
Thanks Clive. I have managed to fix it. My fifo was too small. Silly me :) I will look into the DWT_CYCCNT.