[其他ST产品] stm32 输入捕获

[复制链接]
580|13
 楼主| 呈兴 发表于 2023-6-28 16:34 | 显示全部楼层 |阅读模式
61137649bf07b9dc30.png
根据定时器的计数频率,我们就可以算出t1-t2的时间,从而得到高电平脉宽

计算公式

N * ARR + CCRx2
1
首先设置定时器通道为上升沿捕获,这样在t1时刻,就会捕获到当前的CNT值,然后立即清零CNT,并设置定时器通道为下降沿捕获,这样到t2时刻,又会发生捕获事件,得到此时的CNT值,记为CCRx2


定时器复用功能重映射


96810649bf09dac5c8.png
 楼主| 呈兴 发表于 2023-6-28 16:35 | 显示全部楼层
输入捕获配置步骤

1.使能定时器时钟
2.使能GPIO时钟,配置引脚模式
3.初始化定时器参数,预分频器的值、自动重装载的值等设定
4.设置通用定时器的输入捕获参数,开启输入捕获功能
5.开启捕获和定时器溢出中断
6.初始化NVIC外设,设置定时器中断优先级
7.使能定时器
8.编写定时器中断处理函数
 楼主| 呈兴 发表于 2023-6-28 16:36 | 显示全部楼层
举例
  1. typedef struct
  2. {
  3.         uint16_t TIM_Channel; //通道
  4.         uint16_t TIM_ICPolarity; //捕获极性
  5.         uint16_t TIM_ICSelection; //直接/间接映射
  6.         uint16_t TIM_ICPrescaler; //分频因子
  7.         uint16_t TIM_ICFilter; //滤波
  8. } TIM_ICInitTypeDef;

  9. #define ICPolarity_Rising        0x40
  10. #define ICPolarity_Falling        0x80
  11. #define Capture1_Max                0x3f

  12. void TIM5_IRQHandler()
  13. {
  14.         if(TIM_GetITStatus(TIM5, TIM_IT_Update) == SET) //产生更新中断
  15.         {
  16.                 if((TIM_sta & ICPolarity_Falling) == ICPolarity_Falling) //低电平捕获中
  17.                 {
  18.                         if((TIM_sta & Capture1_Max) == Capture1_Max) //达到计数值上限
  19.                         {
  20.                                 TIM_sta = ICPolarity_Falling;
  21.                         }
  22.                         else
  23.                         {
  24.                                 TIM_sta++; //更新次数
  25.                         }
  26.                 }
  27.         }

  28.         if(TIM_GetITStatus(TIM5, TIM_IT_CC1) == SET)
  29.         {
  30.                 if((TIM_sta & ICPolarity_Falling) == ICPolarity_Falling) //捕获到低电平
  31.                 {
  32.                         TIM_sta |= ICPolarity_Rising;
  33.                         Capture1_val = TIM_GetCapture1(TIM5); //保存捕获值
  34.                         TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising); //设置上升沿捕获
  35.                 }
  36.                 else
  37.                 {
  38.                         TIM_sta = ICPolarity_Falling;
  39.                         TIM_Cmd(TIM5, DISABLE);
  40.                         TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling); //设置下降沿捕获
  41.                         TIM_SetCounter(TIM5, 0); //计数器值清零
  42.                         TIM_Cmd(TIM5, ENABLE);
  43.                 }       
  44.         }
  45.        
  46.         TIM_ClearITPendingBit(TIM5, TIM_IT_Update | TIM_IT_CC1);
  47. }

  48. void KEY_TIM5_init(u16 period, u16 prescaler)
  49. {
  50.         TIM_TimeBaseInitTypeDef tim_tb = {0};
  51.         TIM_ICInitTypeDef tim_ic =
  52.         {
  53.                 TIM_Channel_1, //通道1
  54.                 TIM_ICPolarity_Rising, //上升沿
  55.                 TIM_ICSelection_DirectTI, //直接映射
  56.                 TIM_ICPSC_DIV1, //1分频
  57.                 0
  58.         };
  59.         NVIC_InitTypeDef nvic =
  60.         {
  61.                 TIM5_IRQn,
  62.                 2,
  63.                 2,
  64.                 ENABLE
  65.         };
  66.         GPIO_InitTypeDef gpio =
  67.         {
  68.                 GPIO_Pin_0,
  69.                 GPIO_Speed_50MHz,
  70.                 GPIO_Mode_IPD //下拉输入模式
  71.         };

  72.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能定时器时钟
  73.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  74.         GPIO_Init(GPIOA, &gpio);
  75.        
  76.         tim_tb.TIM_Prescaler = prescaler;
  77.         tim_tb.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
  78.         tim_tb.TIM_Period = period;
  79.         tim_tb.TIM_ClockDivision = TIM_CKD_DIV1;
  80.         TIM_TimeBaseInit(TIM5, &tim_tb); //初始化定时器

  81.         TIM_ICInit(TIM5, &tim_ic); //设置通用定时器的输入捕获参数

  82.         TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE); //开启捕获和定时器溢出中断

  83.         NVIC_Init(&nvic); //初始化NVIC

  84.         TIM_Cmd(TIM5, ENABLE); //使能定时器
  85. }

  86. int main(void)
  87. {
  88.         KEY_TIM5_init(0xffff, 72 - 1);
  89.         while(1)
  90.         {
  91.                 if((TIM_sta & ICPolarity_Rising) == ICPolarity_Rising) //捕获到低电平
  92.                 {
  93.                         res_data = TIM_sta & Capture1_Max;
  94.                         res_data *= 0xffff;
  95.                         res_data += Capture1_val;
  96.                         printf("高电平持续时间 %d um.\n", res_data);
  97.                         TIM_sta = 0;
  98.                 }
  99.         }
  100. }
星辰大海不退缩 发表于 2023-6-29 13:11 | 显示全部楼层
楼主不是用的HAL库进行的编程吧,标准库现在确实见的少了,对于ST来说
Undshing 发表于 2023-7-1 23:28 | 显示全部楼层
用惯了标准库就不想换了
Pulitzer 发表于 2023-12-30 07:14 | 显示全部楼层

输入电源电流环路
童雨竹 发表于 2023-12-30 09:10 | 显示全部楼层

单片机一般都有内部程序区和数据区
Wordsworth 发表于 2023-12-30 10:13 | 显示全部楼层

输入和输出电流环路连接的位置只能是相应的输入 输出电容的接线端
公羊子丹 发表于 2023-12-30 12:09 | 显示全部楼层

CPLD解密,DSP解密都习惯称为单片机解密
万图 发表于 2023-12-30 13:12 | 显示全部楼层

引线越长,它能接收和传送的干扰信号频率就越低
Uriah 发表于 2023-12-30 14:15 | 显示全部楼层

输入电压端上测得的值比它实际
帛灿灿 发表于 2023-12-30 16:11 | 显示全部楼层

引线的长和宽影响它的电阻和电感量
Bblythe 发表于 2023-12-30 17:14 | 显示全部楼层

它们的放置要尽可能靠近
周半梅 发表于 2023-12-30 19:10 | 显示全部楼层

大部分单片机都带有加密锁定位或者加密字节
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

150

帖子

1

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