0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于定时器的基础知识与基本原理及编辑代码分析

GReq_mcu168 来源:CSDN技术社区 作者:码农爱学习 2021-04-03 10:27 次阅读

单片机开发中,电机的控制与定时器有着密不可分的关系,无论是直流电机,步进电机还是舵机,都会用到定时器,比如最常用的有刷直流电机,会使用定时器产生PWM波来调节转速,通过定时器的正交编码器接口来测量转速等。

本篇先介绍定时器的基础知识,然后对照这些知识介绍一下定时器输出PWM的基本原理,以及编程实现与代码分析。

首先来看一下定时器的基础介绍。

11 定时器基础知识

1.1 定时器种类

STM32F4为例,一共有14个定时器:

高级定时器(TIM1、TIM8)

通用定时器(TIM2~TIM5,TIM9~TIM14)

TIM2~TIM5(通用定时器里功能较多的)

TIM9/TIM12

TIM10/TIM11和TIM13/TIM14

基本定时器 (TIM6、TIM7)

44e2ebb0-90fa-11eb-8b86-12bb97331649.png

1.2 各种定时器的特性

1.2.1 高级定时器与通用定时器

这里列举高级定时器的特性,在此基础上,对比添加其与通用定时器的不同之处:

16 位递增、递减、递增/递减自动重载计数器(TIM2 和 TIM5为32位)

16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数介于 1 到 65536 之间。

多达 4 个独立通道(TIM9/TIM12有2个,TIM10/TIM11,TIM13/TIM14只有1个),可用于:

输入捕获

输出比较

PWM 生成(边沿和中心对齐模式)(高级定时器和TIM2~TIM5特有,其它是只有边沿对齐模式)

单脉冲模式输出

带可编程死区的互补输出(高级定时器特有)。

使用外部信号控制定时器且可实现多个定时器互连的同步电路(TIM10/TIM11,TIM13/TIM14没有)。

重复计数器,用于仅在给定数目的计数器周期后更新定时器寄存器(高级定时器特有)。

用于将定时器的输出信号置于复位状态或已知状态的断路输入(高级定时器特有)。

发生如下事件时生成中断/DMA 请求:

更新:计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发)

触发事件(计数器启动、停止、初始化或通过内部/外部触发计数)(TIM10/TIM11和TIM13/TIM14没有此功能)

输入捕获

输出比较

断路输入(高级定时器特有)

支持定位用增量(正交)编码器和霍尔传感器电路(高级定时器和TIM2~TIM5特有)。

外部时钟触发输入或逐周期电流管理(高级定时器和TIM2~TIM5特有)。

1.2.2 基本定时器

基本定时器 (TIM6、TIM7)的功能比较单一,所具有的功能如下:

16 位自动重载递增计数器

只能定时,没有外部 IO

16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数介于 1 和 65536 之间

用于触发 DAC 的同步电路

发生如下更新事件时会生成中断/DMA 请求:计数器上溢

1.3 定时器使用配置

使用定时器,一般需要配置如下:

时基:也就是计数器的计数时钟

自动重装载值:每次计数的最大值

输出通道:当需要使用定时器输出某种波形时(如PWM)

输入通道:当需要使用定时器接收某种波形时(如电机编码器信号)

先来看一下定时器的原理框图,对定时器的内部原理有一个整体直观的感受:

453b40da-90fa-11eb-8b86-12bb97331649.png

1.3.1 时钟源

从上图可以看出,计数器的时钟源可以为:

由RCC的内部时钟分频得到

由定时器的TIMx_ETR引脚得到

由其他定时器通过TRGO输出得到

一般使用RCC的内部时钟CK_INT,也即定时器时钟TIMxCLK,经APB1或APB2预分频器后分频提供。

关于定时器时钟源的具体细节,可以来看一下STM32F4的时钟树:

45fb7698-90fa-11eb-8b86-12bb97331649.png

从STM32F4的内部时钟树可知:

高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11的时钟来源是APB2总线(84MHZ)

通用定时器timer2~timer5,通用定时器timer12~timer14以及基本定时器timer6,timer7的时钟来源是APB1总线(42MHZ)

另外:

当APB1和APB2分频数为1的时候,各定时器的时钟就是对应的APB1或APB2的时钟;

如果APB1和APB2分频数不为1,那么各定时器的时钟就是对应的APB1或APB2的时钟的2倍;

由于库函数中 APB1 预分频的系数默认是 2,所以,所以TIM1、TIM8~TIM11的时钟为APB2时钟的两倍即168MHz,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍即84MHz。

1.3.2 计数器时钟

由于定时器时钟的提供的可以频率较高,计数器不需要这么高的频率来计数,所以会进行降频,使用一个合适的低频时钟来计数。

定时器时钟经过PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟TIMxCLK 进行 1~65536 之间的任何一个数进行分频。

具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。

比如,使用STM32F4的通用定时器2(TIM2CLK为APB1的时钟的两倍即84MHz),PSC设置为83,则计数时钟为84MHz/(83+1)=1MHz,即1ms计一个数。

1.3.3 计数器

计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。

1.3.4 自动重装载寄存器

自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的,定时器就产生溢出中断。

2定时器输出PWM原理

如下图是PWM输出的原理示意图:

假设定时器工作模式设置为向上计数 PWM模式,且当 CNT《CCRx 时,输出 1,当 CNT》=CCRx 时输出 0,则:

当 CNT 值小于 CCRx 的时候, IO 输出高电平 (1)

当 CNT 值大于等于 CCRx 的时候,IO 输出低电平 (0)

当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。

因此,改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的周期(频率),这就是利用定时器输出PWM 的基本原理。

46644916-90fa-11eb-8b86-12bb97331649.png

3定时器常用的寄存器

使用定时器来输出PWM时,需要对其寄存器进行相应的设置。定时器的寄存器有好多个,这里先介绍几个与输出PWM相关的几个寄存器,其它是寄存器以后用到时再介绍。

3.1 控制寄存器CR1

控制寄存器,就是来设置定时的工作模式:

4738af58-90fa-11eb-8b86-12bb97331649.png

位 15:10 保留,必须保持复位值。

位 9:8 CKD:时钟分频 (Clock division)此位域指示定时器时钟 (CK_INT) 频率与数字滤波器所使用的采样时钟(ETR、TIx)之间的分频比,

位 7 ARPE:自动重载预装载使能 (Auto-reload preload enable)

0:TIMx_ARR 寄存器不进行缓冲

1:TIMx_ARR 寄存器进行缓冲

位 6:5 CMS:中心对齐模式选择 (Center-aligned mode selection),包括1种边沿对齐模式与3种中心对齐模式

位 4 DIR:计数器方向 (Direction),0为递增计数,1为递减计数。

注:当定时器配置为中心对齐模式或编码器模式时,该位为只读状态。

位 3 OPM:单脉冲模式 (One-pulse mode)

位 2 URS:更新请求源 (Update request source)

此位由软件置 1 和清零,用以选择 UEV 事件源。

位 1 UDIS:更新禁止 (Update disable)此位由软件置 1 和清零,用以使能/禁止 UEV 事件生成。

位 0 CEN:计数器使能 (Counter enable),0为禁止计数器,1为使能计数器

只有事先通过软件将 CEN 位置 1,才可以使用外部时钟、门控模式和编码器模式。而触发模式可通过硬件自动将 CEN 位置 1。在单脉冲模式下,当发生更新事件时会自动将 CEN 位清零。

3.2 捕获/比较模式寄存器CCMR1

这些通道可用于输入(捕获模式)或输出(比较模式)模式。通道方向通过配置相应的 CCxS 位进行定义。此寄存器的所有其它位在输入模式和输出模式下的功能均不同。对于任一给定位

OCxx 用于说明通道配置为输出时该位对应的功能

ICxx 则用于说明通道配置为输入时 该位对应的功能

因此,必须注意同一个位在输入阶段和输出阶段具有不同的含义。

47b38bec-90fa-11eb-8b86-12bb97331649.png

这里仅先介绍输出模式下的功能:

位 15 OC2CE:输出比较 2 清零使能 (Output compare 3 clear enable)

位 14:12 OC2M[2:0]:输出比较 2 模式 (Output compare 2 mode)

位 11 OC2PE:输出比较 2 预装载使能 (Output compare 2 preload enable)

位 10 OC2FE:输出比较 2 快速使能 (Output compare 2 fast enable)

位 9:8 CC2S[1:0]:捕获/比较 2 选择 (Capture/Compare 2 selection)参考下面的CC1S通道1

位 7 OC1CE:输出比较 1 清零使能 (Output compare 3 clear enable)

OC1CE:输出比较 1 清零使能 (Output Compare 1 Clear Enable)

0:OC1Ref 不受 ETRF 输入影响

1:ETRF 输入上检测到高电平时, OC1Ref 立即清零。

位 6:4 OC1M:输出比较 1 模式 (Output compare 1 mode)一共可配置位7种模式,这里仅介绍2种:

110:PWM 模式 1––在递增计数模式下,只要 TIMx_CNT《TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。在递减计数模式下,只要 TIMx_CNT》TIMx_CCR1,通道 1 便为无效状态 (OC1REF=0),否则为有效状态 (OC1REF=1)。

111:PPWM 模式 2––在递增计数模式下,只要 TIMx_CNT《TIMx_CCR1,通道 1 便为无效状态,否则为有效状态。在递减计数模式下,只要 TIMx_CNT》TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。

位 3 OC1PE:输出比较 1 预装载使能 (Output compare 1 preload enable)

0:禁止与 TIMx_CCR1 相关的预装载寄存器。可随时向 TIMx_CCR1 写入数据,写入后将立即使用新值。

1:使能与 TIMx_CCR1 相关的预装载寄存器。可读/写访问预装载寄存器。TIMx_CCR1 预装载值在每次生成更新事件时都会装载到活动寄存器中。

位 2 OC1FE:输出比较 1 快速使能 (Output compare 1 fast enable)

此位用于加快触发输入事件对 CC 输出的影响(仅当通道配置为 PWM1 或 PWM2 模式时,OCFE 才会起作用)。

0:即使触发开启,CC1 也将根据计数器和 CCR1 值正常工作。触发输入出现边沿时,激活CC1 输出的最短延迟时间为 5 个时钟周期。

1:触发输入上出现有效边沿相当于 CC1 输出上的比较匹配。随后,无论比较结果如何,OC 都设置为比较电平。采样触发输入和激活 CC1 输出的延迟时间缩短为 3 个时钟周期。

位 1:0 CC1S[1:0]:捕获/比较 1 选择 (Capture/Compare 1 selection)

此位域定义通道方向(输入/输出)以及所使用的输入。

00:CC1 通道配置为输出。

01:CC1 通道配置为输入,IC1 映射到 TI1 上。

10:CC1 通道配置为输入,IC1 映射到 TI2 上。

11:CC1 通道配置为输入,IC1 映射到 TRC 上。此模式仅在通过 TS 位(TIMx_SMCR 寄存器)选择内部触发输入时有效

注:仅当通道关闭时(TIMx_CCER 中的 CC1E = 0),才可向 CC1S 位写入数据。

3.3 计数器CNT

计数器的功能很单一,就是计数:

484442ea-90fa-11eb-8b86-12bb97331649.png

位 15:0 CNT[15:0]:计数器值 (Counter value)

3.4 预分频器PSC

预分频器的功能也很单一,就是分频:

48a09f0e-90fa-11eb-8b86-12bb97331649.png

位 15:0 PSC[15:0]:预分频器值 (Prescaler value)

计数器时钟频率 CK_CNT 等于 fCK_PSC / (PSC[15:0] + 1)。

PSC 包含在每次发生更新事件时要装载到实际预分频器寄存器的值。

3.5 自动重装载寄存器ARR

自动重装载寄存器的功能也很单一,就是保存一个数,在计数满的时候,重新开始计数

48d2c9ca-90fa-11eb-8b86-12bb97331649.png

位 15:0 ARR[15:0]:自动重载值 (Auto-reload value)

ARR 为要装载到实际自动重载寄存器的值。

当自动重载值为空时,计数器不工作。

3.6 捕获/比较寄存器CCR

自动重装载寄存器的功能也很单一,也是保存一个数,用于与当前的CNT进行比较,注意 TIM2 和 TIM5是32位计数。

49380fec-90fa-11eb-8b86-12bb97331649.png

以CCR1寄存器(一共有CCR1~CCR4这4个通道)为例:

位31:16 CCR1[31:16]:捕获/比较 1 的高 16 位(对于 TIM2 和 TIM5)。

位15:0 CCR1[15:0]:捕获/比较 1 的低 16 位 (Low Capture/Compare 1 value)

如果通道 CC1 配置为输出:CCR1 是捕获/比较寄存器 1 的预装载值。如果没有通过 TIMx_CCMR寄存器中的OC1PE 位来使能预装载功能,写入的数值会被直接传输至当前寄存器中。否则只在发生更新事件时生效(拷贝到实际起作用的捕获/ 比较寄存器1)。实际捕获/比较寄存器中包含要与计数器 TIMx_CNT进行比较并在 OC1 输出上发出信号的值。

如果通道 CC1 配置为输入:CCR1 为上一个输入捕获 1 事件 (IC1) 发生时的计数器值。

44代码实现与分析

上面介绍了定时器的基础知识与PWM的输出原理,下面就来实际看一下,如何编写对应的代码(以STM32F407为例)。

4.1 定时器初始化

定时器的初始化,因为需要用到对应的引脚输出PWM,因此要先初始化GPIO引脚,然后,还要初始化定时器的时基(计数的时钟)以及输出通道(用于配置PWM的输出模式)。

4.1.1 复用引脚初始化

这里用到的是定时器3,根据STM32F407的数据手册“3 Pinouts and pin description”中的“Table 9. Alternate function mapping”复用引脚说明表,可以看到定时器3通道1对应的引脚位A6:

499a504e-90fa-11eb-8b86-12bb97331649.png

因此程序中对A6引脚可以这样配置,注意一定要配置引脚的复用功能:

GPIO_InitTypeDef GPIO_InitStructure; /*引脚配置 结构体*/

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3); /*GPIOA6复用为定时器3*/

/*复用引脚配置*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //GPIOA6GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /*复用功能*/GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA6

4.1.2 时基初始化

时基初始化,主要是配置定时器的计数频率(psc)和自动重装置值(每次计数的周期,arr),比如TIM3_PWM_Init(500-1,84-1);

(关于psc与arr的知识点,可以再回顾一下上面1.3节的知识)

这里将arr的值设置为500,即计数器每计够500个数就会重新从0开始计数,这个500再乘以计数器计数的周期,就是PWM真正的周期,那计数器计数的频率是多少呢(频率的倒数为周期)?

这里将psc的值设置为84-1,即TIM3的输入频率为84MHz再将频率降低1/84,即使用1MHz的频率计数(1s能计1,000,000个数,也即1us计1个数),那么PWM的真正周期就是500*1us=500us(0.5ms),通过改变占空比的值(ccr),就可以调节PWM的输出占空比。

4a1a81c4-90fa-11eb-8b86-12bb97331649.png

时基初始化配置如下:

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /*时基 结构体*/

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //TIM3时钟使能

/*时基初始化*/TIM_TimeBaseStructure.TIM_Period=arr; /*ARR 自动重装载值(周期),例如500*/TIM_TimeBaseStructure.TIM_Prescaler=psc; /*PSC 定时器分频,例如84*/TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; /*时钟分割*/TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /*向上计数模式*/TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); /*初始化定时器3*/

最后一句的时基初始化,起始就是对定时的寄存器进行配置,该函数的内部实现如下:

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct){ uint16_t tmpcr1 = 0; tmpcr1 = TIMx-》CR1;

if((TIMx == TIM1) || (TIMx == TIM8)|| /*高级定时器TIM和TIM8*/ (TIMx == TIM2) || (TIMx == TIM3)||(TIMx == TIM4) || (TIMx == TIM5)) /*通用定时器中的TIM2~TIM5*/ { /* 设置为计数器模式 */ tmpcr1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS)); tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct-》TIM_CounterMode; } if((TIMx != TIM6) && (TIMx != TIM7)) /*基本定时器TIM6和TIM7无此功能*/ { /* 设置时钟分频 */ tmpcr1 &= (uint16_t)(~TIM_CR1_CKD); tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct-》TIM_ClockDivision; }

/* 配置CR1寄存器 */ TIMx-》CR1 = tmpcr1;

/* 配置ARR寄存器,设置自动重转载值 */ TIMx-》ARR = TIM_TimeBaseInitStruct-》TIM_Period ; /* 配置PSC寄存器,设置预分频值 */ TIMx-》PSC = TIM_TimeBaseInitStruct-》TIM_Prescaler; if ((TIMx == TIM1) || (TIMx == TIM8)) /*高级定时器TIM和TIM8*/ { /* 配置RCR寄存器,设置重复计数值 */ TIMx-》RCR = TIM_TimeBaseInitStruct-》TIM_RepetitionCounter; }

/* 生成一个更新事件来立即重新加载预分频器和重复计数器(仅针对高级定时器TIM1和TIM8)值 */ TIMx-》EGR = TIM_PSCReloadMode_Immediate; }

4.1.3 输出通道初始化

输出通道初始化,主要是配置输出的一些参数,这里主要关注TIM_OCMode(模式)与TIM_OCPolarity(极性),这两个参数是配合使用的:

PWM模式1

向上计数时,一旦TIMx_CNT《TIMx_CCR1时通道1为有效电平,否则为无效电平;

向下计数时,一旦TIMx_CNT》TIMx_CCR1时通道1为无效电平,否则为有效电平。

PWM模式2

向上计数时,一旦TIMx_CNT《TIMx_CCR1时通道1为无效电平,否则为有效电平;

向下计数时,一旦TIMx_CNT》TIMx_CCR1时通道1为有效电平,否则为无效电平。

这里的有效电平又是什么意思呢?怎么算有效电平?它就是通过极性来配置的:

输出High模式:有效电平为高电平

输出Low模式:有效电平为低电平

对比着再来看这张图:

当CNT的计数值小于CCR时,即t1这个时间段,输出有效电平(TIM_OCMode_PWM1模式),而有效电平是高电平(极性为TIM_OCPolarity_High),所以PWM的IO逻辑在t1这个时间段输出了高电平。

46644916-90fa-11eb-8b86-12bb97331649.png

输出通道的配置如下:

TIM_OCInitTypeDef TIM_OCInitStructure; /*输出通道 结构体*//*输出通道初始化,初始化TIM3 Channel1 PWM模式*/ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; /*选择定时器模式:TIM脉冲宽度调制模式1*/TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; /*输出极性:TIM输出比较极性高*/TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根据指定的参数初始化外设TIM3 OC1

TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); /*使能TIM3在CCR1上的预装载寄存器*/TIM_ARRPreloadConfig(TIM3,ENABLE);/*ARPE使能:使能控制寄存器CR的第8位:ARPR, Auto-reload preload enable*/TIM_Cmd(TIM3, ENABLE); /*使能TIM3:使能控制寄存器CR的第0位:CEN, counter enable*/

关于配置CCMR1、CCER寄存器

CCMR1:

47b38bec-90fa-11eb-8b86-12bb97331649.png

CCER:

4afd0ecc-90fa-11eb-8b86-12bb97331649.png

TIM_OC1Init函数对应于输入通道的初始化,其实就是操作CCMR1、CCER等寄存器:

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct){ uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; TIMx-》CCER &= (uint16_t)~TIM_CCER_CC1E;/* 关闭通道1: 复位CC1E位 */ tmpccer = TIMx-》CCER;/* 获取 TIMx CCER 寄存器的值 */ tmpcr2 = TIMx-》CR2; /* 获取 TIMx CR2 寄存器的值 */

tmpccmrx = TIMx-》CCMR1;/* 获取TIMx CCMR1 寄存器的值 */ tmpccmrx &= (uint16_t)~TIM_CCMR1_OC1M; /* 复位输出比较模式OC1M位 */ tmpccmrx &= (uint16_t)~TIM_CCMR1_CC1S; tmpccmrx |= TIM_OCInitStruct-》TIM_OCMode;/* 设置为输出比较模式 */ tmpccer &= (uint16_t)~TIM_CCER_CC1P; /* 复位输出极性CC1P */ tmpccer |= TIM_OCInitStruct-》TIM_OCPolarity; /* 设置输出极性 */ tmpccer |= TIM_OCInitStruct-》TIM_OutputState; /* 设置输出状态 */ if((TIMx == TIM1) || (TIMx == TIM8)) /*高级定时器的特殊配置*/ { //省略。。。 } TIMx-》CR2 = tmpcr2; /* 写数据到TIMx的CR2寄存器 */ TIMx-》CCMR1 = tmpccmrx; /* 写数据到TIMx的CCMR1寄存器 */ TIMx-》CCR1 = TIM_OCInitStruct-》TIM_Pulse;/* 设置CCR1寄存器 */ TIMx-》CCER = tmpccer; /* 写数据到TIMx的CCER寄存器 */}

4.2 动态改变占空比

占空比是通过修改CCR寄存器的值进行修改的,如果定时器初始化时只设置了1次CCR的值,那么会输出恒定占空比的PWM波;如果在定时器运行的时候,动态修改CCR的值,则可以实现PWM占空比的动态调整。

如下程序,实现了每隔10ms对占空比进行一次修改,每次将高电平计数值增加5,当增大道500(占空比100%)时,再逐渐减小到0(占空比0%),不断循环。

u16 led0pwmval=0; u8 dir=1;TIM3_PWM_Init(500-1,84-1); //84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz. while(1) //实现比较值从0-500递增,到500后从500-0递减,循环{ delay_ms(10);

if(dir) { led0pwmval+=5; //dir==1 led0pwmval递增 } else { led0pwmval-=5; //dir==0 led0pwmval递减 } if(led0pwmval》500) { dir=0; //led0pwmval到达500后,方向为递减 } if(led0pwmval==0) { dir=1; //led0pwmval递减到0后,方向改为递增 }

TIM_SetCompare1(TIM3,led0pwmval); /*CCR 修改比较值(占空比)*/}

5 测试效果

将程序下载到板子,我用的一块STM32F407的板,A6引脚上接了一个LED灯,实际效果的LED逐渐变亮,再逐渐变暗,依次循环。

再通过逻辑分析仪来查看实际的输出波形,如下图,测得的pwm周期0.5ms(频率2kHz),与软件中设定的一致。

在某一时刻,脉宽55us。

4bc52bdc-90fa-11eb-8b86-12bb97331649.png

在另一时刻,脉宽0.365ms,即实现了PWM脉宽的动态调整。

4bcd1982-90fa-11eb-8b86-12bb97331649.png

编辑:lyn

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 电机控制
    +关注

    关注

    3523

    文章

    1851

    浏览量

    268267
  • 定时器
    +关注

    关注

    23

    文章

    3235

    浏览量

    114385
  • 代码
    +关注

    关注

    30

    文章

    4733

    浏览量

    68282
收藏 人收藏

    评论

    相关推荐

    定时器的工作方式介绍

    定时器是计算机和嵌入式系统中常见的一种硬件模块,用于实现定时和计数功能。定时器的工作方式通常由一组寄存来控制,这些寄存定义了
    的头像 发表于 07-12 10:29 681次阅读

    定时器相关的寄存有哪些类型

    在微控制编程中,定时器是一种非常常见的功能模块,用于实现各种定时和计数功能。定时器的工作原理是通过内部的计数来跟踪时间的流逝,当计数
    的头像 发表于 07-12 10:25 720次阅读

    鸿蒙开发系统基础能力:Timer定时器

    设置一个定时器,该定时器定时器到期后执行一个函数。
    的头像 发表于 06-28 11:33 835次阅读
    鸿蒙开发系统基础能力:Timer<b class='flag-5'>定时器</b>

    如何实现一个软件定时器

    在Linux,uC/OS,FreeRTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件
    的头像 发表于 04-29 11:00 575次阅读

    s7200定时器的五种故障介绍

    定时器或CPU故障:如果定时器本身或PLC的CPU出现故障,也可能导致定时器无法复位。此时,需要检查定时器和CPU的工作状态,确保其正常运行。
    的头像 发表于 04-03 17:08 2140次阅读

    ​PLC定时器介绍

    定时器是PLC中重要的编程元件,是累计时间增量的内部器件。大部分自动控制领域都需要定时器进行延时控制,灵活地使用定时器可以编制出复杂的控制程序。
    发表于 03-22 12:36 2143次阅读
    ​PLC<b class='flag-5'>定时器</b>介绍

    使用555定时器的可调双定时器电路

    定时器 IC 555 是最通用和最常用的 IC 之一,因为它的应用范围更广,如 PWM放大器、延迟定时器、开关电路、占空比选择、时钟脉冲发生等。这也可用于各种应用,如精确
    的头像 发表于 02-25 15:16 1971次阅读
    使用555<b class='flag-5'>定时器</b>的可调双<b class='flag-5'>定时器</b>电路

    定时器原理能控制马达吗为什么

    定时控制。 定时器的工作原理是基于内部的振荡电路,通过稳定的时钟信号来触发或计时特定的事件。常见的定时器电路有555定时器和微控制中的
    的头像 发表于 01-23 15:21 596次阅读

    555定时器的基本功能 555定时器的工作原理及其应用

    555定时器是一种非常常见和常用的集成电路,它具有广泛的应用领域,例如计时、频率分频、脉冲宽度调制等。本文将详细介绍555定时器的基本功能、工作原理以及应用。 一、555定时器的基本功能 555
    的头像 发表于 01-18 11:12 1.4w次阅读

    浪涌抑制基本原理和种类?

    浪涌抑制基本原理和种类?|深圳比创达电子
    的头像 发表于 01-18 09:59 811次阅读
    浪涌抑制<b class='flag-5'>器</b>的<b class='flag-5'>基本原理</b>和种类?

    AWTK 开源串口屏开发(6) - 定时器的用法

    定时器是个常用的功能,AWTK串口屏提供了丰富的定时器函数,用于定时器的启动、停止、暂停、恢复、修改和重置等功能,本文以计时的例子来介绍定时器
    的头像 发表于 01-13 08:24 528次阅读
    AWTK 开源串口屏开发(6) - <b class='flag-5'>定时器</b>的用法

    单片机定时器的用法

    本章以CW32通用定时器为例介绍单片机定时器的用法。
    的头像 发表于 01-04 10:37 1333次阅读
    单片机<b class='flag-5'>定时器</b>的用法

    51单片机定时器定时1秒程序流水灯结果分析

    流水灯的设计原理、实现步骤和结果分析。 一、设计原理 在51单片机中,定时器常用的工作方式有两种:定时器模式和计数模式。定时器模式是指
    的头像 发表于 12-26 14:57 6455次阅读

    定时器会阻塞线程吗 定时器指令有哪几种

    定时器会阻塞线程吗 定时器指令有哪几种  定时器一般不会阻塞线程,但具体是否会阻塞取决于所使用的定时器实现方式和使用方式。 定时器指令可以分
    的头像 发表于 12-19 14:03 874次阅读

    间歇定时器怎么使用?定时器时间间隔程序浅析

    间歇定时器的作用是重复执行一个函数,且不会阻塞主线程。这种类型的定时器常用于间隔性地自动执行代码,例如网页中的倒计时。
    的头像 发表于 12-14 15:16 1275次阅读