完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
通用定时器TIM2~5
引脚定义 TIM2_CH1------PA0 TIM2_CH2------PA1 TIM2_CH3------PA2 TIM2_CH4------PA3 TIM3_CH1------PA6 TIM3_CH2------PA7 TIM3_CH3------PB0 TIM3_CH4------PB1 对于通用定时器主要有三个功能: 基本的定时器功能,和基本定时器相同 PWM脉冲输出 测量输入脉冲的频率和脉冲宽度 基本定时器功能 TIM2~5的基本定时器功能与基本定时器TIM6和TIM7类似,不过不同的是,对于基本定时器中的计数器只能向上计数,而通用定时器的计数器可以配置计数模式向上或者向下。 向上计数模式:从零开始向上计数,当达到TIMx_ARR中的值时,计数器清零,然后产生一个计数器溢出中断 向下计数模式:从TIMx_ARR中的数值开始向下计数,当计数器中数为0时,自动将TIMx_ARR中的数重装入计数器,同时产生一个向下溢出事件。 PWM脉冲输出 对应于上面的GPIO口,将对应的GPIO配置为推挽复用输出。对于TIM的配置主要包括两个结构TIM_TimeBaseInitTypeDef和TIM_OCInitTypeDef,对于第一个结构体就是配置基本定时器时所使用的,对于第二结构体是输出捕获(Output Capture),只要用来配置输出PWM的占空比,高低电平等信息。 对于TIM_TimeBaseInitTypeDef的配置 类似于基本定时器的配置: .TIM_Period:定时的周期,该值存储在ARR中,计数器从0自增到该值,或者从该值自减到0 .TIM_Prescaler:对TIMxCLK的预分频系数,分频后作为计数器的驱动时钟, 驱 动 时 钟 = T I M x C L K / ( 分 频 系 数 + 1 ) 驱动时钟=TIMxCLK/(分频系数+1) 驱动时钟=TIMxCLK/(分频系数+1) .TIM_ClockDivision:时钟分频因子,这个与上一个不同,这个也是对TIMxCLK进行分频,但分频后的时钟被输送到定时器的ETRP数字滤波器,会影响滤波器的采样频率。ETRP数字滤波器是对外部时钟TIMxETR进行滤波。一般使用内部时钟,该值没有任何影响。 .TIM_CounterMode:配置计数器的技术模式,常用的是向上计数或者向下计数。 具体的配置,如下代码: tim_s.TIM_ClockDivision = TIM_CKD_DIV1; tim_s.TIM_CounterMode = TIM_CounterMode_Up; tim_s.TIM_Period = 9999; tim_s.TIM_Prescaler = 0; TIM_TimeBaseInit(TIM2,&tim_s); 对于TIM_OCInitTypeDef的配置 对于TIM_OCInitTypeDef结构体在通用定时器中的用处来看,就是配置输出PWM的相关信息: .TIM_OCMode:配置PWM输出的模式,总共有两种模式PWM1和PWM2,。 PWM1:向上计数时,当计数器中的数值小于CCR中的数值(也就是后面配置的TIM_Pulse的值)时输出为有效电平,当计数器中的数值大于CCR中的数值且小于ARR中的数值时,输出为无效电平。向下计数时,计数器中的数值大于CCR中的值输出为无效电平。 PWM2:向上计数时,当计数器中的数值小于CCR中的数值(也就是后面配置的TIM_Pulse的值)时输出为无效电平,当计数器中的数值大于CCR中的数值且小于ARR中的数值时,输出为有效电平。向下计数时,计数器中的数值大于CCR中的值输出为有效电平。 .TIM_OutputState:配置输出模式的状态,使能输出。 .TIM_OCPolarity:(polarity n.极性)该配置有效电平的极性,可以将有效电平配置高电平,也可以配置为低电平。 .TIM_Pulse:该参数记为CCR中的数值,由它来控制PWM的占空比。 具体的配置代码如下: oc_s.TIM_OCMode = TIM_OCMode_PWM1; oc_s.TIM_OutputState = TIM_OutputState_Enable; oc_s.TIM_OCPolarity = TIM_OCPolarity_High; oc_s.TIM_Pulse = 1000; TIM_OC1Init(TIM2,&oc_s); 对于同一个定时器的不同通道需要单独初始化TIM_OCxInit(TIMx,&oc_s) 并且对于每个通道初始化之后,需要将CCR中的值存入寄存器TIM_OCxPreloadConfig(TIMx,TIM_OCPreload_Enable) 在开启TIM之前需要将ARR的也存入寄存器TIM_ARRPreloadConfig(TIMx,ENABLE) 对于PWM输出的TIM完整配置代码如下: void TIM2_Config(void) { TIM_TimeBaseInitTypeDef tim_s; TIM_OCInitTypeDef oc_s; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); oc_s.TIM_OCMode = TIM_OCMode_PWM1; oc_s.TIM_OutputState = TIM_OutputState_Enable; oc_s.TIM_OCPolarity = TIM_OCPolarity_High; oc_s.TIM_Pulse = 1000; TIM_OC1Init(TIM2,&oc_s); TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable); oc_s.TIM_Pulse = 8000; TIM_OC2Init(TIM2,&oc_s); TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2,ENABLE); TIM_Cmd(TIM2,ENABLE); } 测量输入脉冲的频率和脉冲宽度 对于测量输入脉冲的频率和脉冲宽度,需要配置对应通道的GPIO。将对应的GPIO配置为下拉输入。对于输入脉冲测量主要配置两个结构体和书写中断函数。具体的工作过程,假设使用通道1来进行脉冲测量,首先在配置中将捕获设为上升沿捕获,则当捕获到上升沿时,触发中断,在中断中将触发方式改为下降沿触发,并将计数器中的数清0。当下降沿到来,再次触发中断,计数器中的数自动存入到CCR中,则在中断中将触发方式再次更改为上升沿触发,且可以读出CCR中的值即为输入PWM的高电平时间。当上升沿再次到来,计数器中的数自动存入到CCR中,并触发中断,在中断中将CCR的值读出即为PWM的周期(以上的过程,默认为PWM的周期小于定时器溢出的时间) 配置两个结构体 在测量输入脉冲时需要配置TIM_TimeBaseInitTypeDef和TIM_ICInitTypeDef,对于TIM_TimeBaseInitTypeDef来说和之前的PWM配置相似,不同的是关于预分频系数和周期的配置,这个按照需要自己配置。 TIM_ICInitTypeDef的配置 .TIM_Channel:进行采用的通道,例TIM_Channel_3。 .TIM_ICPolarity:触发中断的电平,可以设置为上升沿,也可设置成下降沿。 .TIM_ICPrescaler:输入分频器,对输入的PWM可以进行相应的分频,例如2分频,就是两个周期采样一次。(个人理解) .TIM_ICFilter:输入的滤波器,没用,设为0x00 .TIM_ICSeclection:设置是否直连如下图中对于TI1来说,后面有TIFP1和TIFP2,对于TIFP1是直接连,对于TIFP2是间接连接。 #FormatImgID_0# 具体的配置代码: ic_s.TIM_Channel = TIM_Channel_3; ic_s.TIM_ICPolarity = TIM_ICPolarity_Rising; ic_s.TIM_ICPrescaler = TIM_ICPSC_DIV1; ic_s.TIM_ICFilter = 0x00; ic_s.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInit(TIM2,&ic_s); 在结构配置完成以后,需要对中断控制器进行配置: void NVIC_Config(void) { NVIC_InitTypeDef nvic_s; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); nvic_s.NVIC_IRQChannel = TIM2_IRQn; nvic_s.NVIC_IRQChannelPreemptionPriority = 0; nvic_s.NVIC_IRQChannelSubPriority = 2; nvic_s.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic_s); } 配置完成以后打开中断TIM_ITConfig(TIM2,TIM_IT_Update | TIM_IT_CC3|TIM_IT_CC4,ENABLE); TIM_IT_Update:计数器溢出中断 TIM_IT_CC3:通道3的捕获中断 TIM_IT_CC4:通道4的捕获中断 中断函数的编写 对于中断函数的编写流程如下(以上的过程,默认为PWM的周期小于定时器溢出的时间): 首次上升沿捕获成功触发中断,进入中断,在中断中使用TIM_SetCounter(TIMx,0)将对应的定时器中计数器清0.然后将对应的通道设置为下降沿捕获TIM_OCnPolarityConfig(TIMx,TIM_ICPolarity_Falling);,同时需要标记上升沿第一次来。对应通道捕获到下降沿,自动的将计数器CNT中的数值赋值到CCR中,同时触发中断,在中断中可以将CCR的值读出,该值就是所测波形的高电平时间,然后再将该通道设置为上升沿捕获。再次捕获到上升沿,判断是否是第二次捕获上升沿,如果是就将CCR中的值读出,该值是第一个上升沿到第二个上升沿的时间,如果是周期性PWM的话,该值就是PWM的周期时间。如果不是第二次捕获,就重复之前第一捕获的流程。 具体的代码为: void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//计数器溢出中断判断 { } if(TIM_GetITStatus(TIM2,TIM_IT_CC3) == SET)//定时器通道3捕获中断判断 { if(C3_flag == 0)// 第一次上升沿到来 { TIM_SetCounter(TIM2,0); TIM_OC3PolarityConfig(TIM2,TIM_ICPolarity_Falling); C3_flag = 1; } else if(C3_flag == 1)//第一次下降沿到来 { c3_high = (uint32_t)TIM_GetCapture3(TIM2); TIM_OC3PolarityConfig(TIM2,TIM_ICPolarity_Rising); C3_flag = 2; } else if(C3_flag == 2)//第二次上升沿到来 { c3_proide = (uint32_t)TIM_GetCapture3(TIM2); C3_flag = 0; } } TIM_ClearITPendingBit(TIM2,TIM_IT_Update | TIM_IT_CC3|TIM_IT_CC4); } 注意到在上面提到两次PWM的周期小于定时器的溢出时间,是为中断函数的编写和便于把原理叙述清楚,如果没有这个假设,那就要考虑所有的情况 所有的情况大致有以下几类 PWM周期 = 定时器的溢出时间:此时对于上升沿的读取时间是没有问题的,对于周期的读取值会是0. PWM周期 》定时器的溢出时间:此时又分为两种情况:定时器溢出发生在上升沿和下降沿之间,或者发生在下降沿和上升沿之间。这种情况因为发生定时器溢出时,计数器会被清0,所以需要统计定时器溢出的次数,在最后将对应的时间加上(计数器溢出次数*计数器溢出时间。) |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 07:15 , Processed in 0.808718 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号