stm32 PWM输出学习
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);//初始化TIM3TIM_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) = 1msTIM_SetCompare2(TIM3,300); //脉宽= 300/1000 *1ms = 0.3mswhile(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.3msTIM3_PWM_Init(999,71); //72/(71+1)=1MHz, T=1us*(999+1) = 1mswhile(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输出学习相关推荐
- STM32 PWM输出之TIM_SetCompare函数的应用
STM32 PWM输出之TIM_SetCompare函数的应用 想必输出PWM大家都应该会了吧,但是如何更加灵活方便的使用PWM,可能大家还存在着问题,今天我给大家介绍一下TIM_SetCompare ...
- 【学习记录】 STM32 PWM输出实验
STM32 PWM工作过程 以通道1为例: CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值. CCMR1: OC1M[2:0]位: 对于PWM方式下,用于设置PWM模式1[110]或 ...
- STM32 PWM输出实验总结
本实验是基于STM32 407的板子,使用的是通用定时器TIM14,相关的博文其实有很多,本文主要是基于他们结合个人学习理解总结整理,并非完全原创,只希望能帮助更好理解PWM输出的过程尤其是TIM_A ...
- STM32 PWM输出(映射)
STM32 的定时器除了 TIM6 和 7.其他的定时器都可以用来产生 PWM 输出.其中高级定 时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.而通用定时器也能同时产生多达 ...
- STM32 PWM输出实验
定时器用来产生PWM输出: STM32 的定时器除了 TIM6 和 7.其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.而通 ...
- STM32 PWM输出原理和直流电机PWM驱动原理详解及例程
这次讲一讲STM32输出PWM的原理以及PWM可以作为信号传输数据的原理. PWM会有很多地方用到,有控制灯的亮度,控制电机,控制舵机或者其他一些外设,有时候你的单片机所输出的PWM是作为信号去控制, ...
- STM32学习笔记(五 定时器及应用 3 PWM输出实验 )
一.PWM 简介 脉冲宽度调制(PWM) Pulse Width Modulation (调制) 简单来说就是对脉冲宽度的控制. 高级定时器 TIM1 和 TIM8: 可以同时产生多达 7 路的 PW ...
- STM32学习之PWM输出
PWM: Pluse Width Modulation 的缩写,称作脉冲宽度调制,是利用CPU的数字输出来对模拟电路的一种控制,即通过对脉冲宽度的控制. 接下来随笔者看几个概念: PWM的周期:即频率 ...
- STM32学习笔记—PWM输出
1.pwm输出介绍 2.函数配置 3.源码 1.pwm输出介绍 脉冲调制(pwm),其根本原理就是通过控制占空比来控制输出.STM32的定时器除了TIM6和7之外都可以产生pwm输出,其中高级定时器1 ...
最新文章
- php最常见代码,PHP常见算法合集代码实例
- python找最大值的函数_Python 获取最大值函数
- laravel 中添加自定义辅助函数helpers.php
- 有没有通过代码退出程序的方法--官方解答
- 【转】C++中的字符串(String)和数值转换
- NSArray与NSSet的区别
- arm linux samba,嵌入式linux系统教你制作samba服务器
- Oracle11新特性——初始化文件管理
- matlab简介,Matlab简介及各历史版本
- Java 生成条形码 订单条形码
- 他 25 岁进贝尔实验室,32 岁提信息论,40 岁办达特茅斯会议,晚年患上阿兹海默 | 人物志...
- 乐鑫esp8266学习rtos3.0笔记第3篇: 一篇文章带你搞掂存储技术 NVS 的认识和使用,如何利用NVS保存整型、字符串、数组以及结构体。(附带demo)
- 【K8S实战】-超详细教程(三)
- DNS服务器未响应是什么意思
- 导出word单元格间隔空白问题
- SVN使用教程(一)
- 机器人瓦力有什么西方的风格_机器人瓦力中英文对照影评
- struts上传word和excel文件到oracle,Struts文件上传,下载,重传,预览
- vue2+vue3小白零基础教程—vue2篇,全网2021最详细教程
- created不能异步_详解vue中async-await的使用误区
热门文章
- hdu 4556 Stern-Brocot Tree
- JAVA中JPasswordField实现密码的确认
- BZOJ 1412 [ZJOI2009]狼和羊的故事(最小割)
- asp.net怎样解决高并发问题
- C语言中的位域 bit field [转]
- 做毕设时遇到的一些问题,以及一些小技巧
- WPF开发中遇到的问题及解决系列(一):How can I programmatically click a Button
- runat=server
- 使用tensorflow出现 ImportError: DLL load failed: 找不到指定的程序
- 编程方法学7:循环与一半