STM32—PWM的产生

发布者:cwk2003最新更新时间:2017-10-26 来源: eefocus关键字:STM32  PWM 手机看文章 扫描二维码
随时随地手机看文章

1. TIMER输出PWM基本概念

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。

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

 

1.1 PWM输出模式

STM32的PWM输出有两种模式,模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。模式1和模式2的区别如下:

110:PWM模式1-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。

111:PWM模式2-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为有效电平,否则为无效电平。

由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。

而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节。

 

1.2 PWM输出管脚

PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。比如说TIM3的第2个通道,在没有重映像的时候,指定的管脚是PA.7,如果设置部分重映像之后,TIM3_CH2的输出就被映射到PB.5上了,如果设置了完全重映像的话,TIM3_CH2的输出就被映射到PC.7上了。

 

1.3 PWM输出信号

PWM输出的是一个方波信号,信号的频率是由TIMx的时钟频率和TIMx_ARR预分频器所决定的,而输出信号的占空比则是由TIMx_CRRx寄存器确定的。其公式为“占空比=(TIMx_CRRx/TIMx_ARR)*100%”,因此,可以通过向CRR中填入适当的数来输出自己所需的频率和占空比的方波信号。

 

2.TIMER输出PWM实现步骤

1.设置RCC时钟;

2.设置GPIO时钟;

3.设置TIMx定时器的相关寄存器;

4.设置TIMx定时器的PWM相关寄存器。

 

第1步需要注意的是通用定时器TIMx是由APB1提供时钟,而GPIO则是由APB2提供时钟。注意,如果需要对PWM的输出进行重映像的话,还需要开启引脚复用时钟AFIO。

第2步设置GPIO时钟时,GPIO模式应该设置为复用推挽输出GPIO_Mode_AF_PP,如果需要引脚重映像的话,则需要用GPIO_PinRemapConfig()函数进行设置。

第3步设置TIMx定时器的相关寄存器。

第4步设置PWM相关寄存器,首先要设置PWM模式(默认情况下PWM是冻结的),然后设置占空比(根据前面所述公式进行计算),再设置输出比较极性:当设置为High时,输出信号不反相,当设置为Low时,输出信号反相之后再输出。最重要是是要使能TIMx的输出状态和使能TIMx的PWM输出使能。

相关设置完成之后,就可以通过TIM_Cmd()来打开TIMx定时器,从而得到PWM输出了。

 

3.TIMER输出PWM源代码

由于我现在手上的奋斗开发板是将PB.5接到LED上,因此需要使用TIM3的CH2通道,并且要进行引脚重映像。打开TIM3之后,PWM输出,使得LED点亮,通过改变PWM_cfg()中的占空比可以调节LED的亮度。

 

#include "stm32f10x_lib.h"

 

void RCC_cfg();

void GPIO_cfg();

void TIMER_cfg();

void PWM_cfg();

//占空比,取值范围为0-100

int dutyfactor = 50;

 

int main()

{

     int Temp;

       RCC_cfg();

       GPIO_cfg();

       TIMER_cfg();

       PWM_cfg();

 

       //使能TIM3计时器,开始输出PWM

       TIM_Cmd(TIM3, ENABLE);

 

       while(1);

}

 

void RCC_cfg()

{

       //定义错误状态变量

       ErrorStatus HSEStartUpStatus;

      

       //将RCC寄存器重新设置为默认值

       RCC_DeInit();

 

       //打开外部高速时钟晶振

       RCC_HSEConfig(RCC_HSE_ON);

 

       //等待外部高速时钟晶振工作

       HSEStartUpStatus = RCC_WaitForHSEStartUp();

       if(HSEStartUpStatus == SUCCESS)

       {

              //设置AHB时钟(HCLK)为系统时钟

              RCC_HCLKConfig(RCC_SYSCLK_Div1);

 

              //设置高速AHB时钟(APB2)为HCLK时钟

              RCC_PCLK2Config(RCC_HCLK_Div1);

 

              //设置低速AHB时钟(APB1)为HCLK的2分频

              RCC_PCLK1Config(RCC_HCLK_Div2);

             

              //设置FLASH代码延时

              FLASH_SetLatency(FLASH_Latency_2);

 

              //使能预取指缓存

              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

              //设置PLL时钟,为HSE的9倍频 8MHz * 9 = 72MHz

              RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

 

              //使能PLL

              RCC_PLLCmd(ENABLE);

 

              //等待PLL准备就绪

              while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

 

              //设置PLL为系统时钟源

              RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

              //判断PLL是否是系统时钟

              while(RCC_GetSYSCLKSource() != 0x08);

       }

 

       //开启TIM3的时钟

       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

       //开启GPIOB的时钟和复用功能

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);

 

}

 

void GPIO_cfg()

{

       GPIO_InitTypeDef GPIO_InitStructure;

 

      

       //部分映射,将TIM3_CH2映射到PB5

//     GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);

       GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);

 

       //选择引脚5

       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

       //输出频率最大50MHz                                                        

       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

       //复用推挽输出                                              

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 

 

       GPIO_Init(GPIOB,&GPIO_InitStructure);

}

 

void TIMER_cfg()

{

       TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

 

       //重新将Timer设置为缺省值

       TIM_DeInit(TIM3);

       //采用内部时钟给TIM3提供时钟源

       TIM_InternalClockConfig(TIM3);

       //预分频系数为0,即不进行预分频,此时TIMER的频率为72MHz

       TIM_TimeBaseStructure.TIM_Prescaler = 0;

       //设置时钟分割

       TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

       //设置计数器模式为向上计数模式

       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

       //设置计数溢出大小,每计7200个数就产生一个更新事件,即PWM的输出频率为10kHz

       TIM_TimeBaseStructure.TIM_Period = 7200 - 1;

       //将配置应用到TIM3中

       TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

}

 

void PWM_cfg()

{

       TIM_OCInitTypeDef TimOCInitStructure;

       //设置缺省值

       TIM_OCStructInit(&TimOCInitStructure);

       //PWM模式1输出

       TimOCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

       //设置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%

       TimOCInitStructure.TIM_Pulse = dutyfactor * 7200 / 100;

       //TIM输出比较极性高

       TimOCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

       //使能输出状态

       TimOCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

       //TIM3的CH2输出

       TIM_OC2Init(TIM3, &TimOCInitStructure);

       //设置TIM3的PWM输出为使能

       TIM_CtrlPWMOutputs(TIM3,ENABLE);

}


关键字:STM32  PWM 引用地址:STM32—PWM的产生

上一篇:STM32—LCD
下一篇:STM32-系统时钟

推荐阅读最新更新时间:2024-03-16 15:41

STM32的指令周期
在keil中编程时,写了一行代码,然后就想知道,执行这句C代码需要多长时间。 时钟周期在这就不解释了,频率的倒数。 指令周期,个人理解就是cpu执行一条汇编指令所需要的时间。 我们知道cm3使用的三级流水线,那么到底一条指令的执行需要多少个时钟周期。下面通过keil软件仿真,来计算一个指令所需的时钟周期。 使用STM32F103RC,。配置其主时钟HCLK为72mhz测试代码如下: 然后开始仿真 编译通过后,点击dbg按钮,调出如下窗口: 并且设置以上的断点,开始单步调试。并记录时间, 单步调试 这样便可以计算出执行 MVOS r1,#0x04 所用的时间视为29.20833-29.19
[单片机]
<font color='red'>STM32</font>的指令周期
STM32信息安全—密码学基本原理(上)
假设这样一个场景: 有一个女孩Alice,她喜欢Bob,给他发了一封信‘我喜欢你’,另一个女孩Eve想搞破坏,拦截了这封信,篡改了它,再发给Bob,改为‘我不喜欢你’ 我们可以采取什么措施实现: 交换机密/消息:除了目标接收方Bob,其他人都看不到消息的内容 保证消息的完整性:消息被Eve篡改后,Bob能识别出来 (身份)认证:Bob要确定收到的消息确实来自Alice 这就需要密码学帮忙解决。 对消息进行加密 通过加密、解密机制,可以保证交换数据的机密性 两大类加解密机制:以AES为代表的对称加密算法和以RSA/ECC椭圆曲线为代表的非对称加密算法 加解密都需要密钥参与,只是对称加密过程中,加解密使用相同的密
[单片机]
STM32再学习——实时时钟(RTC)
RTC,是RealTimeCounter的缩写。在MCU中,其实是一组连续计数的计数器,各个产品及系列各不相同。因此,在相应的软件配置下,可提供时钟日历的功能。当然,修改这个计数器的值也就重新设置了系统当前的时间和日期。 本文引用地址:http://www.eepw.com.cn/article/182407.htm RTC只是一个时钟,但与RTC相连的有两个系统时钟,一个是APB1接口的PCLK1另一个是RTC时钟 。这样,RTC功能也就分为两个部分:第一部分,APB1接口部分,与APB1总线相连,MCU也就是通过这条总线对其进行读写操作。另一部,RTC核,由一系列可编程计数器组成,这部分又再细分为两个组件:预分频模块与
[单片机]
<font color='red'>STM32</font>再学习——实时时钟(RTC)
在Mac OS X中使用VIM开发STM32(1)
在先前的博文⎣在Mac OS X中搭建STM32开发环境⎤中,我们在Mac中DIY出了最简单的交叉编译和下载环境。但是,只有交叉编译和下载环境是不够的,方便起见,我们需要一个像Keil或者IAR for ARM一样的集编辑源代码、调试与一体的开发环境。当然我们可以选择eclipse,BUT,既然都已经走到这一步了,我们为什么不来一个彻彻底底的DIY呢? 所以,我又看到了VIM这款一直以来低调奢华的编辑器,由于其跨平台的特性,我计划一劳永逸的搞定它!从此不必再纠结用什么IDE更好了,收费的、摸不着头脑的、配置纠结的都特么滚犊子,简直受够了!VIM配置好了以后,可以装进U盘带走,走到哪写到哪,你是不是也激动了?走起
[单片机]
在Mac OS X中使用VIM开发<font color='red'>STM32</font>(1)
基于STM32的平衡小车设计过程
一、简介 接触STM32开发一段时间了,想用STM32做一个有意思的项目,经历了无数的调参调参再调参,终于让它站稳了,接一下就一步步的跟大家介绍一下,项目的整体实现过程— 二、项目介绍 STM32平衡小车是一种基于STM32芯片的智能小车,它可以通过自动控制来保持平衡,使其可以在不同的地形上稳定行驶。其使用范围非常广泛。需要用到一些基本的硬件组件,例如电机、轮子、陀螺仪、加速度计、电池等。通过设计的电路板进行连接,组成一个完整的系统。 三、硬件设计 根据上述需求,我进行了电路图设计 四、软件设计 4.1电机驱动编写 4.1.1电机引脚说明 编码电机 引脚说明: M1电机电源线(12V) GND编码器地线 C
[单片机]
基于<font color='red'>STM32</font>的平衡小车设计过程
STM32】stm32f407 + DS18B20 碰出不一样的火花
前言 之前在这篇文章:【STM32学习记录4】1.44寸TFT液晶屏显示字符、汉字和图片 卖了一个关子: 开发板:stm32f407VET6 开发环境:keil5 MDK 一、硬件基础——DS18B20 1.DS18B20简介 2.硬件连接 根据手册,DS18B20的硬件接法很简单,分为以下两种: 需要注意的是不管哪一种接法DQ上一定要接个上拉电阻 1.【寄生接法】 DS18B20_GND → to→ STM32F407_GND DS18B20_VCC → to→ STM32F407_GND DS18B20_DQ → to→ STM32F407_P** DQ引脚可接任意IO口 关于寄生方式,
[单片机]
【<font color='red'>STM32</font>】stm32f407 + DS18B20 碰出不一样的火花
STM32 RTC 时钟
6.2.8 RTC 时钟 通过设置备份域控制寄存器(RCC_BDCR)里的RTCSEL 位,RTCCLK时钟源可以由 HSE/128、LSE或LSI时钟提供。除非备份域复位,此选择不能被改变。 LSE时钟在备份域里,但HSE和LSI时钟不是。因此: ● 如果LSE被选为RTC时钟: ─ 只要V BAT 维持供电,尽管V DD 供电被切断,RTC仍继续工作。 ● 如果LSI被选为自动唤醒单元(AWU)时钟: ─ 如果V DD 供电被切断, AWU状态不能被保证。有关LSI校准,详见6.2.559/754节LSI时钟。 ● 如果HSE时钟128分频后作为RTC时钟: ─ 如果V DD 供电被切断或内部电压调压器
[单片机]
<font color='red'>STM32</font> RTC 时钟
意法半导体进一步提高半导体集成规模推出达到汽车应用标准的8位微控制器系列产品
中国 , 2006 年 12 月 7 日 — 世界 领先 的车用 微控制器供应 商之一的意法半导体(纽约证券交易所代码: STM) ,今天宣布 ST7FMC 系列微控制器已经通过汽车级质量标准测试 ,达到了汽车市场特别严格的要求。 以工业标准的 8 位内核为核心,专门为无刷直流 (BLDC) 电机 设计,该系列产品适合各种车身应用,如燃油泵和水泵、冷却风扇和车厢风机。 ST7FMC 产品系列的系统集成度高于微处理器或者数字信号处理器 (DSP) 解决方案。该微控制器系列产品最大限度地减少了对外部组件的数量需求,降低了印刷电路板 (PCB
[新品]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved