Здравствуйте,
подскажите, пожалуйста, что я делаю не так.
Задача — чтение ширины импульса.
Погуглив, решил использовать 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 не «связан» с таймером и от этого не вызывается прерывание, вот только путь решения пока не найден