【STM32】STM32之timer3产生PWM

来源:互联网 发布:mysql employees 导入 编辑:程序博客网 时间:2024/06/01 10:39

本篇博文最后修改时间:2017年01月14日,23:50。


一、简介

本文介绍STM32系列如何使用timer3的第3通道(PB0)产生38K频率的PWM。


二、实验平台

库版本:STM32F10x_StdPeriph_Lib_V3.5.0

编译软件:MDK4.53

硬件平台:STM32开发板(主芯片stm32f103c8t6)

仿真器:JLINK


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:897503845@qq.com

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、实验前提
1、在进行本文步骤前,请先阅读以下博文:

2、在进行本文步骤前,请先实现以下博文:
暂无


五、基础知识

暂无

六、实验步骤

1、编写并添加PWM驱动

1)编写驱动GUA_Timer3_PWM.c(存放在“……\HARDWARE”)

//******************************************************************************                            //name:             GUA_Timer3_PWM.c               //introduce:        定时器3的PWM驱动        //author:           甜甜的大香瓜                     //email:            897503845@qq.com         //QQ group          香瓜单片机之STM8/STM32(164311667)                      //changetime:       2017.01.14      //******************************************************************************    #include "stm32f10x.h" #include "GUA_Timer3_PWM.h"    /*********************宏定义************************/    //引脚宏  #define GUA_TIMER3_PWM_PORT             GPIOB  #define GUA_TIMER3_PWM_PIN              GPIO_Pin_0  #define GUA_TIMER3_PWM_MODE             GPIO_Mode_AF_PP #define GUA_TIMER3_PWM_GPIO_CLOCKRCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO #define GUA_TIMER3_PWM_PERIPH_CLOCKRCC_APB1Periph_TIM3  //计数值  #define GUA_TIMER3_PWM_PERIOD(72 - 1)  /*********************内部函数声明************************/   static void GUA_Timer3_PWM_IO_Init(void);static void GUA_Timer3_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);//******************************************************************************              //name:             GUA_Timer3_PWM_IO_Init             //introduce:        定时器3的PWM的IO初始化           //parameter:        none                   //return:           none           //author:           甜甜的大香瓜                   //email:            897503845@qq.com       //QQ group          香瓜单片机之STM8/STM32(164311667)                    //changetime:       2017.01.14                        //******************************************************************************  static void GUA_Timer3_PWM_IO_Init(void)  {      //IO结构体  GPIO_InitTypeDef GPIO_InitStructure;  //时钟配置 RCC_APB2PeriphClockCmd(GUA_TIMER3_PWM_GPIO_CLOCK, ENABLE);//IO初始化GPIO_InitStructure.GPIO_Pin = GUA_TIMER3_PWM_PIN;GPIO_InitStructure.GPIO_Mode = GUA_TIMER3_PWM_MODE;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GUA_TIMER3_PWM_PORT, &GPIO_InitStructure);}//******************************************************************************              //name:             GUA_Timer3_PWM_Config_Init             //introduce:        定时器3的PWM的配置初始化           //parameter:        nGUA_Timer3_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz //return:           none           //author:           甜甜的大香瓜                   //email:            897503845@qq.com       //QQ group          香瓜单片机之STM8/STM32(164311667)                    //changetime:       2017.01.14                        //******************************************************************************  static void GUA_Timer3_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)  {      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  TIM_OCInitTypeDef  TIM_OCInitStructure;    //时钟配置RCC_APB1PeriphClockCmd(GUA_TIMER3_PWM_PERIPH_CLOCK, ENABLE);  //定时器配置TIM_TimeBaseStructure.TIM_Period = GUA_TIMER3_PWM_PERIOD;//设置计数值  TIM_TimeBaseStructure.TIM_Prescaler = nGUA_Timer3_PWM_Prescaler - 1;//设置预分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0;//设置时钟分频系数:不分频  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数溢出模式  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  //PWM配置TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//配置为PWM模式1(小于计数值时为有效电平)  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能                TIM_OCInitStructure.TIM_Pulse = 0;//设置待装入捕获比较寄存器的脉冲值  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//有效电平为低电平  TIM_OC3Init(TIM3, &TIM_OCInitStructure);//使能通道3      //默认关闭PWMGUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);//使能TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);//CH3预装载使能  TIM_ARRPreloadConfig(TIM3, ENABLE);//使能TIM3重载寄存器ARR  TIM_Cmd(TIM3, ENABLE);//使能定时器3  }//******************************************************************************          //name:             GUA_Timer3_PWM_Status          //introduce:        定时器3的PWM开关      //parameter:        nGUA_Timer3_PWM_Status: GUA_TIMER3_PWM_STATUS_ON or GUA_TIMER3_PWM_STATUS_OFF        //return:           none        //author:           甜甜的大香瓜               //email:            897503845@qq.com                  //QQ group          香瓜单片机之STM8/STM32(164311667)                      //changetime:       2017.01.14                        //******************************************************************************    void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status)  {    //打开PWM    if(nGUA_Timer3_PWM_Status == GUA_TIMER3_PWM_STATUS_ON)    {   TIM_SetCounter(TIM3, 0);TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Enable);  }    //关闭PWM  else    {  TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Disable);   }  }    //******************************************************************************          //name:             GUA_Timer3_PWM_SetDutyCycle          //introduce:        定时器3的PWM设置占空比      //parameter:        nGUA_Timer3_PWM_DutyCycle: 0~100为0%~100%        //return:           none        //author:           甜甜的大香瓜               //email:            897503845@qq.com                  //QQ group          香瓜单片机之STM8/STM32(164311667)                      //changetime:       2017.01.14                         //******************************************************************************    void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle)  {    TIM_SetCompare3(TIM3, GUA_TIMER3_PWM_PERIOD*nGUA_Timer3_PWM_DutyCycle/100);   }    //******************************************************************************          //name:             GUA_Timer3_PWM_Init          //introduce:        定时器3的PWM初始化       //parameter:        nGUA_Timer3_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz        //return:           none        //author:           甜甜的大香瓜               //email:            897503845@qq.com                  //QQ group          香瓜单片机之STM8/STM32(164311667)                      //changetime:       2017.01.14                         //******************************************************************************    void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)   {  //初始化IO  GUA_Timer3_PWM_IO_Init();  //初始化定时器配置 GUA_Timer3_PWM_Config_Init(nGUA_Timer3_PWM_Prescaler);}  
初始化后PWM默认是关闭的。

2)编写驱动头文件GUA_Timer3_PWM.h(存放在“……\HARDWARE”)
//******************************************************************************                            //name:             GUA_Timer3_PWM.h               //introduce:        定时器3的PWM驱动的头文件        //author:           甜甜的大香瓜                     //email:            897503845@qq.com         //QQ group          香瓜单片机之STM8/STM32(164311667)                      //changetime:       2017.01.14      //******************************************************************************    #ifndef _GUA_TIMER3_PWM_H_  #define _GUA_TIMER3_PWM_H_     /*********************宏定义************************///类型宏#ifndef GUA_U8        typedef unsigned char GUA_U8;        #endif    #ifndef GUA_8        typedef signed char GUA_8;        #endif            #ifndef GUA_U16        typedef unsigned short GUA_U16;        #endif #ifndef GUA_16        typedef signed short GUA_16;        #endif               #ifndef GUA_U32        typedef unsigned long GUA_U32;        #endif #ifndef GUA_32        typedef signed long GUA_32;       #endif#ifndef GUA_U64    typedef unsigned long long GUA_U64;  #endif#ifndef GUA_64    typedef signed long long GUA_64;  #endif//PWM的开关宏  #define GUA_TIMER3_PWM_STATUS_ON                0       //PWM打开  #define GUA_TIMER3_PWM_STATUS_OFF               1       //PWM关闭  /*********************外部函数声明************************/   void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status);  void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle);  void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);    #endif  

3)工程中添加GUA_Timer3_PWM.c


4)在MDK设置中添加驱动源文件路径


2、添加库的驱动

1)添加库的驱动文件



2)添加库的驱动头文件(stm32f10x_conf.h 中)
#include "stm32f10x_tim.h"

3、在应用层中调用

1)添加驱动头文件(main.c中)

#include "GUA_Timer3_PWM.h"

2)添加测试代码(main.c的main函数中)
GUA_Timer3_PWM_Init(26);//设置PWM频率为1000000/26=38000Hz=38KHzGUA_Timer3_PWM_SetDutyCycle(50);//设置PWM占空比为50%GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);//使能PWMGUA_Timer3_PWM_SetDutyCycle(30);//设置PWM占空比为30%  GUA_Timer3_PWM_SetDutyCycle(60);//设置PWM占空比为60%  GUA_Timer3_PWM_SetDutyCycle(0);//设置PWM占空比为0%  GUA_Timer3_PWM_SetDutyCycle(100);//设置PWM占空比为100% GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);//停止PWMGUA_Timer3_PWM_SetDutyCycle(50);//设置PWM占空比为50%GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);//使能PWM

七、注意事项
1、在初始化PWM的配置之后,需要调用使能PWM的函数才会有PWM的波形。
2、PWM会有死区。

八、实验结果
设置仿真断点在测试代码,仿真并全速运行至断点,单步执行测试代码后的PB0波形如下图:
1、使能PWM

初始化时设置了26us的周期,启动PWM前设置了50%的占空比。因此使能PWM之后直接输出了波形。
低电平13us、高电平13us、一个周期26us,因此占空比为13/26=50%。

2、设置30%占空比

低电平7.75us、高电平18.25us、一个周期26us,因此占空比为7.75/26=29.8%。

3、设置60%占空比

低电平15.75us、高电平10.25us、一个周期26us,因此占空比为15.75/26=60.6%。

4、设置0%占空比

0%时一直为高电平。

5、设置100%占空比


100%时可见低电平有许多0.25us的毛刺脉冲,这是PWM的死区
0~100%的占空比中一定会有一个死区,解决死区脉冲的方法:在死区时配置为IO置位为相应的电平。
PS:香瓜在本PWM驱动中没有解决此问题,因为项目中只使用到50%的占空比。

6、关闭PWM

关闭PWM后,在代码中有设置为IO拉高,因此抓到的波形为高电平。

7、设置50%占空比+使能PWM

再次使能PWM之前,先配置了50%的占空比。
低电平13us、高电平13us、一个周期26us,因此占空比为13/26=50%。

因此,实验成功。

1 0