福州做网站的,wordpress 关于页面,wordpress编辑器分页,seo网络推广公司前言
学习是永无止境的#xff0c;就算之前学过的东西再次学习一遍也能狗学习到很多东西#xff0c;输入捕获很早之前就用过了#xff0c;但是仅仅是照搬例程没有去进行理解。温故而知新#xff01;
定时器
定时器简介
定时器的分类
高级定时器 通用定时器 基本定时器…前言
学习是永无止境的就算之前学过的东西再次学习一遍也能狗学习到很多东西输入捕获很早之前就用过了但是仅仅是照搬例程没有去进行理解。温故而知新
定时器
定时器简介
定时器的分类
高级定时器 通用定时器 基本定时器针对不同情况可以选择自己所需要的定时器以下是这几种定时器的主要功能。
高级定时器
计数器单元输入捕获重复计数器PWM模式互补输出和死区插入支持针对定位的增量(正交)编码器和霍尔传感器电路刹车功能DMA功能
通用定时器
计数器单元输入捕获PWM模式支持针对定位的增量(正交)编码器和霍尔传感器电路DMA功能
基本定时器
计数器单元DMA功能
定时器的功能
我们使用定时器很多时候使用都是用做于计数作用同样也可以作为PWM输出输入捕获脉宽测量频率检测等等有的时候我们还会使用DMAPWM输出这样的功能总之定时器对于我们进行产品开发是必不可少的。 定时器的配置
主要寄存器
这里我使用的是航芯ACM32FP0X系列的单片机不过其他单片机用法也是一样的。 这里我们主要关注以上六个寄存器中断使能寄存器、状态寄存器、事件产生寄存器、预分频寄存器、自动加载寄存器、捕获/比较寄存器。其他的寄存器不是说不重要只是在本次实验中主要理解这几个寄存器就好。
PWM配置
因为本次实验没有使用外置的脉冲发生器所以使用单片机上另一个通用定时器来配置PWM然后使用高级定时器去进行输入捕获。 TIM_Handler_PWM.Instance TIM15;TIM_Handler_PWM.Init.ARRPreLoadEn TIM_ARR_PRELOAD_ENABLE; TIM_Handler_PWM.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; TIM_Handler_PWM.Init.CounterMode TIM_COUNTERMODE_UP; TIM_Handler_PWM.Init.RepetitionCounter 0; TIM_Handler_PWM.Init.Prescaler (timer_clock/TIM_CLOCK_FREQ)*1 - 1; if (timer_clock%TIM_CLOCK_FREQ TIM_CLOCK_FREQ/2) {TIM_Handler_PWM.Init.Prescaler TIM_Handler_PWM.Init.Prescaler 1; }TIM_Handler_PWM.Init.Period (TIM_CLOCK_FREQ/100000)*20 - 1; // period 1ms
首先是常规的配置这里我选择的是定时器15作为PWM口进行输出然后不分频所以APB的时钟就是定时器的时钟。然后就是自动重装载值ARR和预分配系数Prescaler的配置这两个参数共同决定了配置的PWM输出极限频率是多少。
PWM输出频率 Fre 。
这里来解析一下为什么要使用 TIM_CLOCK_FREQ这个参数
TIM_CLOCK_FREQ 代表的是定时器经过分频之后能够达到的极限频率我们可以来推导一下timer_clock也就是主时钟APBCLK分频之后 就是
简单约去公约数得到的就是TIM_CLOCK_FREQ所以当重装载值为1的时候TIM_CLOCK_FREQ就是最高频率。再来解释一下周期是怎么得出的由于1s之内计数器计数了TIM_CLOCK_FREQ次所以一次需要的时间是1/TIM_CLOCK_FREQ所以周期和重装载值之间的关系就是T 这里除以1000的原因是将秒的单位换算成毫秒。OK也不知道讲清楚了没有之前也搞不懂这个关系式后来推导出来的时候还感觉蛮巧妙的。
配置完这些再配置一下模式和占空比CCR和引脚就行了
输入捕获的配置 TIM_IC_InitTypeDef Tim_IC_Init_Para; TIM_Handler.Instance TIM1;TIM_Handler.Init.ARRPreLoadEn TIM_ARR_PRELOAD_ENABLE; TIM_Handler.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; TIM_Handler.Init.CounterMode TIM_COUNTERMODE_UP; TIM_Handler.Init.RepetitionCounter 0; TIM_Handler.Init.Prescaler 0; TIM_Handler.Init.Period 0xFFFF; // max period TIM1_MSP_Pre_Init(TIM_Handler); HAL_TIMER_Base_Init(TIM_Handler); Tim_IC_Init_Para.TIFilter TIM_TI1_FILTER_LVL(0); // no filter Tim_IC_Init_Para.ICPolarity TIM_SLAVE_CAPTURE_ACTIVE_RISING_FALLING; Tim_IC_Init_Para.ICPrescaler TIM_IC1_PRESCALER_1; Tim_IC_Init_Para.ICSelection TIM_ICSELECTION_DIRECTTI; // TI1FP1 HAL_TIMER_Capture_Config(TIM_Handler.Instance, Tim_IC_Init_Para, TIM_CHANNEL_1); TIM1_MSP_Post_Init();
上面也是一些很常规的配置配置了分频系数为1意味着定时器的频率和APB时钟一致重装载值为0xFFFF这些数据传达了一个怎样的信息呢说明了使用输入捕获的频率可高达64MHzAPB时钟为64MHz说明捕获精度可以达到1/64000000 s也就是15ns最长捕获时间间隔为1023us15ns * 0xFFFF。然后下一个就是设置捕获触发模式可能不同的单片机的库设置起来会有细微差别但是大致意思是相同的。由于我们需要收集这些鞋数据然后在串口上打印出来所以我这里使用了中断触发在中断里面收集数据。 HAL_TIMER_Clear_Capture_Flag(TIM_Handler, TIM_CHANNEL_1);NVIC_ClearPendingIRQ(TIM1_CC_IRQn); NVIC_ClearPendingIRQ(TIM1_BRK_UP_TRG_COM_IRQn);NVIC_EnableIRQ(TIM1_CC_IRQn); NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); HAL_TIMER_Base_Init(TIM_Handler); HAL_TIM_ENABLE_IT(TIM_Handler, TIM_IT_CC1);HAL_TIM_ENABLE_IT(TIM_Handler, TIMER_INT_EN_UPD); //计数器向上溢出/向下溢出 用于记录更新次数HAL_TIM_Capture_Start(TIM_Handler.Instance, TIM_CHANNEL_1);
当然这里还加了个溢出中断用于辅助捕获计算超出最大捕获长度的电平时间具体思路就是当计数器溢出的时候在事件更新中断里面设置一个变量进行加加。
可以大致看一下捕获中断里面的函数主要是获取触发了捕获中断之后将数据写入事先定义好的数组然后在定义一个变量进行计数。
void TIM1_CC_IRQHandler(void)
{uint32_t status; status TIM1-SR; if ( (status TIMER_SR_CC1IF) ((TIM1-CCMR1) (BIT0|BIT1)) ) {if(flag1 1)flag2 1;flag1 1;Capture_data[0][capture_times] TIM1-CCR1;}if ((status TIMER_SR_CC2IF) ((TIM1-CCMR1) (BIT8|BIT9)) ) {Capture_data[1][capture_times] TIM1-CCR2; }capture_times; NVIC_ClearPendingIRQ(TIM1_CC_IRQn);
}
然后在主函数里面获取标志位之后打印显示就可以了 这样在主函数当中我们就可以是去使用到这些数据然后打印到串口。这里要注意一点我使用的是双边沿触发所以打印出来的不是一个周期而是两段占空比的数值。
当然这里我还使用了DMAPWM进行PWM输出如果再讲下去就有点多了这部分内容网上也有很多。 总结
输入捕获是高级定时器和通用定时器才有的功能主要通过设置触发边沿和设置捕获频率来对脉宽进行一个测量得出脉宽之后我们就可以很容易地计算出频率和周期。