基于stm32f103zet6的定时器的学习3(定时器产生4路PWM)

发布者:钱老李最新更新时间:2017-09-07 来源: eefocus关键字:stm32f103zet6  定时器  PWM 手机看文章 扫描二维码
随时随地手机看文章

定时器TIM3产生四路PWM波输出。

首先介绍一下PWM吧,算是给自己充电,脉冲宽度调制(PWM),是英文“Pulse Width Modulation ”的缩写,简称脉宽调制,是利用
微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。

一、这个程序的主函数相当简单:


  1. /*******由于没有做外设测试的程序是:按键PA0仅一个LED灯******/  

  2. /*******由于没有做外设测试的程序是:串口采用的是PA9->(T<->T),PA9->(R<->R)*****/  

  3. #include "stm32f10x.h"      

  4. #include "LED.h"  

  5. #include "SysTick.h"  

  6. #include "Delay.h"  

  7. #include "Usart.h"  

  8. #include "stdio.h"  

  9. #include "Timer3.h"  

  10.   

  11. volatile u32 time; // ms 计时变量  

  12.   

  13. int main(void)  

  14. {  

  15.     //初初始化GPIO  

  16.     LED_GPIO_Config();  

  17.     //初始化系统定时器  

  18.     SysTick_Init();  

  19.     USART1_Config();  

  20.   

  21.     printf("\r\n ("__DATE__ " - " __TIME__ ") \r\n");  

  22.     /* TIM3 PWM波输出初始化,并使能TIM3 PWM输出 */  

  23.     TIM3_PWM_Init();  

  24.     while(1);  

  25. }  

  26.   

呵呵,看到这样的函数是最爽的了,但是有得必有失,你在主函数里面少了的操作,你在子函数里面也别想跑掉可怜


二、着重来分析这个PWM的初始化函数了。

1、配置GPIO这个是少不了的!看代码,能够明白了


  1. static void TIM3_GPIO_Config(void)   

  2. {  

  3.   GPIO_InitTypeDef GPIO_InitStructure;  

  4.   

  5.     /* TIM3 clock enable */  

  6.     //PCLK1经过2倍频后作为TIM3的时钟源等于36MHz  

  7.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);   

  8.   

  9.   /* GPIOA and GPIOB clock enable */  

  10.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);   

  11.   

  12.   /*GPIOA Configuration: TIM3 channel 1 and 2 as alternate function push-pull */  

  13.   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;  

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

  15.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

  16.   

  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);  

  18.   

  19.   /*GPIOB Configuration: TIM3 channel 3 and 4 as alternate function push-pull */  

  20.   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1;  

  21.   

  22.   GPIO_Init(GPIOB, &GPIO_InitStructure);  

  23. }  

  24.   


2、重点是接下来的TIM3_Mode_Config这个配置函数,先上代码,然后一步步分析吧!


  1. /* 

  2.  * 函数名:TIM3_Mode_Config 

  3.  * 描述  :配置TIM3输出的PWM信号的模式,如周期、极性、占空比 

  4.  * 输入  :无 

  5.  * 输出  :无 

  6.  * 调用  :内部调用 

  7.  */  

  8. static void TIM3_Mode_Config(void)  

  9. {  

  10.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  

  11.     TIM_OCInitTypeDef  TIM_OCInitStructure;  

  12.   

  13.     /* PWM信号电平跳变值 */  

  14.     u16 CCR1_Val = 500;          

  15.     u16 CCR2_Val = 375;  

  16.     u16 CCR3_Val = 250;  

  17.     u16 CCR4_Val = 125;  

  18.   

  19. /* ----------------------------------------------------------------------- 

  20.     TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles: 

  21.     TIM3CLK = 36 MHz, Prescaler = 0x0, TIM3 counter clock = 36 MHz 

  22.     TIM3 ARR Register = 999 => TIM3 Frequency = TIM3 counter clock/(ARR + 1) 

  23.     TIM3 Frequency = 36 KHz. 

  24.     TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50% 

  25.     TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5% 

  26.     TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25% 

  27.     TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5% 

  28.   ----------------------------------------------------------------------- */  

  29.   

  30.   /* Time base configuration */        

  31.   TIM_TimeBaseStructure.TIM_Period = 999;       //当定时器从0计数到999,即为1000次,为一个定时周期  

  32.   TIM_TimeBaseStructure.TIM_Prescaler = 0;      //设置预分频:不预分频,即为36MHz  

  33.   TIM_TimeBaseStructure.TIM_ClockDivision = 0;  //设置时钟分频系数:不分频  

  34.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式  

  35.   

  36.   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  

  37.   

  38.   /* PWM1 Mode configuration: Channel1 */  

  39.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;     //配置为PWM模式1  

  40.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   

  41.   TIM_OCInitStructure.TIM_Pulse = CCR1_Val;    //设置跳变值,当计数器计数到这个值时,电平发生跳变  

  42.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于CCR1_Val时为高电平  

  43.   

  44.   TIM_OC1Init(TIM3, &TIM_OCInitStructure);   //使能通道1  

  45.   

  46.   TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  

  47.   

  48.   /* PWM1 Mode configuration: Channel2 */  

  49.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  

  50.   TIM_OCInitStructure.TIM_Pulse = CCR2_Val;   //设置通道2的电平跳变值,输出另外一个占空比的PWM  

  51.   

  52.   TIM_OC2Init(TIM3, &TIM_OCInitStructure);    //使能通道2  

  53.   

  54.   TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  

  55.   

  56.   /* PWM1 Mode configuration: Channel3 */  

  57.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  

  58.   TIM_OCInitStructure.TIM_Pulse = CCR3_Val; //设置通道3的电平跳变值,输出另外一个占空比的PWM  

  59.   

  60.   TIM_OC3Init(TIM3, &TIM_OCInitStructure);   //使能通道3  

  61.   

  62.   TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  

  63.   

  64.   /* PWM1 Mode configuration: Channel4 */  

  65.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  

  66.   TIM_OCInitStructure.TIM_Pulse = CCR4_Val; //设置通道4的电平跳变值,输出另外一个占空比的PWM  

  67.   

  68.   TIM_OC4Init(TIM3, &TIM_OCInitStructure);  //使能通道4  

  69.   

  70.   TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  

  71.   

  72.   TIM_ARRPreloadConfig(TIM3, ENABLE);            // 使能TIM3重载寄存器ARR  

  73.   

  74.   /* TIM3 enable counter */  

  75.   TIM_Cmd(TIM3, ENABLE);                   //使能定时器3   

  76. }  

  77.   

开始分析吧!


4、 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

定义了这样一个结构体,跟踪进去!成员是这几个


  1. uint16_t  TIM_ClockDivision   

  2. uint16_t  TIM_CounterMode   

  3. uint16_t  TIM_Period   

  4. uint16_t  TIM_Prescaler   

  5. uint8_t  TIM_RepetitionCounter   

  6.   

这就是上一博文跟踪到的结构体,还来分析,吃多了没事干!


继续,下一个!

5、 TIM_OCInitTypeDef  TIM_OCInitStructure;

这个结构体可是没有见过的!

它的成员有


  1. uint16_t  TIM_OCIdleState   

  2. uint16_t  TIM_OCMode   

  3. uint16_t  TIM_OCNIdleState   

  4. uint16_t  TIM_OCNPolarity   

  5. uint16_t  TIM_OCPolarity   

  6. uint16_t  TIM_OutputNState   

  7. uint16_t  TIM_OutputState   

  8. uint16_t  TIM_Pulse   

  9.   


a、TIM_OCIdleState这个成员的描述如下


Specifies the TIM Output Compare pin state during Idle state,指定的TIM在空闲状态的时候,输出比较引脚的状态,这个可以先不管,在高级定时器中使用到


  1. #define  TIM_OCIdleState_Reset   ((uint16_t)0x0000)   

  2. #define  TIM_OCIdleState_Set   ((uint16_t)0x0100)   


  1.   

  2.   

b、TIM_OCMode描述如下


指定定时器的模式 ,它的取值可以是

?

  1. #define  TIM_OCMode_Active   ((uint16_t)0x0010)   

  2. #define  TIM_OCMode_Inactive   ((uint16_t)0x0020)   

  3. #define  TIM_OCMode_PWM1   ((uint16_t)0x0060)   

  4. #define  TIM_OCMode_PWM2   ((uint16_t)0x0070)   

  5. #define  TIM_OCMode_Timing   ((uint16_t)0x0000)   

  6. #define  TIM_OCMode_Toggle   ((uint16_t)0x0030)   


  1.   

这里选择的是PWM1模式

c、接下来我们继续看下一个结构体成员吧。TIM_OCNIdleState


Specifies the TIM Output Compare pin state during Idle state,它的取值可以是


  1. #define  TIM_OCIdleState_Reset   ((uint16_t)0x0000)   

  2. #define  TIM_OCIdleState_Set     ((uint16_t)0x0100)   

这里似乎和b是一样的,也可以不管,在高级定时器中使用到

d、下一个成员是TIM_OCNPolarity描述如下


Specifies the complementary output polarity可以取得值是


  1. #define     TIM_OCNPolarity_High   ((uint16_t)0x0000)  

  2. #define     TIM_OCNPolarity_Low   ((uint16_t)0x0008)  

它是用来指定的 互补 输出极性的,在高级定时器中使用到


e、下一个成员是TIM_OCPolarity描述如下


Specifies the complementary output polarity可以取得值是



  1. #define     TIM_OCPolarity_High   ((uint16_t)0x0000)  

  2. #define     TIM_OCPolarity_Low   ((uint16_t)0x0008)  

它是用来指定的极性的。


f、TIM_OutputNState描述如下


Specifies the TIM complementary Output Compare state取值如下


  1. #define     TIM_OutputNState_Disable   ((uint16_t)0x0000)  

  2. #define     TIM_OutputNState_Enable   ((uint16_t)0x0004)  

输出互补使能?注意是互补使能?这里暂时 不用,在高级定时器中使用到
g、TIM_OutputState描述如下


Specifies the TIM Output Compare state取值如下


  1. #define  TIM_OutputState_Disable   ((uint16_t)0x0000)   

  2. #define  TIM_OutputState_Enable   ((uint16_t)0x0001)   


  1.   

这里才是输出使能。当然要使能!

h、TIM_Pulse描述如下

Specifies the pulse value to be loaded into the Capture Compare Register. This parameter can be a number between 0x0000 and 0xFFFF 

指定的脉冲值被装入到捕捉比较寄存器。这个参数可以是0x0000和0xFFFF之间的一个数,简单理解为初值吧!

三、成员分析完毕,还有两个比较重要的初始化配置函数


  1. TIM_OC1Init(TIM3, &TIM_OCInitStructure);                                        //使能通道1  

  2. TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  


第一个函数自然是使能通道了,具体来看看函数定义吧!有兴趣的可以跟踪进去瞅瞅


第二个函数就是Enables or disables the TIMx peripheral Preload register on CCR1使能预装在寄存器!

  TIM_OC1Init(TIM3, &TIM_OCInitStructure);你使用sourceinsight工具,进行代码跟踪的话,就能知道句话的作用就是:

开启TIMx_CCR1寄存器的预装载功能,读写操作仅对预装载寄存器操作,TIMx_CCR1的预装载值在更新事件到来时被加载至当前寄存器中。我的理解是:也就是当我们计数溢出的时候

才更新我们的预装值!有两个要注意点的地方

注1 :一旦LOCK 级别设为3(TIMx_BDTR寄存器中的LOCK 位) 并且CC1S=00( 该通道配置成输
出)则该位不能被修改。 
注2:仅在单脉冲模式下(TIMx_CR1寄存器的OPM=1),可以在未确认预装载寄存器情况下使用
PWM模式,否则其动作不确定。 

如果还想继续深入研究的话建议参考那本datasheet吧!不深入讨论了!

软件仿真效果图如下!


手上有示波器,但是一下难以观察到4个通道,所以就懒得演示了,管脚引出来接到对应的LED上面,也能看到亮度不同!至此 PWM基本知识就学到这里!

还有最后两个函数没解释的!

TIM_OC1PreloadConfig(),TIM_ARRPreloadConfig();这两个函数控制的是ccr1和arr的预装在使能,使能和失能的区别就是:使能的时候这两个局存期的读写需要等待有更新事件发生时才能被改变(比如计数溢出就是更新时间)。失能的时候可以直接进行读写而没有延迟。


关键字:stm32f103zet6  定时器  PWM 引用地址:基于stm32f103zet6的定时器的学习3(定时器产生4路PWM)

上一篇:基于stm32f103zet6之红外遥控解码的学习
下一篇:基于stm32f103zet6的定时器的学习2(定时器上溢)

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

飞兆半导体增强型重启定时器
随着技术的发展,消费者越来越多地利用便携设备处理业务和私人事务。由于这些便携设备中构建了众多的基础架构系统,拥有能够快速解决系统锁死的简单方案是至关重要的。飞兆半导体公司(Fairchild Semiconductor)新近扩展重启定时器产品系列,能够为便携设备锁死问题提供更好的解决方案。 重启定时器在按钮/按键按下和系统重启之间提供了延迟,从而防止了无意重启。新的重启定时器系列经设计具有用于重启便携设备的多种延迟时间,以及同时提供固定和可选延迟、单按钮或双按钮重启,还有固定或可变重启脉冲宽度的产品选项。 FT7522和FT10001重启定时器分别具有7.5和10秒的固定延迟,并具有用于单按钮重启的输入。FT3001则提供设计
[手机便携]
一种新颖的ZVZCS PWM全桥变换器
摘要:提出了一种新颖的零电流零电压开关(ZCZVS)PWM全桥变换器,通过增加一个辅助电路的方法实现了变换器的软开关。与以往的ZCZVSPWM全桥变换器相比,所提出的新颖变换器具有电路结构简单、整机效率高以及电流环自适应调整等优点,这使得它特别适合高压大功率的应用场合。详细分析了该变换器的工作原理及电路设计,并在一台功率为4kW,工作频率为80kHz的通信用开关电源装置上得到了实验验证。 关键词:全桥变换器;零电压开关;零电流开关;软开关;脉宽调制 引言 移相全桥零电压PWM软开关(PSFBZVS)变换器与移相全桥零电压零电流PWM软开关(PSFBZVZCS)变换器是目前国内外电源界研究的热门课题,并已得到了广泛的
[电源管理]
51单片机入门经验分享9-定时器模拟实现PWM呼吸灯效果
众所周知,PWM的应用是及其广泛的,现在很多高速的单片机内部都集成了硬件PWM,使用起来也很简单,配置好频率和装入计数值就可以工作了,但是在一些低成本的场合,我们选择的单片机没有硬件PWM功能模块,但是我们还存在这个需求怎么办呢?这个时候,我们需要用PWM来模拟实现他,但实现PWM必须要了解PWM的原理,这里我们先了解下。 PWM全称是脉冲宽度调制解调,比如1个小灯,按照500MS亮一次,500MS灭一次,周期是1S,频率是1HZ,在这里,1个周期说明白了就是2个方波,有高电平和低电平组成,在周期固定的情况下,我们通过不断的调整高电平所占的整个周期比例,即所谓的占空比,就可以实现小灯”不是那么亮“的效果,如果连续起来,就可以实
[单片机]
51单片机入门经验分享9-<font color='red'>定时器</font>模拟实现<font color='red'>PWM</font>呼吸灯效果
Cortex-M3 (NXP LPC1788)之SysTick系统节拍定时器
在GPIO控制篇中的延时闪烁LED只用了简单的for循环,为了精确的计时本篇介绍使用SysTick定时器每1ms产生中断,从而实现精确定时的目的。要使用系统节拍定时器主要进行两个部分的配置。1:系统时钟控制。2系统节拍定时器的控制。 一,系统时钟控制 LPC1788有3个独立的振荡器。他们是主振荡器,内部RC振荡器,RTC振荡器。复位后,LPC1788将用内部的RC振荡器运行,直到被软件切换。这样就能在没有任何外部晶振的情况下运行。LPC1788的时钟控制如图1所示 在开发板上使用12M的晶振作为主振荡器,它通过锁相环PLL0来提高频率提供CPU。由于芯片总是从内部的RC振荡器开始工作,因此主振荡器
[单片机]
Cortex-M3 (NXP LPC1788)之SysTick系统节拍<font color='red'>定时器</font>
STM8S003F3 内部时钟初始化以及定时器做延时的使用
STM8S003F3 内部晶振初始化代码如下: CLK_DeInit(); CLK_LSICmd(ENABLE); CLK_HSICmd(ENABLE); while(SET != CLK_GetFlagStatus(CLK_FLAG_HSIRDY)); CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1); CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //HSI = 16M (1分频) 这里我使用timer4来做例子,代码如下: //延时10us (2分频=8M 计数80个脉冲) TIM4_TimeBaseInit(TIM4
[单片机]
基于stm32f103zet6的串口学习
进行串口配置的步骤 一、初始化GPIO,配置GPIO模式 一个结构体 GPIO_InitTypeDef{ GPIOMode_TypeDef GPIO_Mode//GPIO模式,输入,输出? uint16_t GPIO_Pin //哪个管脚? GPIOSpeed_TypeDef GPIO_Speed//输出响应速度?如果为输入则可以不设置 } //GPIO_Mode包括以下几种方式 Enumerator: 枚举类型 GPIO_Mode_AIN //模拟输入 GPIO_Mode_IN_FLOATING //悬浮输入 GPIO_Mode_IPD //下拉输入 GPIO_Mode_IPU //上拉输入 GPIO_Mode_Out_
[单片机]
51单片机定时器中断控制灯1S亮的程序
#include AT89X51.H unsigned char i=0,j=0; void main() { TMOD=0X01; TH0=0X4c; TL0=0X00; TR0=1; ET0=1; EA=1; P0_3=1; while(1) {}; } timer0() interrupt 1 { TR0=0; TH0=0X4c;//5000us TL0=0X00; i++; if(i =20) { i==0; j++; if(j =20) { j=0; P0_3= ~P0_3; } } TR0=1; } //注意此处必须用两个变量i,否则程序不会通过。
[单片机]
基于单片机的直流电机控制PWM调速代码
(PWM)脉冲宽度调制 脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。 所谓PWM,就是脉冲宽度调制技术,其具有两个很重要的参数:频率和占空比。频率,就是周期的倒数;占空比,就是高电平在一个周期内所占的比例。 本次使用了电机驱动模块是L298N 实物图如下,改模
[单片机]
基于单片机的直流电机控制<font color='red'>PWM</font>调速代码
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • Linux内核移植
    实验步骤:(1)准备工作(2)修改顶层Makefile(3)修改falsh 分区(4)配置编译内核下面以Linux2 6 30 4内核移植到gec2440为例:一、准备 ...
  • S5PV210 PWM定时器
    第一节 S5PV210的PWM定时器S5PV210共有5个32bit的PWM定时器,其中定时器0、1、2、3有PWM功能,定时器4没有输出引脚。PWM定时器使用PCLK_PS ...
  • S5PV210 NAND Flash
    NAND Flash关于NAND FlashS5PV210的NAND Flash控制器有如下特点:1) 支持512byte,2k,4k,8k的页大小2) 通过各种软件模式来进行NAND Fl ...
  • S5PV210串口
    串口设置之输入输出字符S5PV210 UART相关说明 通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER,它用来 ...
  • S5PV210按键控制LED
    原理图如图所示:查询用户手册得到:程序例子:(完整代码见“代码下载链接”)1、轮询的方式查询按键事件 *main c* 核心代码如下:while(1 ...
  • S5PV210控制蜂鸣器
  • S5PV210的启动过程
  • S5PV210点亮LED
  • S5PV210启动过程详解
何立民专栏 单片机及嵌入式宝典

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

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