Hello all,
I'm revisiting this post just to make an update. I have managed to get a working input capture using a pair of timer channels as required capturing pwm input
instead of just a regular input capture. It's much simpler but limited to channel pairs. I use this to capture pwm from an RC receiver. I'm posting it here so googlers may find it.
I'm revisiting this post just to make an update. I have managed to get a working input capture using a pair of timer channels as required capturing pwm input
instead of just a regular input capture. It's much simpler but limited to channel pairs. I use this to capture pwm from an RC receiver. I'm posting it here so googlers may find it.
Code Select
#ifndef PWMINPUTCAPTURE_H_
#define PWMINPUTCAPTURE_H_
#include "config/stm32plus.h"
#include "config/timer.h"
#include "config/timing.h"
using namespace stm32plus;
/**
* PWM input capture mode on Timers 4 & 3.
*
* PWM input capture uses Timer channel pairs 1 & 2 to capture the signal
* on a single input . Duty cycle is captured on channel 1 and pulse width
* is captured on channel 2.
*
* Timer4 Channel1 is on PB6
* Timer3 Channel1 in on PA6
*
*/
class PWMInputCapture {
protected:
/**
* Declare a type for our input timer.
*/
typedef TimerChannel1Feature< // we're going to use channel 1
TimerChannelICRisingEdgeFeature, // we'll capture rising edge
TimerChannelICDirectTiFeature, // direct connection
TimerChannelICPreScaler1Feature, // prescaler of 1
TimerChannelICFilterFeature<0> // no filter
> ch1Features;
typedef TimerChannel2Feature< // we're going to use channel 2
TimerChanneICFallingEdgeFeature, // we'll capture falling edge
TimerChannelICDirectTiFeature, // direct connection
TimerChannelICPreScaler1Feature, // prescaler of 1
TimerChannelICFilterFeature<0> // no filter
> ch2Features;
typedef Timer4<
Timer4InternalClockFeature, // we'll need this for the frequency calculation
ch1Features,
ch2Features,
Timer4InterruptFeature, // we want to use interrupts
Timer4GpioFeature< // we want to read something from GPIO
TIMER_REMAP_NONE, // the GPIO input will not be remapped
TIM4_CH1_IN // we will read channel 1 from GPIO PB6
>,
TimerSlaveFeature<
TIM_TS_TI1FP1,
TIM_SlaveMode_Reset
>,
TimerResetMasterFeature
> TimerInput1;
typedef Timer3<
Timer3InternalClockFeature, // we'll need this for the frequency calculation
ch1Features,
ch2Features,
Timer3InterruptFeature, // we want to use interrupts
Timer3GpioFeature< // we want to read something from GPIO
TIMER_REMAP_NONE, // the GPIO input will not be remapped
TIM3_CH1_IN // we will read channel 1 from GPIO PA6
>,
TimerSlaveFeature<
TIM_TS_TI1FP1,
TIM_SlaveMode_Reset
>,
TimerResetMasterFeature
> TimerInput2;
/*
* The timer needs to be a class member so we can see it from the callback
*/
TimerInput1 *_TimerInput1;
TimerInput2 *_TimerInput2;
public:
/* These does not have to be an array if only interested in one of the captured value */
volatile uint16_t _steerCapture[2];
volatile uint16_t _throttleCapture[2];
void initialize() {
/*
* Declare a new instance of the input capture timer.
*/
_TimerInput1=new TimerInput1;
_TimerInput2=new TimerInput2;
/* Timer4 runs at 36Mhz on APB1
* This sets up a free running timer that ticks at 1MHz
*/
_TimerInput1->setTimeBaseByFrequency(1000000, 0xFFFF, TIM_CounterMode_Up);
_TimerInput2->setTimeBaseByFrequency(1000000, 0xFFFF, TIM_CounterMode_Up);
/*
* Insert our subscribtion of the capture interrupts generated by the input timer
*/
_TimerInput1->TimerInterruptEventSender.insertSubscriber(
TimerInterruptEventSourceSlot::bind(this,&PWMInputCapture::onSteerInterrupt)
);
_TimerInput2->TimerInterruptEventSender.insertSubscriber(
TimerInterruptEventSourceSlot::bind(this,&PWMInputCapture::onThrottleInterrupt)
);
/* Select the TIM4 Input Trigger: TI1FP1 */
// TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
_TimerInput1->enableSlaveFeature();
/* Select the slave Mode: Reset Mode */
// TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
// TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
_TimerInput1->enableMasterFeature();
/* Select the TIM3 Input Trigger: TI1FP1 */
// TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
_TimerInput2->enableSlaveFeature();
/* Select the slave Mode: Reset Mode */
// TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
// TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
_TimerInput1->enableMasterFeature();
/*
* Enable channel 1 interrupts on Timer inputs.
*/
_TimerInput1->enableInterrupts(TIM_IT_CC1);
_TimerInput2->enableInterrupts(TIM_IT_CC1);
/*
* Enable timers to start the action
*/
_TimerInput1->enablePeripheral();
_TimerInput2->enablePeripheral();
} // Iniatilize
/*
* Interrupt callback function. This is called when the input capture
* event is fired
*/
void onSteerInterrupt(TimerEventType tet, uint8_t /* timerNumber */) {
if (tet == TimerEventType::EVENT_COMPARE1) {
// store the current capture time
// _steerCapture[0] = TIM_GetCapture1(TIM4); // Period
// _steerCapture[1] = TIM_GetCapture2(TIM4); // Duty/Width
// _steerCapture[0] = _TimerInput1->ch1Features::getCapture();
_steerCapture[1] = _TimerInput1->ch2Features::getCapture();
}
} // onInterrupt
/*
* Interrupt callback function. This is called when the input capture
* event is fired
*/
void onThrottleInterrupt(TimerEventType tet, uint8_t /* timerNumber */) {
if (tet == TimerEventType::EVENT_COMPARE1) {
// store the current capture time
// _throttleCapture[0] = TIM_GetCapture1(TIM3); // Period
// _throttleCapture[1] = TIM_GetCapture2(TIM3); // Duty/Width
// _throttleCapture[0] = _TimerInput2->ch1Features::getCapture();
_throttleCapture[1] = _TimerInput2->ch2Features::getCapture();
}
} // onInterrupt
}; //
#endif /* PWMInputCapture_H_ */