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. Oracle数据库网闸配置注意事项

    1.数据库用户需要的权限 grant select any dictionary to coss; grant alter any procedure to coss; grant create tr ...

  2. 1、Tomcat7性能监控与优化

    1.   目的 通过优化tomcat提高网站的并发能力. 2.   服务器资源 服务器所能提供CPU.内存.硬盘的性能对处理能力有决定性影响. 3.   优化配置 3.1. 配置tomcat管理员账户 ...

  3. WndProc和hook区别

    1)WndProc函数作用:主要在程序中拦截并处理系统消息和自定义消息 比如:windows程序会产生很多消息,比如你单击鼠标,移动窗口都会产生消息.这个函数就是默认的消息处理函数.你可以重载这个函数 ...

  4. Spring.Net 未将对象引用设置到对象的实例

    “/”应用程序中的服务器错误. 未将对象引用设置到对象的实例. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详 ...

  5. docker网络模式----入门docker的难点

    众所周知,现在docker是轻量级虚拟化的典型代表!这段时间想要建立一个分布式系统,但是手头上主机没那么多,所以使用docker进行虚拟化,但是在使用的过程中对网络这一部分是一直不太理解,特别找了一篇 ...

  6. android studio 程序员有福了—从layout自动生成viewholder类

    狂点这里下载 超级牛逼的插件啊,比那些使用SparseArray的强太多了! 在android studio 1.0上测试,没有问题. 不说了直接说功能 Android Toolbox Plugin ...

  7. web安全-传输安全

    web安全-传输安全 anyproxy 代理服务器在之间可以看到 1.HTTP传输窃听 浏览器-代理服务器-链路-服务器 传输链路窃听篡改 2.HTTP窃听 >* 窃听用户密码 >* 窃听 ...

  8. jpa batch批量操作save和persist比较

    1.网上最常见的JPA----entityManager批量操作方法 private EntityManager em; @PersistenceContext(name = "Entity ...

  9. DB2安装步骤

    ##################################DB2的安装########################### ## 安装前准备 ## 关闭内存地址随机化机制 vi /etc/ ...

  10. 10.15 lzxkj

    几天前写的,忘了放了,在此填坑 10月16的题我出的不写题解了 lzxkj 题目背景 众所不周知的是, 酒店之王 xkj 一个经常迷失自我的人 有一天, 当起床铃再一次打响的时候, TA 用 O(1) ...