完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一。通用定时器的基本原理
1.三种STM32定时器区别 2.通用定时器功能特点描述 (1)STM32 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能特点包括: ①位于低速的APB1总线上(APB1) ②16 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。 ③16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值。 ④4 个独立通道(TIMx_CH1~4),这些通道可以用来作为: (每个定时器都有四个通道,互不影响) 输入捕获 输出比较 PWM 生成(边缘或中间对齐模式) 单脉冲模式输出 ⑥可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。 ⑦如下事件发生时产生中断/DMA(6个独立的IRQ/DMA请求生成器): 1)更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 2)触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) 3)输入捕获 4)输出比较 5)支持针对定位的增量(正交)编码器和霍尔传感器电路 6)触发输入作为外部时钟或者按周期的电流管理 ⑧STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。 ⑨使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。 3.计数器模式 通用定时器可以向上计数、向下计数、向上向下双向计数模式。 ①向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。 ②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。 ③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。 二。定时器中断 1.时钟选择 1) 内部时钟(CK_INT) 2) 外部时钟模式 1:外部输入脚(TIx) 3) 外部时钟模式 2:外部触发输入(ETR) 4) 内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟) 2.内部时钟选择(默认为内部时钟) 3.时钟计算方法 这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。这里的CK_INT时钟是从 APB1 倍频的来的,STM32 中除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx的时钟是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于APB1 的时钟。这里还要注意的就是高级定时器的时钟不是来自 APB1,而是来自 APB2 的。 除非APB1的分频系数是1,否则通用定时器的时钟等于APB1时钟的2倍。 默认调用SystemInit函数情况下: SYSCLK=72M AHB时钟=72M APB1时钟=36M 所以APB1的分频系数=AHB/APB1时钟=2 所以,通用定时器时钟CK_INT=2*36M=72M 4.定时器中断实验相关寄存器 (1)计数器当前值寄存器CNT (2)预分频寄存器TIMx_PSC (3)自动重装载寄存器(TIMx_ARR) (4)控制寄存器1(TIMx_CR1) (5)DMA中断使能寄存器(TIMx_DIER) 5.常用库函数 (1)定时器参数初始化: void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); typedef struct { uint16_t TIM_Prescaler; //设置分频系数,PSC uint16_t TIM_CounterMode; //设置技术方式【向上计数,向下计数,中央对齐计数】 uint16_t TIM_Period; //设置自动重装计数周期值,就是ARR uint16_t TIM_ClockDivision; //设置时钟分频因子 uint8_t TIM_RepetitionCounter;//高级定时器才用 } TIM_TimeBaseInitTypeDef; (2)定时器使能函数 void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState) (3)定时器中断使能函数: void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); (4)状态标志位获取和清除: FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);//自动判断是否触发中断 void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); 6.定时器中断实现步骤 ①能定时器时钟。 RCC_APB1PeriphClockCmd(); ②初始化定时器,配置ARR,PSC。 TIM_TimeBaseInit(); ③开启定时器中断,配置NVIC。 void TIM_ITConfig();//可设置允许中断更新 NVIC_Init(); ④使能定时器。 TIM_Cmd();//允许TIMx工作 ⑤编写中断服务函数。 TIMx_IRQHandler();//主要清除中断标志位 7.定时时间计算公式 Tout= ((arr+1)*(psc+1))/Tclk 其中: Tclk: TIMx 的输入时钟频率(单位为 Mhz) Tout: TIM3x溢出时间(单位为 us) psc:分频系数 arr:自动重装值 【psc+arr:一般设置为入口参数,用于调节定时周期】 三。定时器输出PWM 1.PWM 简介 STM32 的定时器除了TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,STM32 最多可以同时产生 30 路 PWM 输出! 要使 STM32 的高级定时器 TIM1 产生 PWM 输出,除了上一章介绍的几个寄存器(ARR、PSC、 CR1 等) 外,我们还会用到 4 个寄存器(通用定时器则只需要 3 个),来控制 PWM 的输出。这四个寄存器分别是:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4) 以及刹车和死区寄存器(TIMx_BDTR)。接下来我们简单介绍一下这四个寄存器。 2.STM32 PWM工作过程示意图 CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值。 CCMR1: OC1M[2:0]位: 对于PWM方式下,用于设置PWM模式1【110】或者PWM模式2【111】 CCER:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。 CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。 PWM模式1 & PWM模式2的比较:输出电平的极性相反 3.STM32 PWM void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); 4.自动重载的预装载寄存器 void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); 功能:简单的说,ARPE=1,ARR立即生效。..。.APRE=0,ARR下个比较周期生效。 5.PWM输出库函数 (1)PWM配置初始函数:void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); typedef struct { uint16_t TIM_OCMode; //PWM模式1或者模式2 uint16_t TIM_OutputState; //输出使能 OR使能 uint16_t TIM_OutputNState; uint16_t TIM_Pulse; //比较值,写CCRx uint16_t TIM_OCPolarity; //比较输出极性 uint16_t TIM_OCNPolarity; uint16_t TIM_OCIdleState; uint16_t TIM_OCNIdleState; } TIM_OCInitTypeDef;//可以只给上述四个成员赋值就行,其他的参数 TIM_OutputNState, TIM_OCNPolarity, TIM_OCIdleState 和 TIM_OCNIdleState 是 高级定时器 TIM1 和 TIM8 才用到的 (2)设置比较值函数 void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Compare2); (3)使能输出比较预装载 void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); (4)使能自动重装载的预装载寄存器允许位 void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); 6.PWM输出配置步骤 ①使能定时器和相关IO口时钟。 使能定时器3时钟:RCC_APB1PeriphClockCmd(); 使能GPIOB时钟:RCC_APB2PeriphClockCmd(); ②初始化IO口为复用功能输出。函数:GPIO_Init(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; ③这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,所以需要开启AFIO时钟。同时设置重映射。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); ④ 初始化定时器:ARR,PSC等:TIM_TimeBaseInit(); ⑤初始化输出比较参数:TIM_OC2Init();// PWM 模式及通道方向 ⑥使能预装载寄存器: TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); ⑦ 使能定时器。TIM_Cmd(); 注:设置 MOE 输出,使能 PWM 输出 普通定时器在完成以上设置了之后, 就可以输出 PWM 了,但是高级定时器,还需要使能刹车和死区寄存器(TIM1_BDTR)的 MOE 位,以使能整个 OCx(即 PWM)输出。 TIM_CtrlPWMOutputs(TIM1,ENABLE);// MOE 主输出使能 ⑧ 不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2();//修改 TIM1_CCR1 来控制占空比 定时器中断+PWM初始化产生 源码: #include “timer.h” #include “LED.h” #include “stm32f10x.h” //arr:自动重装值 //pre:预分频系数 void TIM3_Int_Init(u16 arr,u16 pre) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3的时钟,挂载在APB1上 //初始化时钟 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分割 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数 TIM_TimeBaseInitStruct.TIM_Period = arr;//自动重装值 TIM_TimeBaseInitStruct.TIM_Prescaler = pre;//预分频 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct); //开启定时器中断,配置NVIC TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//允许更新中断 NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;//TIM3中断 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3; NVIC_Init(&NVIC_InitStruct); TIM_Cmd(TIM3,ENABLE);//使能定时器3 } void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3,TIM_IT_Update)) { TIM_ClearITPendingBit(TIM3,TIM_IT_Update); LED0 = !LED0; } } //TIM1_CH1---》PA8:默认复用功能--部分重映射 void TIM1_PWM_Init(u16 arr,u16 pre) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//使能TIM3的时钟,挂载在APB1上 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //初始化PA8 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化定时器 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分割 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数 TIM_TimeBaseInitStruct.TIM_Period = arr;//自动重装值 TIM_TimeBaseInitStruct.TIM_Prescaler = pre;//预分频 TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct); //初始化PWM设置 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//设置为 脉宽调制模式2 TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性高 TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能 TIM_OCInitStruct.TIM_Pulse = 0;//设置待装入捕获比较器的脉冲值 TIM_OC1Init(TIM1,&TIM_OCInitStruct);//初始化外设TIM1 //MOE 主输出使能 TIM_CtrlPWMOutputs(TIM1,ENABLE); //使能预装载寄存器 TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //使能TIM1在ARR上的预装载寄存器 TIM_ARRPreloadConfig(TIM1,ENABLE); //使能定时器TIM1 TIM_Cmd(TIM1,ENABLE); } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1936浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
729浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
569浏览 3评论
594浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
552浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 19:19 , Processed in 0.895739 second(s), Total 76, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号