输入捕获原理及配置步骤
一、输入捕获概念
STM32的输入捕获,简单的说就是通过检测 TIMx_CHx (定时器X的通道X)上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT) 存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。
二、输入捕获流程:
输出比较模式的配置步骤:
1. 选择计数器时钟(内部,外部,预分频器)。
2. 将相应的数据写入TIMx_ARR和TIMx_CCRx寄存器中。
3. 如果要产生一个中断请求,设置CCxIE位。
4. 选择输出模式,例如:
─ 要求计数器与CCRx匹配时翻转OCx的输出引脚,设置OCxM=011
─ 置OCxPE = 0禁用预装载寄存器
─ 置CCxP = 0选择极性为高电平有效
─ 置CCxE = 1使能输出 5
. 设置TIMx_CR1寄存器的CEN位启动计数器
三、输入捕获程序设计步骤:
设置 TIM3 时钟和的 GPIOC 端口霍尔捕获(连接引脚 06、07、08):
1)开启 TIM3 时钟和 GPIOC 时钟,重映射PC 6、7、8
要使用 TIM3,我们必须先开启 TIM3 的时钟以及输入的GPIO引脚。这里我们还要配置 PC6、7、8 为浮空输入
GPIO_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7| GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
2)初始化 TIM3,设置 TIM3 的 ARR 和 PSC
在开启了 TIM3 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来设置输入捕获的自动重装载值和计数频率。
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_DeInit(HALL_TIMER);
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 向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化 Tim3
}
3)设置 TIM3 的输入比较参数,开启输入捕获
输入比较参数的设置包括映射关系,滤波,分频以及捕获方式等。这里我们需要设置通道 1 为输入模式,且 IC1 映射到 TI1(通道 1)上面,并且使用滤波(提高响应速度)器,上升沿捕获。
参数设置结构体 TIM_ICInitTypeDef 的定义:
typedef struct
{
uint16_t TIM_Channel; //用来设置通道
uint16_t TIM_ICPolarity; //用来设置输入信号的有效捕获极性
uint16_t TIM_ICSelection; //映射
uint16_t TIM_ICPrescaler; //配置输入分频
uint16_t TIM_ICFilter; //滤波
} TIM_ICInitTypeDef;
缺省值配置( TIM_ICStructInit(&TIM_ICInitStructure); ):
配置程序:
TIM_ICInit
{
TIM_ICInitTypeDef TIM3_ICInitStructure;
TIM3_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1 映射到TI1 上
TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //上升沿捕获
TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1 上
TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
TIM3_ICInitStructure.TIM_ICFilter = 0x0B; //IC1F=1011 配置输入滤波器
TIM_ICInit(TIM3, &TIM3_ICInitStructure);
}
4)使能捕获和更新中断(设置 TIM3 的 DIER 寄存器)
//TIM3 预分频重载模式,预分频值立即填装(PSC)
TIM_PrescalerConfig(TIM3, PSC, TIM_PSCReloadMode_Immediate);
TIM_InternalClockConfig(TIM3); //设置TIM3内部时钟
TIM_SelectHallSensor(TIM3, ENABLE); //使能霍尔传感器接口
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //经滤波定时器输入1
//选中触发信号(TRGI)的上升沿重初始化计数器并触发寄存器的更新
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
//生成单一的脉冲:计数器在下一个更新事件停止
TIM_UpdateRequestConfig(TIM3, TIM_UpdateSource_Regular);
5)设置中断分组,编写中断服务函数
中断矢量配置
NVIC_InitTypeDef NVIC_InitHALLStructure;
NVIC_InitHALLStructure.NVIC_IRQChannel = TIM3_IRQChannel;
NVIC_InitHALLStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY; //先占优先级
NVIC_InitHALLStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;//从优先级
NVIC_InitHALLStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitHALLStructure);
TIM_ClearFlag(HALL_TIMER, TIM_FLAG_Update + TIM_FLAG_CC1 + TIM_FLAG_CC2 + \
TIM_FLAG_CC3 + TIM_FLAG_CC4 + TIM_FLAG_Trigger + TIM_FLAG_CC1OF + \
TIM_FLAG_CC2OF + TIM_FLAG_CC3OF + TIM_FLAG_CC4OF); //清除标志位
TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);//开中断
TIM_SetCounter(HALL_TIMER, HALL_COUNTER_RESET); //计数器重置
接着是 TIM3_IRQChannel 中断通道对应的中断服务子程序的编写:
void TIM3_IRQHandler(void)
{
……………………………………
……………………………………
}
6)使能定时器
TIM_Cmd(TIM3,ENABLE);