/**
******************************************************************************
* @file CaptureAngle.c
* @author
* @version V3.5.0
* @date 20-2-2019
* @brief This file provides all the TIM firmware functions.
******************************************************************************
* @attention pwm capture the pulse width
*
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
#include "CaptureAngle.h"
//1、中断设置 优先级和使能
static void General_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
//2 、GPIO配置 PB6配置为下拉输入模式。
static void General_GPIO_Gonfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
// 3. 定时器4模式配置,其中包含时基结构体、输入捕获结构体的初始化以及中断的开启。
static void GeneralTim_Config(void)
{
// 开启定时器时钟,即内部时钟CK_INT=72M
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=7200-1;//每计数10k,结束一个
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= 7200-1;//10k
// 时钟分频因子,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/*--------------------输入捕获结构体初始化-------------------*/
TIM_ICInitTypeDef TIM_ICInitStructure;
// 配置输入捕获的通道,需要根据具体的GPIO来配置
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
// 输入捕获信号的极性配置
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
// 输入通道和捕获通道的映射关系,有直连和非直连两种
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
// 输入的需要被捕获的信号的分频系数
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
// 输入的需要被捕获的信号的滤波系数
TIM_ICInitStructure.TIM_ICFilter = 0;
// 定时器输入捕获初始化
TIM_ICInit(TIM4, &TIM_ICInitStructure);
// 清除更新和捕获中断标志位
TIM_ClearFlag(TIM4, TIM_FLAG_Update|TIM_IT_CC1);
// 开启更新和捕获中断
TIM_ITConfig (TIM4, TIM_IT_Update | TIM_IT_CC1, ENABLE );
// 使能计数器
TIM_Cmd(TIM4, ENABLE);
}
//4. 输入捕获初始化函数
void GeneralTim_Init(void)
{
General_NVIC_Config();
General_GPIO_Gonfig();
GeneralTim_Config();
}
//5. 中断函数
// 首先判断定时器是否溢出定时周期,并做处理。
//然后上升沿捕获时将计数器寄存器的值清零,中断改为下降沿触发。
//下降沿捕获中断时,读取计数值,改为上升沿触发,开始捕获标识清零,结束捕获置1,。。。。。。。。
TIM_ICUserValueTypeDef TIM_ICUserValueStructure;
void TIM4_IRQHandler(void)
{
// 当要被捕获的信号的周期大于定时器的最长定时时,定时器就会溢出,产生更新中断
// 这个时候我们需要把这个最长的定时周期加到捕获信号的时间里面去
if ( TIM_GetITStatus (TIM4, TIM_IT_Update) != RESET ) //判断是否为更新中断
{
TIM_ICUserValueStructure.Capture_Period ++;
TIM_ClearITPendingBit (TIM4, TIM_FLAG_Update );
}
// 上升沿捕获中断
if ( TIM_GetITStatus (TIM4, TIM_IT_CC1)!= RESET)//判断是否发生捕获事件
{
// 第一次捕获
if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 )
{
// 计数器清0
TIM_SetCounter ( TIM4, 0 );
// 自动重装载寄存器更新标志清0
TIM_ICUserValueStructure.Capture_Period = 0;
// 存捕获比较寄存器的值的变量的值清0
TIM_ICUserValueStructure.Capture_CcrValue = 0;
// 当第一次捕获到上升沿之后,就把捕获边沿配置为下降沿
TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Falling);
// 开始捕获标准置1
TIM_ICUserValueStructure.Capture_StartFlag = 1;
}
// 下降沿捕获中断
else // 第二次捕获
{
// 获取捕获比较寄存器的值,这个值就是捕获到的高电平的时间的值
TIM_ICUserValueStructure.Capture_CcrValue =TIM_GetCapture1(TIM4);
// 当第二次捕获到下降沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获
TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Rising);
// 开始捕获标志清0
TIM_ICUserValueStructure.Capture_StartFlag = 0;
// 捕获完成标志置1
TIM_ICUserValueStructure.Capture_FinishFlag = 1;
}
TIM_ClearITPendingBit (TIM4,TIM_IT_CC1|TIM_IT_Update);
}
}
以上代码是从另外一个博客拿来的,亲测可用。
原文网址:
https://blog.csdn.net/weixin_42108004/article/details/81951894
另外一个讲解的很清楚:
https://blog.csdn.net/gtkknd/article/details/52195498
pwm输入模式,使用两个通道,捕获更加精确。