//example_gptimer_capture.c
include "example.h"
static uint32_t capture_VAL[20];
static uint8_t capture_idx = 0;
static uint8_t capture_en = 0;
volatile uint16_t testUpdateCnt = 0;
int global_autoload; //timer中autoload的值
// 计算两次获取到的时间差,用以计算一个输入周期的长度
int getLastTimeInterval(uint32_t curCount)
{
static uint32_t s_lastTimeCount = 0;
uint32_t ret;
if (curCount >= s_lastTimeCount) {
ret = curCount - s_lastTimeCount;
} else {
ret = global_autoload - s_lastTimeCount + curCount;
}
s_lastTimeCount = curCount;
return ret;
}
void GPTIMER2_isr(void)
{
//输入波形触发的中断
if (GPTIMER_IsActiveFlagCC1(GPTIMER2) == true)
{
uint32_t value = GPTIMER_IC_GetCapture(GPTIMER2, GPTIMER_CHANNEL_CH1);
capture_VAL[capture_idx++] = getLastTimeInterval(value); //计算和上次之间的差值
//采集20次就停掉,在后边来分析
if(capture_idx >= 20)
{
GPTIMER_DisableIntCC1(GPTIMER2);
GPTIMER_DisableIntUpdate(GPTIMER2);
capture_en = 1;
capture_idx = 0;
}
GPTIMER_ClearFlagCC1(GPTIMER2);
}
else if (GPTIMER_IsActiveFlagUpdate(GPTIMER2) == true)
{
//如果连续进到这里,则是输入脉冲停掉了
//to do...
testUpdateCnt++;
GPTIMER_ClearFlagUpdate(GPTIMER2);
}
}
//计算捕获的频率
int get_captureFrequency(void)
{
uint32_t average, sum = 0;
if (capture_en == 1)
{
//取中间的10个,计算平均值
for (int i = 5; i < 15; i++)
{
sum += capture_VAL[i];
}
average = sum / 10;
printf("Testing capture average = %d\r\n", average);
//输入pwm的频率,为 timer的主频 / clk计数
uint32_t timerFreq, inFreq;
timerFreq = SYS_GetPclkFreq() / 1;
inFreq = timerFreq / average;
//重新开启新的采集
capture_en = 0;
GPTIMER_EnableIntCC1(GPTIMER2);
GPTIMER_EnableIntUpdate(GPTIMER2);
return inFreq;
}
return 0;
}
//例程:
// 启动一个timer输入捕获capture来捕获上升沿,然后用另一个timer开启一个pwm输出。
// 然后将这两个pin脚短接,用以测试这里的捕获。
//VE里需要配套设置:
// GPTIMER4_CH0 PIN_85
// GPTIMER2_CH1 PIN_87:INPUT
//
extern void TestGpTimerPwm();
void TestGpTimerCapture()
{
SYS_EnableAPBClock(APB_MASK_GPTIMER2);
GPTIMER_InitTypeDef tm_init;
GPTIMER_StructInit(&tm_init);
tm_init.Autoreload = SYS_GetPclkFreq(); //这里配置的数值,要大于输入波形的周期。在不分频情况下,这里设置成sysClk,就是1秒来一次update中断
tm_init.Prescaler = 0; //10 - 1; //如果设置10分频,是设置捕获timer的时钟为sysclk的1/10
GPTIMER_Init(GPTIMER2, &tm_init);
global_autoload = tm_init.Autoreload; //用于时间计算里的计数溢出
GPTIMER_IC_InitTypeDef ic_init;
ic_init.ICPolarity = GPTIMER_IC_POLARITY_FALLING; //输入通道触发方式:上升沿、下降沿、双边
ic_init.ICMode = GPTIMER_ICMODE_DIRECTTI; //映射到T1上
ic_init.ICPrescaler = GPTIMER_ICPSC_DIV1; //配置输入分配。DIV1为不分频。
ic_init.ICFilter = GPTIMER_IC_FILTER_FDIV1; //设置输入滤波器,防抖动。FDIV1为不滤波
GPTIMER_IC_Init(GPTIMER2, GPTIMER_CHANNEL_CH1, &ic_init);
GPIO_AF_ENABLE(GPTIMER2_CH1); //输入IO
INT_EnableIRQ(GPTIMER2_IRQn, TIMER_PRIORITY); //打开中断
GPTIMER_EnableIntUpdate(GPTIMER2); //使能更新中断。如果中断中来的是更新中断(而不是捕获中断),说明脉冲太宽了。
GPTIMER_EnableIntCC1(GPTIMER2); //使能捕获中断
GPTIMER_EnableCounter(GPTIMER2);
//test
TestGpTimerPwm(); //开启另一个引脚的pwm输出。将两引脚短接,pwm的输出作为这里的输入。
int ret = 0;
while (1)
{
UTIL_IdleUs(1000e3);
ret = get_captureFrequency();
printf("calc freq = %d, testUpdateCnt = %d\r\n", ret, testUpdateCnt);
}
}