[其他ST产品] STM32F103高级定时器作输入捕获(以TIM1通道4为例)

[复制链接]
 楼主| 欢乐家园 发表于 2023-8-27 12:37 | 显示全部楼层 |阅读模式
毕业设计需要使用比较多的定时器,但手上的F103C8T6核心板定时器资源比较少,所以被迫使用高级定时器1(一直都是用通用定时器,毕竟以前玩F429的时候管脚资源充足,就没有去学习高级定时器的用法,以为完全一样的用法,但是移植程序过程还是发现好些需要注意的地方)。下面列出程序中与通用定时器有差别的地方。

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

高级定时器TIM1和GPIOA时钟来源都是APB2



3973264ead3201604c.png

 楼主| 欢乐家园 发表于 2023-8-27 12:38 | 显示全部楼层
9328964ead3280bd0c.png


由上面两图可知,需要使能的是TIM1时钟和GPIOA时钟:https://bbs.21ic.com/forum.php?mod=attachment&aid=MjE1MjcxMHw1NWM0MTI4N3wxNzU1OTg2MzkwfDB8

  1.     //使能TIM1和GPIOA时钟
  2.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//初始化TIME时钟
  3.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//初始化GPIOA时钟
 楼主| 欢乐家园 发表于 2023-8-27 12:38 | 显示全部楼层
 楼主| 欢乐家园 发表于 2023-8-27 12:38 | 显示全部楼层
2. GPIOA中的PA11配置为输入模式,PA12设置为输出模式
  1.     //配置PA11
  2.     GPIOA_Initstructure.GPIO_Pin=GPIO_Pin_11;//PA11
  3.     GPIOA_Initstructure.GPIO_Mode=GPIO_Mode_IPD;//输入
  4.     GPIO_ResetBits(GPIOA,GPIO_Pin_11); //PA11 下拉
  5.     GPIO_Init(GPIOA,&GPIOA_Initstructure);
  6.    
  7.     //配置PA12
  8.     GPIOA_Initstructure.GPIO_Pin=GPIO_Pin_12;//PA12
  9.     GPIOA_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;//输出                     
  10.     GPIOA_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.     GPIO_Init(GPIOA,&GPIOA_Initstructure);
 楼主| 欢乐家园 发表于 2023-8-27 12:39 | 显示全部楼层
关于GPIO口的八种模式原子论坛有帖子说的很详细,以前看过的,有兴趣可以去搜索。

 楼主| 欢乐家园 发表于 2023-8-27 12:46 | 显示全部楼层
初始化TIM1、置 TIM1 的输入比较参数、
  1.     //初始化 TIM1, 设置 TIM1 的 ARR 和 PSC
  2.     TIM1_CH4_Handler.TIM_Prescaler=psc;//预分频系数
  3.     TIM1_CH4_Handler.TIM_Period=arr;//自动重装载值
  4.     TIM1_CH4_Handler.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
  5.     TIM1_CH4_Handler.TIM_ClockDivision=TIM_CKD_DIV1;//预分频系数为1
  6.     TIM1_CH4_Handler.TIM_RepetitionCounter=0;//设置重复溢出次数,就是多少次溢出后进入中断,一般为0,只有高级定时器才有用
  7.     TIM_TimeBaseInit(TIM1,&TIM1_CH4_Handler);
  8.    
  9.     //设置 TIM1 的输入比较参数,开启输入捕获
  10.     TIM1_IC_Handler.TIM_Channel=TIM_Channel_4;//TIM1通道4
  11.     TIM1_IC_Handler.TIM_ICFilter=0x00;//输入滤波器长度为0
  12.     TIM1_IC_Handler.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
  13.     TIM1_IC_Handler.TIM_ICPrescaler=TIM_ICPSC_DIV1;//预分频系数,不分频
  14.     TIM1_IC_Handler.TIM_ICSelection=TIM_ICSelection_DirectTI; //映射到 TI1 上
  15.     TIM_ICInit(TIM1,&TIM1_IC_Handler);
 楼主| 欢乐家园 发表于 2023-8-27 12:46 | 显示全部楼层
TIM1_CH4_Handler.TIM_RepetitionCounter=0;//设置重复溢出次数,就是多少次溢出后进入中断,一般为0,只有高级定时器才有用到
 楼主| 欢乐家园 发表于 2023-8-27 12:46 | 显示全部楼层
使能捕获和更新中断、设置中断分组、使能定时器
  1.     //使能捕获和更新中断(设置 TIM1 的 DIER 寄存器)
  2.     TIM_ITConfig( TIM1,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断和捕获中断
  3.    
  4.     //设置中断分组
  5.     NVIC_Initstructure.NVIC_IRQChannel=TIM1_CC_IRQn;//定时器1
  6.     NVIC_Initstructure.NVIC_IRQChannelCmd=ENABLE;//使能TIM1
  7.     NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级2
  8.     NVIC_Initstructure.NVIC_IRQChannelSubPriority=0;//子优先级0
  9.     NVIC_Init(&NVIC_Initstructure);
  10.    
  11.     TIM_CtrlPWMOutputs(TIM1,ENABLE);        //主输出使能
  12.    
  13.     //使能定时器(设置 TIM1 的 CR1 寄存器)
  14.     TIM_Cmd(TIM1,ENABLE);//使能定时器1
 楼主| 欢乐家园 发表于 2023-8-27 12:47 | 显示全部楼层
选择NVIC_IRQChannel中的TIM1_CC_IRQn,即TIM1捕获比较中断。

1381864ead5546d298.png
 楼主| 欢乐家园 发表于 2023-8-27 12:47 | 显示全部楼层
定时器1中断服务函数
  1. //定时器1中断服务程序
  2. void TIM1_CC_IRQHandler(void)
  3. {
  4.     if((TIM1CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
  5.     {
  6.         if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
  7.         {
  8.             if(TIM1CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
  9.             {
  10.                 if((TIM1CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
  11.                 {
  12.                     TIM1CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
  13.                     TIM1CH4_CAPTURE_VAL=0XFFFF;
  14.                 }else TIM1CH4_CAPTURE_STA++;
  15.             }
  16.         }
  17.         if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)//捕获 1 发生捕获事件
  18.         {
  19.             if(TIM1CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
  20.             {
  21.                 TIM1CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
  22.                 TIM1CH4_CAPTURE_VAL=TIM_GetCapture4(TIM1);
  23.                 TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Rising);
  24.                 //CC1P=0 设置为上升沿捕获
  25.             }else //还未开始,第一次捕获上升沿
  26.             {
  27.                 TIM1CH4_CAPTURE_STA=0; //清空
  28.                 TIM1CH4_CAPTURE_VAL=0;
  29.                 TIM_SetCounter(TIM1,0);
  30.                 TIM1CH4_CAPTURE_STA|=0X40; //标记捕获到了上升沿
  31.                 TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Falling);
  32.                 //CC1P=1 设置为下降沿捕获
  33.             }
  34.         }
  35.     }
  36.     TIM_ClearITPendingBit(TIM1, TIM_IT_CC4|TIM_IT_Update); //清除中断标志位
  37. }
 楼主| 欢乐家园 发表于 2023-8-27 12:47 | 显示全部楼层
定时器中断函数服务名字选择:void TIM1_CC_IRQHandler(void);
7822264ead5703f46f.png
 楼主| 欢乐家园 发表于 2023-8-27 12:48 | 显示全部楼层
以上,就是使用TIM1做输入捕获的过程。
xxmmi 发表于 2023-8-27 12:51 | 显示全部楼层
定时器资源为啥比较少
您需要登录后才可以回帖 登录 | 注册

本版积分规则

113

主题

1029

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部

113

主题

1029

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部