//通用定时器输入捕获部分
//输入捕获的用途:
捕获按键时长、超声波测距模块、红外接收
//输入捕获的作用:
监测外部输入信号的脉冲宽度
//监测高电平信号:
测量测量上升沿发生的CNT值,加载到CCR寄存器中;再检测下降沿发生时CNT的值,加载到CCR寄存器中;
两个值相减,就能获得高电平触发的时间;
1Mhz ----- 数一个数1us
//通用定时器输入捕获部分框图及原理:
1.外部信号先进行滤波处理
2.信号进入边沿检测器
3.TI1FP1信号进入预分频器(不建议分频,最好默认一)
4.当通道检测到上升沿或者下降沿时,产生捕获捕获事件(标志位置一)
//在计算按按键按下所产生的高电平的时间时,必须考虑周期溢出的情况(因为人按下按键到松手的时间一般在100ms左右)
//定时器周期限制,一般来说ARR为16位,最多只能数65536个数,频率若为1Mhz,那么一个周期为65.536ms
//怎么知道周期溢出?
1.可以用轮询的方式(占用CPU)
2.采用更新中断(一般采用这种方式好)
//总结:
我们在配置好通用定时器的输入捕获的功能的同时,还需要打开捕获中断与更新中断
//输入捕获滤波器的原理:
与打点计数器类似:
打点频率越慢,打点个数越多,滤波的效果越好//总的来说我们要让频率慢,打点的个数尽量多
可以根据外界过来信号的具体情况,来选择是否使用滤波功能
1.配置时钟分频:决定打点的周期 CR1寄存器
2.配置滤波器 --- CCMRx
//TIMx 捕获/比较模式寄存器 1 (TIMx_CCMR1)
输入捕获部分:
ICxPSC:输入捕获x 预分频器 (Input capture 1 prescaler)
此位域定义 CC1 输入 (IC1) 的预分频比。
只要 CC1E=0(TIMx_CCER 寄存器),预分频器便立即复位。
00:无预分频器,捕获输入上每检测到一个边沿便执行捕获
01:每发生 2 个事件便执行一次捕获
10:每发生 4 个事件便执行一次捕获
11:每发生 8 个事件便执行一次捕获
CCxS:捕获/比较 x 选择 (Capture/Compare 1 selection)
此位域定义通道方向(输入/输出)以及所使用的输入。
00:CC1 通道配置为输出
01:CC1 通道配置为输入,IC1 映射到 TI1 上
10:CC1 通道配置为输入,IC1 映射到 TI2 上
11:CC1 通道配置为输入,IC1 映射到 TRC 上。此模式仅在通过 TS 位(TIMx_SMCR 寄存 器)选择内部触发输入时有效
//TIMx 捕获/比较使能寄存器 (TIMx_CCER)
CCxNP:捕获/比较 x 输出极性
CCx 通道配置为输入:
此位与 CCxP 配合使用,用以定义 TIxFP1/TIxFP1 的极性。请参见 CCxP 说明
CC1 通道配置为输入:
CCxNP/CCxP 位可针对触发或捕获操作选择 TIxFP1 和 TIxFP1 的极性。
00:上升沿触发捕获
01:下降沿触发 捕获
10:保留,不使用此配置
11:上升沿和下降沿均触发捕获
//总结:CCxNP与CCxP,只有CCxP决定捕获边沿,所以可以将CCxNP保持为零
CCxE:捕获/比较 x 输出使能
CCx 通道配置为输入:
此位决定了是否可以实际将计数器值捕获到输入捕获/比较寄存器 1 (TIMx_CCRx) 中。
0:禁止捕获
1:使能捕获
//捕获按键按下所产生高电平时间长短的思路与例程:
/*
函数功能:TIM5输入捕获通道1初始化
返回值:void
形参:void
函数说明:
*/
void TIM_CaptureInit(void)
{
u16 pri;
//①打开时钟GPIOA、TIM5
RCC->AHB1ENR |= 1 << 0;
RCC->APB1ENR |= 1 << 3;
//②PA0配置为复用模式
GPIOA->MODER &=~ (3 << 0);
GPIOA->MODER |= 2 << 0;
//③PA0与TIM2/TIM5复用关系
GPIOA->AFR[0] |= 2 << 0;
//④时基单元 PSC:84 ARR:65536
TIM5->PSC = 84 - 1;
TIM5->ARR = 65536 - 1;
TIM5->EGR |= 1 << 0;
TIM5->SR &=~ (1 << 0);
//⑤配置输入捕获通道
TIM5->CR1 |= 2 << 8; //配置滤波 CR1:时钟分频 CCMRx滤波器配置
TIM5->CCMR1 |= 0xf << 4;
TIM5->CCMR1 |= 1 << 0;//CCMRx
TIM5->CCER &=~ (1 << 3);
TIM5->CCER &=~ (1 << 1);
TIM5->CCER |= 1 << 0;//CCER --- 上升沿
//⑥使能CC1捕获/比较中断、更新中断
TIM5->DIER |= 1 << 1;
TIM5->DIER |= 1 << 0;
//⑦配置NVIC
pri = NVIC_EncodePriority (5,2,2);
NVIC_SetPriority(TIM5_IRQn,pri);
NVIC_EnableIRQ(TIM5_IRQn);
//⑧使能定时器
TIM5->CR1 |= 1 << 0;
}
u16 n;
u16 CNT1,CNT2;
u32 T;
/*TIM2中断服务函数*/
void TIM5_IRQHandler(void)
{
if(TIM5->SR & 1 << 0)//判断更新中断标志位置一
{
//清除更新标志位
TIM5->SR &=~ (1 << 0);
//n++;
n++;
}
if(TIM5->SR & 1 << 1)//判断输入捕获通道1标志位置一
{
//清除输入捕获通道1标志位
TIM5->SR &=~ (1 << 1);
if(GPIOA->IDR & 1 << 0)//IDR接收到高电平,捕获上升沿,捕获高电平时间开始
{
//溢出次数清零 n =0;
n = 0;
//使用一个静态/全局变量接收CCR寄存器的值(CNT1)
CNT1 = TIM5->CCR1;
//切换为下降沿捕获 CC1P置一
TIM5->CCER |= 1 << 1;
}
else if(!(GPIOA->IDR & 1 << 0))//IDR接收到低电平,捕获下降沿,高电平结束
{
//使用一个静态/全局变量接收CCR寄存器的值(CNT2)
CNT2 = TIM5->CCR1;
//套公式:T = 65536 * n -CNT1 + CNT2
T = 65536 * n - CNT1 + CNT2;
//使用串口打印看按键按下时间
printf("%d\r\n",T);
//切换为上升沿捕获 CC1P清零
TIM5->CCER &=~ (1 << 1);
}
}
}