输入捕获实验是电容按键检测实验的前提所以需要先学习用TIM实现输入捕获
1、系列目录
2 、输入捕获原理
定时器都有四个通道,我们需要将使用其中一个通道与开发板的按键相同,例如正点原子F1精英板的KEY_UP按键和TIM5_CH1为共用IO(PA0),所以我们只需要开启TIM5的捕获功能即可计时按键的高低电平变化。
所以要使用到
TIM_TimeBaseInitTypeDef和TIM_ICInitTypeDef这两个结构体,Base结构体已经在上一节解释,现在来分析IC这个结构体
3、IC结构体分析
TIM_ICInitTypeDef看名字就知道和输入有关,因为IC的I = in 输入
TIM_OCInitTypeDef当然也有OC O=out 输出,将会在PWM实验中使用到
typedef struct
{
uint16_t TIM_Channel; /*!< Specifies the TIM channel.
This parameter can be a value of @ref TIM_Channel */
uint16_t TIM_ICPolarity; /*!< Specifies the active edge of the input signal.
This parameter can be a value of @ref TIM_Input_Capture_Polarity */
uint16_t TIM_ICSelection; /*!< Specifies the input.
This parameter can be a value of @ref TIM_Input_Capture_Selection */
uint16_t TIM_ICPrescaler; /*!< Specifies the Input Capture Prescaler.
This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
uint16_t TIM_ICFilter; /*!< Specifies the input capture filter.
This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;
TIM_Channel:选择使用通道几进行捕获
TIM_ICPolarity:选择高电平、低电平、高低电平触发输入捕获
TIM_ICSelection:配置CCMR1寄存器的CC1S位
(00输出,01输入IC1映射在TI1上,10输入IC1映射在TI2上,11输入IC1映射在TRC上)
TIM_ICPrescaler:输入信号分频值
TIM_ICFilter:滤波器,多少次捕获触发一次中断
4 、捕获时间计算
捕获时间t :
t = num * T
总计数次数num:
num = (TIM5CH1_CAPTURE_STA & 0x3F)* arr + TIM5CH1_CAPTURE_VAL
时钟周期T:
在 基本计时实验中的第四部分已经分析过。
5、重点代码分析
如果分析不明白可以查看我对自定义寄存器这种办法的详细讲解 用户自定义寄存器详解
6、代码示例
/*
*TIM5配置
*/
void TIM5_Config(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//PA0 配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//下拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//提前强制拉低
//TIM5基础配置
//计时器时钟 = APB总线时钟/分频因子
// psc
TIM_TimeBaseStructure.TIM_Period = arr;//重装载值/最大计数值
TIM_TimeBaseStructure.TIM_Prescaler = psc;//预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
//TIM5输入捕获配置
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//选择TIM5的CH1通道
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//将IC1映射到IT1
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//信号分频值,不分频
TIM_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
TIM_ICInit(TIM5,&TIM_ICInitStructure);
//中断优先级配置 优先级:2 0
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM5,TIM_IT_Update | TIM_IT_CC1 ,ENABLE);// TIM5计数更新中断、CCR1捕获中断使能
TIM_Cmd(TIM5,ENABLE); //使能TIM5
}
/*
*TIM5输入捕获 中断服务函数
*/
u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态
u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
int a=0;
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA & 0x80) == 0)//未捕获成功
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update) != RESET) //再次检测是否有中断
{
if(TIM5CH1_CAPTURE_STA & 0x40)//已经捕获到高电平
{
if((TIM5CH1_CAPTURE_STA & 0x3F) == 0x3F )//到达计时最大值,不能再进行计数;所有数据附上最大值
{
TIM5CH1_CAPTURE_STA |= 0x80;//将捕获状态位(bit8)设为1,标记成功捕获
TIM5CH1_CAPTURE_VAL = 0xFFFF;
}
else
{
TIM5CH1_CAPTURE_STA++;
}
}
}
if(TIM_GetITStatus(TIM5,TIM_IT_CC1) != RESET)
{
if(TIM5CH1_CAPTURE_STA & 0x40)//从第一个高电平开始,捕获到第一个下降沿
{
TIM5CH1_CAPTURE_STA |= 0x80;//置位bit8,标记为一次捕获结束
TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //????????????????????????
}
else//第一个高电平刚到
{
TIM5CH1_CAPTURE_STA = 0;
TIM5CH1_CAPTURE_VAL = 0;
TIM_SetCounter(TIM5,0); //全部清空
TIM5CH1_CAPTURE_STA |= 0x40;//标记捕获到上升沿
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);//????????????????????????
}
}
}
TIM_ClearITPendingBit(TIM5,TIM_IT_Update | TIM_IT_CC1);//同时清空两个中断标志
}
/*
*main.c
*/
主函数中需要配置arr和psc,再根据TIM5CH1_CAPTURE_STA和TIM5CH1_CAPTURE_VAL的值计算出定时时间即可