实验目的
STM32的通用定时器和高级定时器拥有输入捕获功能,本章我们将利用TIM3的CH3通道产生PWM输出波形连接到TIM5的CH2输入捕捉通道,测量PWM输出波形频率。数据手册请参看第14章中的相关内容
实验简介
输入捕获模式可以用来测量脉冲宽度和频率。所谓的捕获,就是检测定时器的TIMx_CHx输入捕获引脚,检测到信号跳变时,将当前的定时器的计数值(TIMx_CNT)保存到捕获寄存器(TIMx_CCRx),完成一次捕获,当使能捕获中断时,会产生中断。
本实验是利用捕获功能来测量脉冲频率,脉冲由PWM模块产生,那我们是怎么样测量的呢?原理是这样的:连续捕获2次上升沿/下降沿信号跳变,分别记录下2次的定时器计数值,这2个计数值的差值就是脉冲宽度,且计数器的计数频率我们是知道的,这样我们就可以计算出周期和频率。
电路设计
本实验,是将上一章产生的PWM波形,通过跳帽连接到TIM5的CH2(PA1)进行捕捉,USB转串口打印频率信息
有关寄存器
因为使用的是TIM5_CH2通道
APB1 外设时钟使能寄存器(RCC_APB1ENR)
APB2 外设时钟使能寄存器(RCC_APB2ENR)
TIM1 和TIM8 捕获/比较模式寄存器 1(TIMx_CCMR1)
这里配置为10 IC2映射到TI1上
注意: 这里主要靠介绍,我们使用的是2 这里是1
TIM1 和TIM8 捕获/比较使能寄存器(TIMx_CCER)
**TIM1 和TIM8 DMA/中断使能寄存器(TIMx_DIER) **
寄存器代码
test.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "key.h"
extern u8 TIM5CH2_CAPTURE_STA;
//输入捕获状态
extern u8 TIM5CH2_CAPTURE_VAL;
//输入捕获值
int main(void)
{
u32 temp = 0;
Stm32_Clock_Init(9);
uart_init(72,115200);
delay_init(72);
LED_Init();
TIM3_PWM_Init(899,0);
//不分频 ,PWM频率为72000/(899+1)=80Khz
TIM5_Cap_Init(0xffff,72-1);
//以1Mhz的频率计数
while(1)
{
delay_ms(10);
LED3_PWM_VAL++;
if(LED3_PWM_VAL ==300)
LED3_PWM_VAL=0;
if(TIM5CH2_CAPTURE_STA & 0x80)
//成功捕获道了一次高电平
{
temp = TIM5CH2_CAPTURE_STA & 0x3f;
//一般情况下定时器不会溢出,前六位做溢出时间
temp *= 65536;
//1次 65536
temp += TIM5CH2_CAPTURE_VAL;
//得到高电平时间时间
printf("HIGH: %d usrn",temp);
//打印高电平
TIM5CH2_CAPTURE_STA = 0;
//开启下次捕获
}
}
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
#define LED3_PWM_VAL TIM3->CCR3
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
void TIM5_Cap_Init(u16 arr,u16 psc);
#endif
timer.c
#include "timer.h"
#include "led.h"
//捕捉前的前章有,不再赘述
void TIM3_IRQHandler(void)
{
if(TIM3->SR & 0x0001)
{
LED2 = !LED2;
}
TIM3->SR &= ~(1<<0);
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<1;
TIM3->ARR = arr;
TIM3->PSC = psc;
TIM3->DIER |= 1<<0;
TIM3->CR1 |= 0x01;
MY_NVIC_Init(1,3,TIM3_IRQn,2);×é 2
}
void TIM3_PWM_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<1;
RCC->APB2ENR |= 1<<3;
GPIOB->CRL &= 0xFFFFFFF0;
GPIOB->CRL |= 0x0000000B;
RCC->APB2ENR |= 1<<0;
AFIO->MAPR &= 0xFFFFF3FF;
AFIO->MAPR |= 1<<11;
TIM3->ARR = arr;
TIM3->PSC = psc;
TIM3->CCMR2 |= 7<<4;
TIM3->CCMR2 |= 1<<3;
TIM3->CCER |= 1<<8;
TIM3->CR1 = 0x0080;
TIM3->CR1 |= 0x01;
}
void TIM5_Cap_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<3;
//TIM5使能
RCC->APB2ENR |= 1<<2;
//GPIOA 也就是PORTA时钟使能
//因为使用的是PB1
GPIOA->CRL &= 0xFFFFFF0F;
GPIOA->CRL |= 0x00000080;
//PA1 引脚 下拉/上拉输入模式
GPIOA->ODR |= 0<<1;
//先让PA1为低电平,然后上升沿捕捉
TIM5->ARR = arr;
//设定计时器自动重装值
TIM5->PSC = psc;
//预分频器
TIM5->CCMR1 |= 1<<9;
//CC2S = 10
TIM5->CCMR1 |= 0<<12;
//IC2F = 0000 ,配置输入滤波器,不滤波
TIM5->CCMR1 |= 0<<10;
//配置输入分频,不分频
TIM5->CCER |= 0<<5;
//CC2P = 0 上升沿捕捉
TIM5->CCER |= 1<<4;
//允许捕捉计数器值到捕获寄存器中
TIM5->DIER |= 1<<2;
//允许2捕获中断
TIM5->DIER |= 1<<0;
//允许更新中断
TIM5->CR1 |=0x01;
//使能定时器
MY_NVIC_Init(2,0,TIM5_IRQn,2);
}
u8 TIM5CH2_CAPTURE_STA = 0;
//输入捕获状态
u16 TIM5CH2_CAPTURE_VAL ;
//输入捕获值
void TIM5_IRQHandler(void)
{
u16 tsr;
tsr = TIM5->SR;
//状态寄存器
if((TIM5CH2_CAPTURE_STA&0x80) == 0)
//还未捕捉成功
{
if(tsr&0x01)
//溢出
{
if(TIM5CH2_CAPTURE_STA&0x40)
//已经捕获到了高电平
{
if((TIM5CH2_CAPTURE_STA&0x3F) == 0x3F)
//高电平太长了
{
TIM5CH2_CAPTURE_STA |= 0x80;
//标志成功捕获了一次
TIM5CH2_CAPTURE_VAL = 0xFFFF;
}
else
TIM5CH2_CAPTURE_STA++;
}
}
if(tsr&0x04)
//捕获2发生捕获事件
{
if(TIM5CH2_CAPTURE_STA&0x40)
//捕获到一个下降沿
{
TIM5CH2_CAPTURE_STA|=0x80;
//标记成功捕获到一次高电平脉宽
TIM5CH2_CAPTURE_VAL = TIM5->CCR1;
//读取当前的捕获值
TIM5->CCER &= ~(1<<5);
}
else
{
TIM5CH2_CAPTURE_STA = 0;
//清空
TIM5CH2_CAPTURE_VAL = 0;
//
TIM5CH2_CAPTURE_STA |= 0x40;
//标记捕捉上升沿
TIM5->CNT = 0;
//计数器清零
TIM5->CCER |= 1<<5;
//CC1p = 1 设置为下降沿捕捉
}
}
}
TIM5->SR = 0;
//清除中断标志位
}
HAL库代码
main.c
#include "MyIncludes.h"
uint32_t uwIC2Value1 = 0;
//第一次捕捉值
uint32_t uwIC2Value2 = 0;
//第二次捕捉值
uint32_t uwDiffCapture = 0;
//两次捕捉差值
uint16_t uhCaptureIndex = 0;
//捕捉索引
uint32_t uwFrequency = 0;
//捕捉到的波形频率
uint8_t Cap_Over = 0;
void Cap_Process(void)
{
if(TimCapHandle.Channel == HAL_TIM_ACTIVE_CHANNEL_2)
//如果有源通道 为2
// TIM5 的 CH2 输入捕捉通道
{
if(uhCaptureIndex == 0)
//第一次捕捉
{
uwIC2Value1 = HAL_TIM_ReadCapturedValue(&TimCapHandle,TIM_CHANNEL_2);
//第一次捕捉值
uhCaptureIndex = 1;
}
else if(uhCaptureIndex == 1)
//第二次捕捉
{
uwIC2Value2 = HAL_TIM_ReadCapturedValue(&TimCapHandle,TIM_CHANNEL_2);
//第二次捕捉值
if(uwIC2Value2 > uwIC2Value1)
{
uwDiffCapture = (uwIC2Value2 - uwIC2Value1);
}
else if(uwIC2Value2 < uwIC2Value1)
{
uwDiffCapture = ((0xffff - uwIC2Value1) + uwIC2Value2) + 1;
//如果第二次小于第一次说明已经计满一次
}
uwFrequency = HAL_RCC_GetPCLK1Freq()/uwDiffCapture;
uhCaptureIndex = 0;
//捕捉到的波形频率=定时器PCK频率/2次捕捉的差值
Cap_Over = 1;
//捕捉完成
}
}
}
char buff[50];
int main(void)
{
u8 dir = 0;
u16 duty = 50;
u32 Set_Freq = 10000;
//设置频率
System_Init();
SysTick_Init(NULL);
USART1_Init(115200,NULL,NULL);
PWM_Init(Set_Freq,duty);
// 默认10kHz
//PWM初始化(频率,占空比)
Tim5_CapInit(FREQ_COUNTER,Cap_Process);
//Tim5输入捕捉初始化(计数器频率,函数)
while(1)
{
if(Cap_Over == 1)
//显示捕获结果
{
Cap_Over = 0;
sprintf(buff,"Cap Freq: %dHzzrn",uwFrequency);
printf(buff);
//打印信息
if(dir == 0)
//递增
{
if(Set_Freq < 20000)
Set_Freq+=100;
else dir = 1;
}
else if(dir == 1)
{
if(Set_Freq > 10000)
Set_Freq -= 100;
else dir = 0;
}
PWM_Init(Set_Freq,duty);
delay_ms(500);
}
}
}
InCap.h
#ifndef __INCAP_H_
#define __INCAP_H_
#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"
#define FREQ_COUNTER 1000000
//定义计数频率,要和初始化中一致
typedef struct
{
void (*T5_CapISR)(void);
//定时器5中断中运行的函数
}_TIMERCAP_ISR;
extern TIM_HandleTypeDef TimCapHandle;
void Tim5_CapInit(u32 Cnt_Freq,void(*ISR)(void));
//TImER5输入捕捉初始化
#endif
InCap.c
#include "InCap.h"
TIM_HandleTypeDef TimCapHandle;
//TIM基本句柄结构变量声明
TIM_IC_InitTypeDef sICConfig;
//TIM输入捕获配置结构变量声明
_TIMERCAP_ISR TIM5_CAP_ISR;
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
//HAL_TIM_IC_Init中调用
{
GPIO_InitTypeDef GPIO_InitStruct;
//GPIO基本配置结构
__HAL_RCC_TIM5_CLK_ENABLE();
//使能TIM5时钟
__GPIOA_CLK_ENABLE();
//TIM5_CH2管脚PA1
//使能GPIOA时钟
//配置输入捕捉管脚
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
//交替功能输入模式
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
//配置NVIC中断
HAL_NVIC_SetPriority(TIM5_IRQn,0,1);
//设置中断
HAL_NVIC_EnableIRQ(TIM5_IRQn);
//设置中断源
}
void Tim5_CapInit(u32 Cnt_Freq,void (*ISR)(void))
//TIMER5输入捕捉初始化
{
TIM5_CAP_ISR.T5_CapISR = ISR;
//回调函数
TimCapHandle.Instance = TIM5;
//设置定时器
TimCapHandle.Init.Period = 0xffffffff;
//自动重装值,这里设为最大
TimCapHandle.Init.Prescaler = 0;
//设置1us的计数频率
TimCapHandle.Init.ClockDivision = 0;
//时钟不分频,来自RCC
TimCapHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
// 递增计数
TimCapHandle.Init.RepetitionCounter = 0;
//指定重复计数器值。
HAL_TIM_IC_Init(&TimCapHandle);
//定时器输入捕获初始化
sICConfig.ICPolarity = TIM_ICPOLARITY_RISING;
//上升沿捕获
sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
//管脚为捕获输入,映射到TI2
sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
//输入捕获预分频,为 0 禁止预分频
sICConfig.ICFilter =0x00;
//输入捕获滤波器,这是一个递减计数器,这里不滤波
HAL_TIM_IC_ConfigChannel(&TimCapHandle,&sICConfig,TIM_CHANNEL_2);
//定时器捕获配置通道
HAL_TIM_IC_Start_IT(&TimCapHandle,TIM_CHANNEL_2);
//启动输入捕捉
}
void TIM5_IRQHandler(void)
//TIMER5中断服务函数
{
HAL_TIM_IRQHandler(&TimCapHandle);
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
//用户回调函数,在HAL_TIM_IRQHandler中调用
{
if(TIM5_CAP_ISR.T5_CapISR != NULL)
TIM5_CAP_ISR.T5_CapISR();
}
实验现象
注意:要将P8 跳帽连接。
实验目的
STM32的通用定时器和高级定时器拥有输入捕获功能,本章我们将利用TIM3的CH3通道产生PWM输出波形连接到TIM5的CH2输入捕捉通道,测量PWM输出波形频率。数据手册请参看第14章中的相关内容
实验简介
输入捕获模式可以用来测量脉冲宽度和频率。所谓的捕获,就是检测定时器的TIMx_CHx输入捕获引脚,检测到信号跳变时,将当前的定时器的计数值(TIMx_CNT)保存到捕获寄存器(TIMx_CCRx),完成一次捕获,当使能捕获中断时,会产生中断。
本实验是利用捕获功能来测量脉冲频率,脉冲由PWM模块产生,那我们是怎么样测量的呢?原理是这样的:连续捕获2次上升沿/下降沿信号跳变,分别记录下2次的定时器计数值,这2个计数值的差值就是脉冲宽度,且计数器的计数频率我们是知道的,这样我们就可以计算出周期和频率。
电路设计
本实验,是将上一章产生的PWM波形,通过跳帽连接到TIM5的CH2(PA1)进行捕捉,USB转串口打印频率信息
有关寄存器
因为使用的是TIM5_CH2通道
APB1 外设时钟使能寄存器(RCC_APB1ENR)
APB2 外设时钟使能寄存器(RCC_APB2ENR)
TIM1 和TIM8 捕获/比较模式寄存器 1(TIMx_CCMR1)
这里配置为10 IC2映射到TI1上
注意: 这里主要靠介绍,我们使用的是2 这里是1
TIM1 和TIM8 捕获/比较使能寄存器(TIMx_CCER)
**TIM1 和TIM8 DMA/中断使能寄存器(TIMx_DIER) **
寄存器代码
test.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "key.h"
extern u8 TIM5CH2_CAPTURE_STA;
//输入捕获状态
extern u8 TIM5CH2_CAPTURE_VAL;
//输入捕获值
int main(void)
{
u32 temp = 0;
Stm32_Clock_Init(9);
uart_init(72,115200);
delay_init(72);
LED_Init();
TIM3_PWM_Init(899,0);
//不分频 ,PWM频率为72000/(899+1)=80Khz
TIM5_Cap_Init(0xffff,72-1);
//以1Mhz的频率计数
while(1)
{
delay_ms(10);
LED3_PWM_VAL++;
if(LED3_PWM_VAL ==300)
LED3_PWM_VAL=0;
if(TIM5CH2_CAPTURE_STA & 0x80)
//成功捕获道了一次高电平
{
temp = TIM5CH2_CAPTURE_STA & 0x3f;
//一般情况下定时器不会溢出,前六位做溢出时间
temp *= 65536;
//1次 65536
temp += TIM5CH2_CAPTURE_VAL;
//得到高电平时间时间
printf("HIGH: %d usrn",temp);
//打印高电平
TIM5CH2_CAPTURE_STA = 0;
//开启下次捕获
}
}
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
#define LED3_PWM_VAL TIM3->CCR3
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
void TIM5_Cap_Init(u16 arr,u16 psc);
#endif
timer.c
#include "timer.h"
#include "led.h"
//捕捉前的前章有,不再赘述
void TIM3_IRQHandler(void)
{
if(TIM3->SR & 0x0001)
{
LED2 = !LED2;
}
TIM3->SR &= ~(1<<0);
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<1;
TIM3->ARR = arr;
TIM3->PSC = psc;
TIM3->DIER |= 1<<0;
TIM3->CR1 |= 0x01;
MY_NVIC_Init(1,3,TIM3_IRQn,2);×é 2
}
void TIM3_PWM_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<1;
RCC->APB2ENR |= 1<<3;
GPIOB->CRL &= 0xFFFFFFF0;
GPIOB->CRL |= 0x0000000B;
RCC->APB2ENR |= 1<<0;
AFIO->MAPR &= 0xFFFFF3FF;
AFIO->MAPR |= 1<<11;
TIM3->ARR = arr;
TIM3->PSC = psc;
TIM3->CCMR2 |= 7<<4;
TIM3->CCMR2 |= 1<<3;
TIM3->CCER |= 1<<8;
TIM3->CR1 = 0x0080;
TIM3->CR1 |= 0x01;
}
void TIM5_Cap_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<3;
//TIM5使能
RCC->APB2ENR |= 1<<2;
//GPIOA 也就是PORTA时钟使能
//因为使用的是PB1
GPIOA->CRL &= 0xFFFFFF0F;
GPIOA->CRL |= 0x00000080;
//PA1 引脚 下拉/上拉输入模式
GPIOA->ODR |= 0<<1;
//先让PA1为低电平,然后上升沿捕捉
TIM5->ARR = arr;
//设定计时器自动重装值
TIM5->PSC = psc;
//预分频器
TIM5->CCMR1 |= 1<<9;
//CC2S = 10
TIM5->CCMR1 |= 0<<12;
//IC2F = 0000 ,配置输入滤波器,不滤波
TIM5->CCMR1 |= 0<<10;
//配置输入分频,不分频
TIM5->CCER |= 0<<5;
//CC2P = 0 上升沿捕捉
TIM5->CCER |= 1<<4;
//允许捕捉计数器值到捕获寄存器中
TIM5->DIER |= 1<<2;
//允许2捕获中断
TIM5->DIER |= 1<<0;
//允许更新中断
TIM5->CR1 |=0x01;
//使能定时器
MY_NVIC_Init(2,0,TIM5_IRQn,2);
}
u8 TIM5CH2_CAPTURE_STA = 0;
//输入捕获状态
u16 TIM5CH2_CAPTURE_VAL ;
//输入捕获值
void TIM5_IRQHandler(void)
{
u16 tsr;
tsr = TIM5->SR;
//状态寄存器
if((TIM5CH2_CAPTURE_STA&0x80) == 0)
//还未捕捉成功
{
if(tsr&0x01)
//溢出
{
if(TIM5CH2_CAPTURE_STA&0x40)
//已经捕获到了高电平
{
if((TIM5CH2_CAPTURE_STA&0x3F) == 0x3F)
//高电平太长了
{
TIM5CH2_CAPTURE_STA |= 0x80;
//标志成功捕获了一次
TIM5CH2_CAPTURE_VAL = 0xFFFF;
}
else
TIM5CH2_CAPTURE_STA++;
}
}
if(tsr&0x04)
//捕获2发生捕获事件
{
if(TIM5CH2_CAPTURE_STA&0x40)
//捕获到一个下降沿
{
TIM5CH2_CAPTURE_STA|=0x80;
//标记成功捕获到一次高电平脉宽
TIM5CH2_CAPTURE_VAL = TIM5->CCR1;
//读取当前的捕获值
TIM5->CCER &= ~(1<<5);
}
else
{
TIM5CH2_CAPTURE_STA = 0;
//清空
TIM5CH2_CAPTURE_VAL = 0;
//
TIM5CH2_CAPTURE_STA |= 0x40;
//标记捕捉上升沿
TIM5->CNT = 0;
//计数器清零
TIM5->CCER |= 1<<5;
//CC1p = 1 设置为下降沿捕捉
}
}
}
TIM5->SR = 0;
//清除中断标志位
}
HAL库代码
main.c
#include "MyIncludes.h"
uint32_t uwIC2Value1 = 0;
//第一次捕捉值
uint32_t uwIC2Value2 = 0;
//第二次捕捉值
uint32_t uwDiffCapture = 0;
//两次捕捉差值
uint16_t uhCaptureIndex = 0;
//捕捉索引
uint32_t uwFrequency = 0;
//捕捉到的波形频率
uint8_t Cap_Over = 0;
void Cap_Process(void)
{
if(TimCapHandle.Channel == HAL_TIM_ACTIVE_CHANNEL_2)
//如果有源通道 为2
// TIM5 的 CH2 输入捕捉通道
{
if(uhCaptureIndex == 0)
//第一次捕捉
{
uwIC2Value1 = HAL_TIM_ReadCapturedValue(&TimCapHandle,TIM_CHANNEL_2);
//第一次捕捉值
uhCaptureIndex = 1;
}
else if(uhCaptureIndex == 1)
//第二次捕捉
{
uwIC2Value2 = HAL_TIM_ReadCapturedValue(&TimCapHandle,TIM_CHANNEL_2);
//第二次捕捉值
if(uwIC2Value2 > uwIC2Value1)
{
uwDiffCapture = (uwIC2Value2 - uwIC2Value1);
}
else if(uwIC2Value2 < uwIC2Value1)
{
uwDiffCapture = ((0xffff - uwIC2Value1) + uwIC2Value2) + 1;
//如果第二次小于第一次说明已经计满一次
}
uwFrequency = HAL_RCC_GetPCLK1Freq()/uwDiffCapture;
uhCaptureIndex = 0;
//捕捉到的波形频率=定时器PCK频率/2次捕捉的差值
Cap_Over = 1;
//捕捉完成
}
}
}
char buff[50];
int main(void)
{
u8 dir = 0;
u16 duty = 50;
u32 Set_Freq = 10000;
//设置频率
System_Init();
SysTick_Init(NULL);
USART1_Init(115200,NULL,NULL);
PWM_Init(Set_Freq,duty);
// 默认10kHz
//PWM初始化(频率,占空比)
Tim5_CapInit(FREQ_COUNTER,Cap_Process);
//Tim5输入捕捉初始化(计数器频率,函数)
while(1)
{
if(Cap_Over == 1)
//显示捕获结果
{
Cap_Over = 0;
sprintf(buff,"Cap Freq: %dHzzrn",uwFrequency);
printf(buff);
//打印信息
if(dir == 0)
//递增
{
if(Set_Freq < 20000)
Set_Freq+=100;
else dir = 1;
}
else if(dir == 1)
{
if(Set_Freq > 10000)
Set_Freq -= 100;
else dir = 0;
}
PWM_Init(Set_Freq,duty);
delay_ms(500);
}
}
}
InCap.h
#ifndef __INCAP_H_
#define __INCAP_H_
#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"
#define FREQ_COUNTER 1000000
//定义计数频率,要和初始化中一致
typedef struct
{
void (*T5_CapISR)(void);
//定时器5中断中运行的函数
}_TIMERCAP_ISR;
extern TIM_HandleTypeDef TimCapHandle;
void Tim5_CapInit(u32 Cnt_Freq,void(*ISR)(void));
//TImER5输入捕捉初始化
#endif
InCap.c
#include "InCap.h"
TIM_HandleTypeDef TimCapHandle;
//TIM基本句柄结构变量声明
TIM_IC_InitTypeDef sICConfig;
//TIM输入捕获配置结构变量声明
_TIMERCAP_ISR TIM5_CAP_ISR;
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
//HAL_TIM_IC_Init中调用
{
GPIO_InitTypeDef GPIO_InitStruct;
//GPIO基本配置结构
__HAL_RCC_TIM5_CLK_ENABLE();
//使能TIM5时钟
__GPIOA_CLK_ENABLE();
//TIM5_CH2管脚PA1
//使能GPIOA时钟
//配置输入捕捉管脚
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
//交替功能输入模式
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
//配置NVIC中断
HAL_NVIC_SetPriority(TIM5_IRQn,0,1);
//设置中断
HAL_NVIC_EnableIRQ(TIM5_IRQn);
//设置中断源
}
void Tim5_CapInit(u32 Cnt_Freq,void (*ISR)(void))
//TIMER5输入捕捉初始化
{
TIM5_CAP_ISR.T5_CapISR = ISR;
//回调函数
TimCapHandle.Instance = TIM5;
//设置定时器
TimCapHandle.Init.Period = 0xffffffff;
//自动重装值,这里设为最大
TimCapHandle.Init.Prescaler = 0;
//设置1us的计数频率
TimCapHandle.Init.ClockDivision = 0;
//时钟不分频,来自RCC
TimCapHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
// 递增计数
TimCapHandle.Init.RepetitionCounter = 0;
//指定重复计数器值。
HAL_TIM_IC_Init(&TimCapHandle);
//定时器输入捕获初始化
sICConfig.ICPolarity = TIM_ICPOLARITY_RISING;
//上升沿捕获
sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
//管脚为捕获输入,映射到TI2
sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
//输入捕获预分频,为 0 禁止预分频
sICConfig.ICFilter =0x00;
//输入捕获滤波器,这是一个递减计数器,这里不滤波
HAL_TIM_IC_ConfigChannel(&TimCapHandle,&sICConfig,TIM_CHANNEL_2);
//定时器捕获配置通道
HAL_TIM_IC_Start_IT(&TimCapHandle,TIM_CHANNEL_2);
//启动输入捕捉
}
void TIM5_IRQHandler(void)
//TIMER5中断服务函数
{
HAL_TIM_IRQHandler(&TimCapHandle);
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
//用户回调函数,在HAL_TIM_IRQHandler中调用
{
if(TIM5_CAP_ISR.T5_CapISR != NULL)
TIM5_CAP_ISR.T5_CapISR();
}
实验现象
注意:要将P8 跳帽连接。
举报