STM32 的定时器除了 TIM6 和 7,其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。通用定时器也能同时产生多达 4路的 PWM 输出。

今天的实验,我们仅利用 TIM3的 CH2 通道产生一路 PWM 输出。

1.相关寄存器介绍

1)捕获/比较模式寄存器 (TIMx_CCMR1/2)

捕获/比较模式寄存器(TIMx_CCMR1/2),该寄存器总共有 2 个,TIMx  _CCMR1和 TIMx _CCMR2。TIMx_CCMR1 控制 CH1 和 CH2,而 TIMx_CCMR2 控制 CH3 和 CH4。

OCxx描述了通道在输出模式下的功能(上行),ICxx描述了通道在输出模式下的功能(下行)。因此必须注意,同一个位在输出模式和输入模式下的功能是不同的。

这里我们需要说明的是模式设置位 OCxM,此部分由 3 位组成。总共可以配置成 7 种模式,我们使用的是 PWM 模式,所以这 3 位必须设置为 110/111。这两种PWM 模式的区别就是输出电平的极性相反。

这里的有效电平或者无效电平是可以配置的。

2) 捕获/比较使能寄存器(TIMx_CCER)

3)捕获/比较寄存器(TIMx_CCR1~4)

该寄存器总共有 4 个,对应 4 个通道 CH1~CH4。因为这 4 个寄存器都差不多,我们仅以 TIMx_CCR1 为例介绍。

我们通过修改这个寄存器的值,就可以控制 PWM 的输出脉宽。

2. TIM3_REMAP 重映射

我们要利用 TIM3 的 CH2 输出 PWM 来控制 LED的亮度,但是 TIM3_CH2 默认是接在 PA7上面的,而我们的 LED接在 PB5 上面,如果是普通 MCU,可能就只能用飞线把 PA7 飞到 PB5上;不过,我们用的是 STM32,可以通过重映射功能,把 TIM3_CH2映射到 PB5 上。

3.代码难点分析

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

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  

//使能GPIOB时钟(PB5连接LED)和AFIO复用功能时钟

为什么要使能RCC_APB2Periph_AFIO呢?

参考手册上说:

对寄存器AFIO_EVCR(事件控制寄存器),AFIO_MAPR( 复用重映射和调试I/O配置寄存器),AFIO_EXTICRX(外部中断配置寄存器)进行读写操作前,应当首先打开AFIO的时钟。

因为我们在这个实验中用到了AFIO_MAPR,所以要打开AFIO时钟。

2)GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射,TIM3_CH2->PB5

3)GPIO配置

//设置该引脚为复用输出功能,输出TIM3-CH2的PWM波形

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; 

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //推挽复用输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

4)TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

可以参考捕获/比较使能寄存器(TIMx_CCER)位0, 输出使能。

5)TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

可以参考捕获/比较使能寄存器(TIMx_CCER)位1, 高/低 电平有效。

6)TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); 预装载使能

可以参考捕获/比较模式寄存器 (TIMx_CCMR1/2) 位3.

7)TIM_SetCompare2(TIM3,300);

参考捕获/比较寄存器(TIMx_CCR1~4),这里设置比较值为300.

4. 代码参考

//PWM输出初始化函数
//arr:自动重装载值
//psc: 预分频系数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
//使能GPIOB时钟(PB5连接LED)和AFIO复用功能时钟 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射,TIM3_CH2->PB5 //设置该引脚为复用输出功能,输出TIM3-CH2的PWM波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化TIM3
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler = psc;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //TIM3 Channel2 PWM 初始化
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM2模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //捕获/比较使能寄存器(TIMx_CCER) 输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //预装载使能 TIM_Cmd(TIM3, ENABLE); //开启TIM3 }

main函数如下

int main(void)
{ TIM3_PWM_Init(999,71); //72/(71+1)=1MHz, T=1us*(999+1) = 1ms
TIM_SetCompare2(TIM3,300); //脉宽= 300/1000 *1ms = 0.3ms
while(1)
{
;
}
}

仿真说明:我们的代码设置为:

PWM2模式,向上计数,高电平有效。

所以,TIMx_CNT<TIMx_CCRx时通道x为低,否则为高。

5.仿真效果图如下

6. 疑问

如果调换main函数两句的顺序,则无法达到预期效果。

<span style="font-size:18px;">int main(void) //实验失败
{
TIM_SetCompare2(TIM3,300); //脉宽= 300/1000 *1ms = 0.3ms
TIM3_PWM_Init(999,71); //72/(71+1)=1MHz, T=1us*(999+1) = 1ms while(1)
{
;
}
}</span>

至于原因,这里不讨论,留待以后思考。

7. 用PWM控制LED的亮度

int main(void)
{
u16 led0pwmval = 0; //比较值
u8 dir = 1;
delay_init(); TIM3_PWM_Init(899,0); while(1)
{
delay_ms(10); if(dir)
led0pwmval++;
else
led0pwmval--; if(led0pwmval>300)
dir=0;
if(led0pwmval==0)
dir=1; TIM_SetCompare2(TIM3,led0pwmval);
}
}

这里,我们将 led0pwmval 这个值设置为 PWM 比较值,也就是通过 led0pwmval 来控制 PWM 的占空比,进而控制LED的平均电流,达到控制LED亮度的目的。

led0pwmval 的值从 0 变到 301,然后又从 301 变到 0,如此循环,LED的亮度也会跟着从暗变到亮,然后又从亮变到暗。至于这里的值,我们为什么取 300,是因为 PWM 的输出占空比达到并且超过这个值的时候, LED 亮度变化就不明显了。

stm32 PWM输出学习的更多相关文章

  1. STM32 PWM输出(映射)

    STM32 的定时器除了 TIM6 和 7.其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.而通用定时器也能同时产生多达 4 ...

  2. STM32 HAL库学习系列第4篇 定时器TIM----- 开始定时器与PWM输出配置

    基本流程: 1.配置定时器 2.开启定时器 3.动态改变pwm输出,改变值  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); 函数总结: __HAL_TIM ...

  3. stm32寄存器版学习笔记05 PWM

    STM32除TIM6和TIM7外都可以产生PWM输出.高级定时器TIM1和TIM8可以同时产生7路PWM,通用定时器可以产生4路PWM输出. 1.TIM1 CH1输出PWM配置步骤 ①开启TIM1时钟 ...

  4. STM32(7)——通用定时器PWM输出

    1.TIMER输出PWM基本概念         脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种 ...

  5. Arduino学习经验(一)之解决舵机库和pwm输出冲突

    一.前言 最近在公司学习Arduino uno ,用它实现小车超声波避障功能.实现的功能很简单,就是在小车前方挂一个超声波模块,当碰到障碍物时,会通过舵机进行摆头,判断两边的距离,进行左右转弯.但是碰 ...

  6. STM32 PWM的输出与Keil软件仿真

    导读:PWM(Pulse Width Modulation)控制——脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值). PWM控制技术在逆变电路中应用最广,应用 ...

  7. STM32 精确输出PWM脉冲数控制电机(转)

    STM32 精确输出PWM脉冲数控制电机 发脉冲两种目的1)速度控制2)位置控制 速度控制目的和模拟量一样,没有什么需要关注的地方发送脉冲方式为PWM,速率稳定而且资源占用少 stm32位置控制需要获 ...

  8. STM32—TIMx输出PWM信号驱动MG996R舵机

    文章目录 一.前言 二.MG996R舵机简介 三.TIM定时器简介 四.通用定时器TIMx 1.TIMx主要功能 2.TIMx框图 3.计数单元 4.时钟选择 5.输出比较PWM 五.TIM3输出双路 ...

  9. (stm32f103学习总结)—stm32 PMW输出实验

    一.PWM简介 PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制.它是利用微处理器的数字输出来对模拟电路进行控 制的一种非常有效的技术,其控制简 ...

随机推荐

  1. drools规则引擎笔记(二)

    规则引擎版本,drools6.5.0 final eclipse:Neon JDK1.8 今天主要是在规则的when部分加入了多个fact对象. 对于working memory存在多个fact的情形 ...

  2. 整理的C#屏幕截图,控件截图程序

    代码基本从网上搜集而来,整理成以下文件: 包括屏幕截图(和屏幕上看到的一致): 以及控件截图(只要该控件在本窗口内显示完全且不被其他控件遮挡就可正确截图) using System; using Sy ...

  3. Linux基础学习(二)

    前言: 我们在上一节了解了一下linux的硬件组成,虽然也许对具体的东西还不甚了解,但是我们知道了linux下一切皆文件这一特性 我们装好了CentOS7的虚拟机(这个可以看别人教程来装起来,比较简单 ...

  4. 降临(线段树优化dp)

    降临 选定点i会有代价\(c_i\),如果一个区间j内的点全被选择,就可以获得回报\(p_j\).点数和区间个数\(<1e5\). 还以为是线段树优化网络流(50万个点200万条边看上去很可做的 ...

  5. loj #2024. 「JLOI / SHOI2016」侦查守卫

    #2024. 「JLOI / SHOI2016」侦查守卫   题目描述 小 R 和 B 神正在玩一款游戏.这款游戏的地图由 nnn 个点和 n−1n - 1n−1 条无向边组成,每条无向边连接两个点, ...

  6. web flash推流录制测试研究

    用flash as3写了一段推流测试demo,参考srs_publisher和simplest_as3_rtmp_streamer.推流到srs2服务器,录制为flv文件.测试一轮结果如下: Web ...

  7. 牛客寒假算法基础集训营4 C Applese 走迷宫

    链接:https://ac.nowcoder.com/acm/contest/330/C来源:牛客网 精通程序设计的 Applese 双写了一个游戏. 在这个游戏中,它被困在了一个 n×m迷宫 在迷宫 ...

  8. springboot整合xxl-mq学习笔记

    首先xxl-mq是大神xuxueli开发的一个消息中间件框架: 与springboot整合过程: <?xml version="1.0" encoding="UTF ...

  9. Step by Step: 基于MFC下的COM组件开发-Helloworld

    http://blog.csdn.net/sybifei/article/details/45008745 [这篇文章有问题, 仅供参考] http://blog.csdn.net/define_us ...

  10. POJ-2112 Optimal Milking(floyd+最大流+二分)

    题目大意: 有k个挤奶器,在牧场里有c头奶牛,每个挤奶器可以满足m个奶牛,奶牛和挤奶器都可以看成是实体,现在给出两个实体之间的距离,如果没有路径相连,则为0,现在问你在所有方案里面,这c头奶牛需要走的 ...