STM32F103高级定时器作输入捕获(以TIM1通道4为例)

毕业设计需要使用比较多的定时器,但手上的F103C8T6核心板定时器资源比较少,所以被迫使用高级定时器1(一直都是用通用定时器,毕竟以前玩F429的时候管脚资源充足,就没有去学习高级定时器的用法,以为完全一样的用法,但是移植程序过程还是发现好些需要注意的地方)。下面列出程序中与通用定时器有差别的地方。

用到的定时器是TIM1通道4,原型是作为超声波捕获,单独拿出配置定时器输入捕获函数和中断服务函数来说明,程序都写了注释,没有一一说明的地方可以直接看注释。

  1. 高级定时器TIM1和GPIOA时钟来源都是APB2
    在这里插入图片描述
    在这里插入图片描述
    由上面两图可知,需要使能的是TIM1时钟和GPIOA时钟:
    //使能TIM1和GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//初始化TIME时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//初始化GPIOA时钟

在这里插入图片描述
2. GPIOA中的PA11配置为输入模式,PA12设置为输出模式

    //配置PA11
    GPIOA_Initstructure.GPIO_Pin=GPIO_Pin_11;//PA11
    GPIOA_Initstructure.GPIO_Mode=GPIO_Mode_IPD;//输入
    GPIO_ResetBits(GPIOA,GPIO_Pin_11); //PA11 下拉
    GPIO_Init(GPIOA,&GPIOA_Initstructure);
    
    //配置PA12
    GPIOA_Initstructure.GPIO_Pin=GPIO_Pin_12;//PA12
    GPIOA_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;//输出		     
    GPIOA_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIOA_Initstructure);

关于GPIO口的八种模式原子论坛有帖子说的很详细,以前看过的,有兴趣可以去搜索。

  1. 初始化TIM1、置 TIM1 的输入比较参数、
    //初始化 TIM1, 设置 TIM1 的 ARR 和 PSC
    TIM1_CH4_Handler.TIM_Prescaler=psc;//预分频系数
    TIM1_CH4_Handler.TIM_Period=arr;//自动重装载值
    TIM1_CH4_Handler.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
    TIM1_CH4_Handler.TIM_ClockDivision=TIM_CKD_DIV1;//预分频系数为1
    TIM1_CH4_Handler.TIM_RepetitionCounter=0;//设置重复溢出次数,就是多少次溢出后进入中断,一般为0,只有高级定时器才有用
    TIM_TimeBaseInit(TIM1,&TIM1_CH4_Handler);
    
    //设置 TIM1 的输入比较参数,开启输入捕获
    TIM1_IC_Handler.TIM_Channel=TIM_Channel_4;//TIM1通道4
    TIM1_IC_Handler.TIM_ICFilter=0x00;//输入滤波器长度为0
    TIM1_IC_Handler.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
    TIM1_IC_Handler.TIM_ICPrescaler=TIM_ICPSC_DIV1;//预分频系数,不分频
    TIM1_IC_Handler.TIM_ICSelection=TIM_ICSelection_DirectTI; //映射到 TI1 上
    TIM_ICInit(TIM1,&TIM1_IC_Handler);

TIM1_CH4_Handler.TIM_RepetitionCounter=0;//设置重复溢出次数,就是多少次溢出后进入中断,一般为0,只有高级定时器才有用到

  1. 使能捕获和更新中断、设置中断分组、使能定时器
    //使能捕获和更新中断(设置 TIM1 的 DIER 寄存器)
    TIM_ITConfig( TIM1,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断和捕获中断
    
    //设置中断分组
    NVIC_Initstructure.NVIC_IRQChannel=TIM1_CC_IRQn;//定时器1
    NVIC_Initstructure.NVIC_IRQChannelCmd=ENABLE;//使能TIM1
    NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级2
    NVIC_Initstructure.NVIC_IRQChannelSubPriority=0;//子优先级0
    NVIC_Init(&NVIC_Initstructure);
   
    TIM_CtrlPWMOutputs(TIM1,ENABLE);	//主输出使能
   
    //使能定时器(设置 TIM1 的 CR1 寄存器)
    TIM_Cmd(TIM1,ENABLE);//使能定时器1

选择NVIC_IRQChannel中的TIM1_CC_IRQn,即TIM1捕获比较中断。在这里插入图片描述

  1. 定时器1中断服务函数
//定时器1中断服务程序
void TIM1_CC_IRQHandler(void)
{
    if((TIM1CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
    {
        if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
        {
            if(TIM1CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
            {
                if((TIM1CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                {
                    TIM1CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
                    TIM1CH4_CAPTURE_VAL=0XFFFF;
                }else TIM1CH4_CAPTURE_STA++;
            }
        }
        if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)//捕获 1 发生捕获事件
        {
            if(TIM1CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
            {
                TIM1CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
                TIM1CH4_CAPTURE_VAL=TIM_GetCapture4(TIM1);
                TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Rising);
                //CC1P=0 设置为上升沿捕获
            }else //还未开始,第一次捕获上升沿
            {
                TIM1CH4_CAPTURE_STA=0; //清空
                TIM1CH4_CAPTURE_VAL=0;
                TIM_SetCounter(TIM1,0);
                TIM1CH4_CAPTURE_STA|=0X40; //标记捕获到了上升沿
                TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Falling);
                //CC1P=1 设置为下降沿捕获
            }
        }
    }
    TIM_ClearITPendingBit(TIM1, TIM_IT_CC4|TIM_IT_Update); //清除中断标志位
}

定时器中断函数服务名字选择:void TIM1_CC_IRQHandler(void);
在这里插入图片描述

以上,就是使用TIM1做输入捕获的过程。

发布了17 篇原创文章 · 获赞 47 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_42827999/article/details/103440416