STM32. Быстрый частотомер. Reciprocal counter.

Кто любит RISC в жизни, заходим, не стесняемся.
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

Дано:
1. Датчик у которого на выходе ЧМ сигнал (меандр) частотой 30..300 кГц;
2. Плата STM32F4Discovery (нужна большая внутр частота).
Задача: Получить показания датчика (измерить частоту) 10000 раз в секунду.
Решение.


Исходник main.c
Спойлер

Код: Выделить всё

/* Includes ------------------------------------------------------------------*/
#include "stm32f4_discovery.h"
/* Private define ------------------------------------------------------------*/
#define freqMeasureWindow (uint16_t) 16800;  // тиков - время (окно) измерения (макс)
/* Private function prototypes -----------------------------------------------*/
void TIM1_Config(void);			// Конфиг. таймера времени,
void TIM1_GPIO_config(void);	// его портов,
void TIM1_NVIC_config(void);	// источника прерываний.
void TIM4_Config(void);  // конфиг счетчика импульсов
void TIM4_NVIC_config(void); // источника прерываний
void TIM4_ETR_GPIO_config(void); // его портов
/* Private functions ---------------------------------------------------------*/

/*****************************************************************************************
 * @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_stm32f4xx.s) before to branch to application main.
		To reconfigure the default setting of SystemInit() function, refer to
		system_stm32f4xx.c file
	*/
	// TIM1 Configuration
	TIM1_NVIC_config();
	TIM1_GPIO_config();
	TIM1_Config();
	// TIM4 Configuration
	TIM4_NVIC_config();
	TIM4_ETR_GPIO_config();
	TIM4_Config();
	while (1){
	};
}
/***********************************************************************************************
 * @brief  Configure the TIM1 Pins.
 * @param  None
 * @retval None
 */
void TIM1_Config(void)
{
	TIM_TimeBaseInitTypeDef	TIM_TimeBaseStructure;	// Time Base Structure
	TIM_ICInitTypeDef		TIM_ICInitStructure;	// Input Capture management structure

	/* TIM1 clock enable */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
	/* TIM1 deinitialization */
	TIM_DeInit(TIM1);
	
	// Time base configuration // по факту задаем только ARR (auto-reload register)
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
	TIM_TimeBaseStructure.TIM_Prescaler = 0;	// TIM1 max = 168 MHz     Предделитель
	TIM_TimeBaseStructure.TIM_Period = freqMeasureWindow;	// tic's ~ 100us	   Окно измерения = period*предделитель/168 (us)
												// Specifies the period value to be loaded into the active Auto-Reload Register at the next update event */
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000; // only for advanced-control timers TIM1 and TIM8
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
	
	/* TIM1 configuration: Input capture mode ------------------------
	The Rising edge is used as active edge,
	The TIM1 CCR1 is used to compute the frequency value for CH1 connected to PA8 or PE9
	The TIM1 CCR2 is used to compute the frequency value for CH2 connected to PA9 or PE11
	The TIM1 CCR3 is used to compute the frequency value for CH3 connected to PA10 or PE13
	------------------------------------------------------------ */
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // Specifies the active edge of the input signal
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;	/* TIM Input 1, 2, 3 or 4 is selected to be 
																	 * connected to IC1, IC2, IC3 or IC4, respectively */
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	// TIM Input Capture Prescaler = no prescaler
															// Capture performed each time an edge is detected on the capture input
	TIM_ICInitStructure.TIM_ICFilter = 0x0; // Specifies the input capture filter = no filter
											// This parameter can be a number between 0x0 and 0xF
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInit(TIM1, &TIM_ICInitStructure);
	//TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	//TIM_ICInit(TIM1, &TIM_ICInitStructure);
	//TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
	//TIM_ICInit(TIM1, &TIM_ICInitStructure);
	
	// Syncronization parameters
	TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);	// выдать Trigger по событию Update. нужно чтобы сбрасывать
															// TIM4, который считает входные фронты
	TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1);	// со входа TI1_FP1
	TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Trigger);	// The counter starts at a rising edge of the trigger TRGI
	TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);	// p553 Ref.Man.
		
	// Enable the CC1 Interrupt Request
	TIM_ITConfig(TIM1, TIM_IT_CC1 | TIM_IT_Update, ENABLE);
	// Чтобы синхронизировать начало счета с фронтом измеряемого импульса
	TIM_SelectOnePulseMode (TIM1, TIM_OPMode_Single);	// Counter stops counting at the next update event
														// (clearing the bit CEN)
	// TIM enable counter
	//TIM_Cmd(TIM1, ENABLE);
}
/******************************************************************************************
  * @brief  Configure the Pin7 Port B for TIM1 chanel 2 Alternative Function.
  * @param  None
  * @retval None
  **/
void TIM1_GPIO_config(void) 
{
	GPIO_InitTypeDef GPIO_InitStructure; // Структура регистров для конфигурации портов
	
	/* GPIOA clock enable */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	
	// TIM1 chennel 1,2,3 configuration : PA8, PA9, PA10 
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;
	GPIO_Init(GPIOE, &GPIO_InitStructure); // инициализировать структуру для PA
  
	// Connect TIM pin to AF1 */
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_TIM1 );
}
/******************************************************************************************
  * @brief  Configure the NVIC for TIM1.
  * @param  None
  * @retval None
  **/
void TIM1_NVIC_config(void) 
{
	NVIC_InitTypeDef NVIC_InitStructure; // Структура для конфигурации регистров прерываний

	/* Enable and set TIM1 capture compare interrupt*/
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	/* Enable and set TIM1 update interrupt & TIM10 global */
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
/***********************************************************************************************
 * @brief  Configure the TIM4 as 
 * @param  None
 * @retval None
 */
void TIM4_Config(void)
{
	// TIM4 clock enable
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM4, ENABLE);
	// TIM4 deinitialization
	TIM_DeInit(TIM4);
	// external clock mode source mode 2
	TIM_ETRClockMode2Config(TIM4, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); // счетик CNT тактируется от ETR (PE0), 
																		      // prescaler выкл, по переднему фронту
	// Slave mode reset
	TIM_SelectInputTrigger (TIM4, TIM_TS_ITR0);		// Internal trigger 0 for TIM4,TIM3,TIM2 is TIM1 for TIM4 (p658 in Ref.Man)
	TIM_SelectSlaveMode	(TIM4, TIM_SlaveMode_Reset); 	// TIM4 CNT, presc will be reinited by TIM1_Update event (p658 in Ref.Man)
	TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
	
	// TIM enable counter
	TIM_Cmd(TIM4, ENABLE);
}
/******************************************************************************************
  * @brief  Configure the Pin0 Port E for TIM4 ETR(External trigger) Alternative Function.
  * @param  None
  * @retval None
  **/
void TIM4_ETR_GPIO_config(void) 
{
	GPIO_InitTypeDef GPIO_InitStructure; // Структура регистров для конфигурации портов
	
	/* GPIOB clock enable */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	
	// TIM4 ETR configuration : PE.00
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0; 
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;
	GPIO_Init(GPIOE, &GPIO_InitStructure); // инициализировать структуру
  
	// Connect TIM pin to AF2
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_TIM4); // TIM4_ETR PE0
}
/******************************************************************************************
  * @brief  Configure the NVIC for TIM1.
  * @param  None
  * @retval None
  **/
void TIM4_NVIC_config(void) 
{
	NVIC_InitTypeDef NVIC_InitStructure; // Структура для конфигурации регистров прерываний

	/* Enable and set TIM1 global Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
Исходник stm32f4_it.c
Спойлер

Код: Выделить всё

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"
/* Private define ------------------------------------------------------------*/
#define HClkFreq (uint32_t)168000000
/* Private variables ---------------------------------------------------------*/
__IO uint16_t lastCCRValue = 0;	// 
__IO uint16_t impCount = 0; // количество импульсов (фронтов) пришедших на TIM4.ETR 
							// обновление по событию TIM1_Update
__IO uint32_t freqW = 0;	// частота вычисленная средняя по окну
__IO uint32_t freq1[40];	// массив посчитаных частот каждого импульса в пределах окна
__IO uint32_t freq1Sum;		// сумма значений freq1[] для расчета freq1Avg
__IO uint32_t freq1Avg;		// среднее арифметическое посчитаных частот каждого импульса в пределах окна

/******************************************************************************/
/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f4xx.s).                                               */
/******************************************************************************/
/**
  * @brief  This function handles TIM1 update interrupt request and TIM10 global.
  * @param  None
  * @retval None
  */
void TIM1_UP_TIM10_IRQHandler(void) 
{
	TIM1->SR = ~TIM_IT_Update;
	
	freq1Avg = freq1Sum / (impCount-1);
	freq1Sum = 0;
	
	freqW = HClkFreq * (impCount-1) / lastCCRValue;
} // end func
/********************************************************************************
  * @brief  This function handles TIM1 update interrupt request and TIM10 global.
  * @param  None
  * @retval None
  */
void TIM1_CC_IRQHandler(void) 
{
	//TIM_ClearITPendingBit (TIM1, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3); // clear interrupt flag. необязательно. само сбросится при чтении CCRx
	lastCCRValue = TIM1 -> CCR1;	
	impCount = TIM4 -> CNT;
	
	freq1[impCount-1] = HClkFreq * (impCount-1) / lastCCRValue;
	freq1Sum += freq1[impCount-1];
}
Тут есть еще над чем работать...

Литература и ссылки:
1. DataSheet STM32F4;
2. Reference Manual STM32F4
3. соседняя тема "STM32 частотомер", мои сообщения со стр.6

P.S. Буду писать в несколько этапов. И изменять по ходу пьессы.
Последний раз редактировалось kybin Пт мар 28, 2014 10:35:14, всего редактировалось 5 раз.
Реклама
ut1wpr
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Re: STM32. Быстрый частотомер. Reprocical counter.

Сообщение ut1wpr »

Reprocical counter.
Reciprocal counting - http://www.spectracomcorp.com/Desktopmo ... PortalId=0
С уважением,
Виктор.
Реклама
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reprocical counter.

Сообщение kybin »

ut1wpr писал(а):
Reprocical counter.
Reciprocal counting - http://www.spectracomcorp.com/Desktopmo ... PortalId=0
Да уж. Серьёзная ошибка :oops:
За ссыль спасибо.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение HHIMERA »

4 знака и 16800 тактов на каждую итерацию... Если устраивает... то почему бы и нет...
"Я не даю готовых решений, я заставляю думать!"(С)
Реклама
Эиком - электронные компоненты и радиодетали
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

HHIMERA писал(а):4 знака...
Это с точностью +-10Гц?
Так и есть, ~
Реклама
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

Изображение


Тов. модератору. :write:
СпойлерВнесите, пожалуйста, это в первый пост. или дайте доступ на изменение поста.
Последний раз редактировалось kybin Пт мар 28, 2014 17:10:36, всего редактировалось 1 раз.
Реклама
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение akl »

Почему TIM4.CNT считает с 1, а не с 0?
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение HHIMERA »

А это точно... Reciprocal counter???
"Я не даю готовых решений, я заставляю думать!"(С)
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

akl писал(а):Почему TIM4.CNT считает с 1, а не с 0?
Потому что в 0 сбрасывается по событию Update Generation от TIM1. TIM4 считает фронты.
HHIMERA писал(а):А это точно... Reciprocal counter???
Без сомнений. New frequency counting principle improves resolution 3.Reciprocal counting.
Изображение, where tc is the time of one clock cycle. MT = measuring time.

На самом деле диаграмма не отображает некоторых деталей процесса.. Но это очень важно.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение HHIMERA »

Это НЕ Reciprocal counter!!! :))

Должно быть так...

Finput = (Fref * Ninput) / Nref
где Ninput количество входных периодов за определённое время... а Nref - количество референсных периодов за это же время...
"Я не даю готовых решений, я заставляю думать!"(С)
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

HHIMERA писал(а):Это НЕ Reciprocal counter!!! :))
Должно быть так...
Finput = (Fref * Ninput) / Nref
где Ninput количество входных периодов за определённое время... а Nref - количество референсных периодов за это же время...
Даже не знаю... :)) Чем ваша формула отличается от мной приведенных 2ух? Даже 3ёх - еще одна в коде.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение HHIMERA »

Дык... ща ЛИ нарисуется... проведёт экспертизу метОды... и вынесет вердикт... мне лень... 8)
"Я не даю готовых решений, я заставляю думать!"(С)
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение Леонид Иванович »

Ну так я же не разбираюсь в STM32, поэтому прочитать программу не могу :) По временной диаграмме тоже ничего не понятно. Если бы было описание словами, что делаем шаг за шагом, я бы вынес вердикт.

P.S. Посмотрел немножко программу. Если по каждому фронту входного сигнала генерируется прерывание, так вообще таймера 4 не нужно, входные периоды можно считать программно. Такой частотомер реализуется на чем угодно, был бы только аппаратный захват таймера. Но такой вариант неинтересен, должна быть возможность измерять частоты до 1/2 Fclk.

Ваша формула написана некорректно, так как частота, умноженная на количество входных импульсов (безразмерная величина) и деленная на время даст размерность "секунда в минус второй степени", а никак не частоту. Делить надо на количество импульсов заполнения. Фактически здесь так и есть, но в формуле каким-то образом появилось время.
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение akl »

kybin Вот картинка, представляющая метод. В вашем случае, при Fo=168МГц время измерения будет 16'800 тактов, по окончании которых будет последний активный фронт Fx.
Изображение
book3_1.GIF
Взято из книги, выжимку из которой выкладывал здесь.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение HHIMERA »

akl писал(а):при Fo=168МГц время измерения будет 16'800 тактов, по окончании которых будет последний активный фронт Fx.
Если я правильно понял "курс ликбеза по Reciprocal counter" от ЛИ... то в данном случае - не более 16'800 тактов...
Т.е. таймер должен пинаться каждые 16'800 тактов... но измерительный интервал должен быть чуть короче... тем более... что на конечный результат это практически не влияет...

Для примера... STM32F0Discovery... 48MHz... древние опыты с Reciprocal counter...
Один из таймеров делит клок на 23...
Fclk = TIM_clk = 48004080 Hz
Fout = TIM_clk / 23 = 2087133,9130434782608695652173913

TIM2_freq = (TIM_clk * cnt_input) / cnt_ref;

=============
tизм = ~1сек
cnt_input _2086860 (видно, что интервал измерения чуть меньше 1 сек.)
cnt_ref __47997780

Частота в отладчике Кейл _2087133.913043
Ручной счёт _____________2087133,9130434782608695652173913

=============
tизм = ~0,9сек
cnt_input _1878174
cnt_ref __43198002

Частота в отладчике Кейл _2087133.913043
Ручной счёт _____________2087133,9130434782608695652173913

=============
tизм = ~1,1сек
cnt_input _2295546
cnt_ref __52797558

Частота в отладчике Кейл _2087133.913043
Ручной счёт _____________2087133,9130434782608695652173913

Как видим... девиации времени измерения практически не влияют на результат... в случае с синхронизированным внутренним сигналом картинка вообще идеальная...
При внешнем несинхронизированном сигнале всё заметно хуже... но результат из разрядной сетки не выходит... точность остаётся в пределах расчётной...
"Я не даю готовых решений, я заставляю думать!"(С)
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

HHIMERA, а что насчет tизм ~= 100 мкс?
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

Леонид Иванович писал(а):Ну так я же не разбираюсь в STM32, поэтому прочитать программу не могу :) По временной диаграмме тоже ничего не понятно. Если бы было описание словами, что делаем шаг за шагом, я бы вынес вердикт.
Наверное картинка одному мне понятна потому как я ее рисовал :) :(
Шаг за шагом:
I. Настройка TIM4: Предназначен для счета импульсов измеряемого сигнала.
1. Считать внешние передние фронты (External trigger = ETR)
2. Подключить триггер TIM1 для сброса. По событию TIM1_Update счетчик будет сброшен.
II. Настройка TIM1:
1. One pulse mode. Запуск счета по внешнему триггеру (передний фронт измеряемого сигнала). Остановка и сброс по событию Update (CNT==ARR). Это можно сказать синхронизация
2. Захват по внешнему триггеру (передний фронт измеряемого сигнала). Это чтобы узнать tизм
III. Обработка прерывания TIM1_Update
1. Вычиление частоты
fизм = Base freq * Counted input cycles / Counted clock pulses
fизм = F_tim1 * TIM4_CNT / TIM1_CCR1
Вродк бы все.
Леонид Иванович писал(а):P.S. Посмотрел немножко программу. Если по каждому фронту входного сигнала генерируется прерывание, так вообще таймера 4 не нужно, входные периоды можно считать программно. Такой частотомер реализуется на чем угодно, был бы только аппаратный захват таймера. Но такой вариант неинтересен, должна быть возможность измерять частоты до 1/2 Fclk.
1. исп-ся 2 таймера в связке.
2. прерывание по фронту генерируется для расчета длительности каждого импульса. Забивания их в массив. Вычисления ср. арифметического. Это пережиток прошлых вариаций. Его нужно убрать.
и сделать так:

Код: Выделить всё

void TIM1_UP_TIM10_IRQHandler(void)
{
   TIM1->SR = ~TIM_IT_Update; // сброс флага TIM1_Update
   freqW = HClkFreq * (impCount-1) / TIM1 -> CCR1;
}
Это и вся нагрузка на ядро :)
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение kybin »

HHIMERA писал(а):Дык... ща ЛИ нарисуется... проведёт экспертизу метОды... и вынесет вердикт... мне лень... 8)
ага. вон какую петицию накатал... :)))
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение Goodefine »

kybin писал(а): 2. прерывание по фронту генерируется для расчета длительности каждого импульса. Забивания их в массив. Вычисления ср. арифметического. Это пережиток прошлых вариаций. Его нужно убрать.
и сделать так:...
Это не совсем тот метод о котором говорится - вся фишка в том, чтобы периоды измеряемой частоты считать аппаратно. Вычислять сразу по одному периоду и делать статистику на некотором числе измерений ОДНОГО периода не есть правильно - погрешность в этом случае уменьшаться не будет, вернее будет, но другая. Умозрительно это особенно заметно когда измеряемая частота будет приближаться к "линейке", т.е. к частоте измерительного таймера. В Reciprocal counting увеличение точности достигается накоплением измерительных импульсов за некоторое количество периодов входной частоты. Это число периодов (а также число переполнений измерительного таймера) можно считать в прерывании программно (и тут все понятно, реализация не будет отличаться от реализации на той же avr-ке), либо аппаратно с помощью каскадирования таймеров. Вторая задача, видимо, не слишком очевидно решается в STM, если решается вообще.
Еще есть вторичные нюансы, например введение таймаута, если входная частота отсутствует - чтоб не ждать до бесконечности
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32. Быстрый частотомер. Reciprocal counter.

Сообщение HHIMERA »

kybin писал(а):HHIMERA, а что насчет tизм ~= 100 мкс?
А что не так??? Уже всё написали...

Fclk = TIM_clk = 48004080 Hz
Внешняя частота с STM8L151 1000045Hz ...

TIM2_freq = (TIM_clk * cnt_input) / cnt_ref;

=============
tизм = ~0,0001 сек
cnt_input _96 (видно, что интервал измерения чуть меньше 0,0001 сек.)
cnt_ref _4609

Частота в отладчике Кейл _999868.0147537

Премежёвывается с...

=============
cnt_input _96
cnt_ref _4608

Частота в отладчике Кейл _1000085

Если всё правильно считаю... 7 верных цифры - 4 теряем на временном интервале = 3 верных цифры имеются...
вон какую петицию накатал...
Ну да... чоть прорвало...
"Я не даю готовых решений, я заставляю думать!"(С)
Ответить

Вернуться в «ARM»