skyksandr
@skyksandr
Full Stack Ruby on Rails Developer

STM32F4 Discovery. Вопрос по input capture mode

Здравствуйте,

подскажите, пожалуйста, что я делаю не так.
Задача — чтение ширины импульса.
Погуглив, решил использовать Input capture mode у таймера.
Получился вот такой код:
#include "stm32f4xx.h"
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_tim.h>
#include <misc.h>
#include "lcd.hpp"
#include "stdio.h"

volatile int IC3ReadValue1 = 0;
volatile int IC3ReadValue2 = 0;
volatile int Capture = 0;
volatile int CaptureNumber = 0;
volatile int dataCaptureReady = 0;

void tim3ConfigRising()
{

	TIM_ICInitTypeDef timICStruct;

	timICStruct.TIM_Channel = TIM_Channel_2;
	timICStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	timICStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	timICStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	timICStruct.TIM_ICFilter = 0x0;

	TIM_ICInit(TIM3, &timICStruct);

}

void tim3ConfigFalling()
{
	TIM_ICInitTypeDef timICStruct;

	timICStruct.TIM_Channel = TIM_Channel_2;
	timICStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
	timICStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	timICStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	timICStruct.TIM_ICFilter = 0x0;

	TIM_ICInit(TIM3, &timICStruct);

}

void initTimers()
{
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

	  /* Частота счёта - 10 мкс, период - 20 мс */
	 TIM_TimeBaseInitTypeDef base_timer;
	 TIM_TimeBaseStructInit(&base_timer);
	 base_timer.TIM_Prescaler = SystemCoreClock / 1000 - 1;
	 base_timer.TIM_Period = 2000;
	 base_timer.TIM_ClockDivision = 0;
	 base_timer.TIM_CounterMode = TIM_CounterMode_Up;
	 TIM_TimeBaseInit(TIM3, &base_timer);

	 tim3ConfigRising();

	 // TIM enable counter
  	 TIM_Cmd(TIM3, ENABLE);

	 // Enable the CC2 Interrupt Request
	 TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);

	 NVIC_InitTypeDef NVIC_InitStructure;

	 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 NVIC_Init(&NVIC_InitStructure);
}

void initGpio()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

	GPIO_InitTypeDef gpioStruct;
	gpioStruct.GPIO_Mode = GPIO_Mode_IN;
	gpioStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	gpioStruct.GPIO_Speed = GPIO_Speed_50MHz;
	gpioStruct.GPIO_Pin = GPIO_Pin_7;

	GPIO_Init(GPIOA, &gpioStruct);
}

int main(void)
{

	LiquidCrystal lcd(RCC_AHB1Periph_GPIOC, GPIOC, GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2,
			RCC_AHB1Periph_GPIOC, GPIOC, GPIO_Pin_5, GPIO_Pin_4);

	initGpio();
	initTimers();

	char buffer[20];
	char *bufPtr;
	bufPtr = (char*)buffer;
	while(1)
	{

		if (dataCaptureReady)
		{
			/* Capture computation */
				if (IC3ReadValue2 > IC3ReadValue1)
				{
				Capture = (IC3ReadValue2 - IC3ReadValue1);
				}
				else
				{
				Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);
				}
				/* Frequency computation */
				int TIM3Freq = (uint32_t) SystemCoreClock / Capture;

			dataCaptureReady = 0;
			sprintf(bufPtr, "%d %d", Capture, TIM3Freq);
			lcd.setCursor(0,0);
			lcd.print(bufPtr);
		}

	}

}

extern "C" {
	void TIM3_IRQHandler()
	{

		if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)
		{
			/* Clear TIM3 Capture compare interrupt pending bit */
			TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
			if(CaptureNumber == 0)
			{
				/* Get the Input Capture value */
				IC3ReadValue1 = TIM_GetCapture2(TIM3);
				CaptureNumber = 1;

				tim3ConfigFalling();

			}
			else if(CaptureNumber == 1)
			{
				/* Get the Input Capture value */
				IC3ReadValue2 = TIM_GetCapture2(TIM3);

				dataCaptureReady = 1;
				CaptureNumber = 0;

				tim3ConfigRising();

			}
		}
	}
}


Но, не выходит каменный цветок.
Обработчик прерывания не вызывается, в регистре TIM3->CCR2 пусто, при том что в GPIOA->IDR все как и ожидается.

Есть предположение, что пин PA07 не «связан» с таймером и от этого не вызывается прерывание, вот только путь решения пока не найден
  • Вопрос задан
  • 10676 просмотров
Решения вопроса 1
Да, верно. Пин PA07 не связан с таймером, потому что это его альтернативная функция, которую необходимо включить.
gpioStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы