一、硬件设计
选用通用定时器TIM5的CH1,其输入管脚为PA0,在开发板上PA0连接按键,当按键按下输入高电平,按键松开输入低电平,实验测量高电平的脉冲宽度。
二、软件设计
1. 配置中断向量表的优先级
因只使用一个中断 TIM5_IRQn,抢占优先级与子优先级可随意配置。
代码如下:
static void General_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
2. GPIO配置
PA0配置为浮空输入模式。
static void General_GPIO_Gonfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK , ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;
GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
}
3. 定时器模式配置,其中包含时基结构体、输入捕获结构体的初始化以及中断的开启。
static void GeneralTim_Config(void)
{
// 开启定时器时钟,即内部时钟CK_INT=72M
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD;
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_PSC;
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
/*--------------------输入捕获结构体初始化-------------------*/
TIM_ICInitTypeDef TIM_ICInitStructure;
// 配置输入捕获的通道,需要根据具体的GPIO来配置
TIM_ICInitStructure.TIM_Channel = GENERAL_TIM_CHANNEL_x;
// 输入捕获信号的极性配置
TIM_ICInitStructure.TIM_ICPolarity = GENERAL_TIM_STRAT_ICPolarity;
// 输入通道和捕获通道的映射关系,有直连和非直连两种
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
// 输入的需要被捕获的信号的分频系数
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
// 输入的需要被捕获的信号的滤波系数
TIM_ICInitStructure.TIM_ICFilter = 0;
// 定时器输入捕获初始化
TIM_ICInit(GENERAL_TIM, &TIM_ICInitStructure);
// 清除更新和捕获中断标志位
TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update|GENERAL_TIM_IT_CCx);
// 开启更新和捕获中断
TIM_ITConfig (GENERAL_TIM, TIM_IT_Update | GENERAL_TIM_IT_CCx, ENABLE );
// 使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
4. 输入捕获初始化函数
void GeneralTim_Init(void)
{
General_NVIC_Config();
General_GPIO_Gonfig();
GeneralTim_Config();
}
5. 中断函数
首先判断定时器是否溢出定时周期,并做处理。然后上升沿捕获时将计数器寄存器的值清零,中断改为下降沿触发。下降沿捕获中断时,读取计数值,改为上升沿触发,开始捕获标识清零,结束捕获置1,。。。。。。。。
void GENERAL_TIM_INT_FUN(void)
{
// 当要被捕获的信号的周期大于定时器的最长定时时,定时器就会溢出,产生更新中断
// 这个时候我们需要把这个最长的定时周期加到捕获信号的时间里面去
if ( TIM_GetITStatus ( GENERAL_TIM, TIM_IT_Update) != RESET )
{
TIM_ICUserValueStructure.Capture_Period ++;
TIM_ClearITPendingBit ( GENERAL_TIM, TIM_FLAG_Update );
}
// 上升沿捕获中断
if ( TIM_GetITStatus (GENERAL_TIM, GENERAL_TIM_IT_CCx ) != RESET)
{
// 第一次捕获
if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 )
{
// 计数器清0
TIM_SetCounter ( GENERAL_TIM, 0 );
// 自动重装载寄存器更新标志清0
TIM_ICUserValueStructure.Capture_Period = 0;
// 存捕获比较寄存器的值的变量的值清0
TIM_ICUserValueStructure.Capture_CcrValue = 0;
// 当第一次捕获到上升沿之后,就把捕获边沿配置为下降沿
GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Falling);
// 开始捕获标准置1
TIM_ICUserValueStructure.Capture_StartFlag = 1;
}
// 下降沿捕获中断
else // 第二次捕获
{
// 获取捕获比较寄存器的值,这个值就是捕获到的高电平的时间的值
TIM_ICUserValueStructure.Capture_CcrValue =
GENERAL_TIM_GetCapturex_FUN (GENERAL_TIM);
// 当第二次捕获到下降沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获
GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);
// 开始捕获标志清0
TIM_ICUserValueStructure.Capture_StartFlag = 0;
// 捕获完成标志置1
TIM_ICUserValueStructure.Capture_FinishFlag = 1;
}
TIM_ClearITPendingBit (GENERAL_TIM,GENERAL_TIM_IT_CCx);
}
}
6. 主函数,计算脉冲宽度利用串口输出
int main()
{
uint32_t time;
// TIM 计数器的驱动时钟
float TIM_PscCLK = 72000000.0 / (GENERAL_TIM_PSC+1);
USART_Config();
GeneralTim_Init();
printf("rn ----输入捕获测量脉宽实验----rn");
while(1)
{
if(TIM_ICUserValueStructure.Capture_FinishFlag == 1)
{
time = (TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD + 1)
+ TIM_ICUserValueStructure.Capture_CcrValue + 1);
printf("t=%fn",time/TIM_PscCLK);
TIM_ICUserValueStructure.Capture_FinishFlag = 0;
}
}
}
7. 相关宏定义
#define GENERAL_TIM TIM5
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM5
#define GENERAL_TIM_PERIOD 0XFFFF
#define GENERAL_TIM_PSC (72-1)
// TIM 输入捕获通道GPIO相关宏定义
#define GENERAL_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA
#define GENERAL_TIM_CH1_PORT GPIOA
#define GENERAL_TIM_CH1_PIN GPIO_Pin_0
#define GENERAL_TIM_CHANNEL_x TIM_Channel_1
// 中断相关宏定义
#define GENERAL_TIM_IT_CCx TIM_IT_CC1
#define GENERAL_TIM_IRQ TIM5_IRQn
#define GENERAL_TIM_INT_FUN TIM5_IRQHandler
// 获取捕获寄存器值函数宏定义
#define GENERAL_TIM_GetCapturex_FUN TIM_GetCapture1
// 捕获信号极性函数宏定义
#define GENERAL_TIM_OCxPolarityConfig_FUN TIM_OC1PolarityConfig
// 测量的起始边沿
#define GENERAL_TIM_STRAT_ICPolarity TIM_ICPolarity_Rising
// 测量的结束边沿
#define GENERAL_TIM_END_ICPolarity TIM_ICPolarity_Falling
// 定时器输入捕获用户自定义变量结构体声明
typedef struct
{
uint8_t Capture_FinishFlag; // 捕获结束标志位
上一篇:STM32F103_ADC单通道电压采集中断读取初始化配置步骤
下一篇:STM32F103_SD卡FatFs文件系统移植
推荐阅读最新更新时间:2024-11-13 20:25
设计资源 培训 开发板 精华推荐
- 使用 Analog Devices 的 LTC2621CDD-1 的参考设计
- 用于电机控制应用的双全桥L6227Q的演示板
- 用于以太网路由器和以太网交换机的 3.3V DC 到 DC 单路输出电源
- AL8807Q 高效 30V、1.3A 汽车级降压 LED 驱动器的典型应用
- LT3756IMSE 90% 效率、20W SEPIC LED 驱动器的典型应用电路
- 【课程设计】多功能定位器
- 基于 STM32 Nucleo 的 L62xx 系列双刷直流和步进电机驱动器的评估套件环境
- 使用 RP40-11015DFR DC/DC 转换器并根据 EN55022 A 类(单输出)进行 EMC 滤波的典型应用
- 使用 Analog Devices 的 LTC1595AIN8 的参考设计
- LTC3776 的典型应用 - 用于 DDR/QDR 存储器终端的双路 2 相、无 RSENSE 同步控制器