Всем привет, прошу вашей помощи. Устроился на новую работу, и попался мне на переделку вот такой код :
CODE
class FreqIn
{
static std::vector<FreqIn*>tims;
static int timsNum;
public:
FreqIn(TIM_TypeDef *tim_, IRQn irqnUP_, IRQn irqnCC_, uint16_t chan_, uint32_t busDiv_)
: tim(tim_)
, irqnUP(irqnUP_)
, irqnCC(irqnCC_)
, chan(chan_)
, busDiv(busDiv_)
{
prescaler = 0;
tims.push_back(this);
timsNum ++;
reset();
}
void start()
{
stop();
enable = 1;
}
void stop()
{
enable = 0;
}
void reset()
{
timerInit();
stop();
}
inline float freq() {return freq_;}
inline uint16_t holdEdge() {return holdEdge_;}
inline void setEdge(uint16_t t)
{
timerInit();
holdEdge_ = t;
}
inline uint16_t holdPrescaler() {return prescaler;}
inline void setPrescaler(uint16_t t)
{
//timerInit();
prescaler = t;
}
private:
void timerInit()
{
NVIC_DisableIRQ(irqnUP);
NVIC_DisableIRQ(irqnCC);
TIM_Cmd(tim, DISABLE);
TIM_TimeBaseInitTypeDef timer_base;
TIM_TimeBaseStructInit(&timer_base);
timer_base.TIM_Prescaler = prescaler-1; //1,2,3
timer_base.TIM_Period = 0xFFFF;
TIM_TimeBaseInit(tim, &timer_base);
TIM_ICInitTypeDef TIM_ICStructure;
TIM_ICStructure.TIM_Channel = chan; // канал
if (holdEdge_)
{
TIM_ICStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; // по заднему фронту
}
else
{
TIM_ICStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
}
TIM_ICStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // прямо с ножки
TIM_ICStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // без делителя
TIM_ICStructure.TIM_ICFilter = 0; // без фильтра
// эта функция и включает режим PWM input - автоматически настраивает комплементарный канал
// правда в стандартной библиотеке работает на 1 и 2 канале, на 3 и 4 - не умеет
//TIM_PWMIConfig(tim, &TIM_ICStructure);
TIM_ICInit(tim, &TIM_ICStructure);
// Выбираем источник для триггера: вход 1
TIM_SelectInputTrigger(tim, TIM_TS_TI1FP1);
// По событию от триггера счётчик будет сбрасываться.
TIM_SelectSlaveMode(tim, TIM_SlaveMode_Reset);
// Включаем события от триггера
TIM_SelectMasterSlaveMode(tim, TIM_MasterSlaveMode_Enable);
// Разрешаем таймеру генерировать прерывание по захвату
if (chan == TIM_Channel_1) TIM_ITConfig(tim, TIM_IT_CC1, ENABLE);
if (chan == TIM_Channel_2) TIM_ITConfig(tim, TIM_IT_CC2, ENABLE);
if (chan == TIM_Channel_3) TIM_ITConfig(tim, TIM_IT_CC3, ENABLE);
if (chan == TIM_Channel_4) TIM_ITConfig(tim, TIM_IT_CC4, ENABLE);
TIM_ITConfig(tim, TIM_IT_Update, ENABLE);
TIM_ClearFlag(tim, TIM_FLAG_CC1);
TIM_ClearFlag(tim, TIM_FLAG_CC2);
TIM_ClearFlag(tim, TIM_FLAG_CC3);
TIM_ClearFlag(tim, TIM_FLAG_CC4);
TIM_ClearFlag(tim, TIM_IT_Update);
// Включаем таймер
TIM_Cmd(tim, ENABLE);
// разрешаем прерывания
NVIC_SetVector(irqnUP, (uint32_t)irqHandler);
NVIC_SetVector(irqnCC, (uint32_t)irqHandler);
NVIC_EnableIRQ(irqnUP);
NVIC_EnableIRQ(irqnCC);
}
static void irqHandler()
{
for (register int i = 0; i != timsNum; ++i)
{
tims[i]->irq();
}
}
inline void captCh(int ch)
{
}
inline void irq()
{
if (TIM_GetITStatus(tim, TIM_IT_CC1) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC1);
TIM_ClearITPendingBit(tim, TIM_IT_Update);
cnt = TIM_GetCapture1(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_CC2) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC2);
TIM_ClearITPendingBit(tim, TIM_IT_Update);
cnt = TIM_GetCapture2(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_CC3) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC3);
TIM_ClearITPendingBit(tim, TIM_IT_Update);
cnt = TIM_GetCapture3(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_CC4) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC4);
TIM_ClearITPendingBit(tim, TIM_IT_Update);
cnt = TIM_GetCapture4(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_Update);
ovf++;
}
}
uint32_t ovf;
uint32_t cnt;
uint32_t prescaler;
float freq_;
uint16_t holdEdge_;
uint16_t chan;
uint32_t busDiv;
volatile int enable;
TIM_TypeDef *tim;
IRQn irqnUP;
IRQn irqnCC;
};
это 4 таймера для считывания частоты.
на частотах до 2-3 герц работает отлично, на 32 килогерца показывает точно 320000, но стоит выстваить к примеру 32.101 как частота съезжает и показывается как 32.104 ~ 32.117, на схеме стоит внешний предделитель.
Подскажите я уже все перекопал, ничего не помогает...