【STM32】STM32之timer3产生PWM

来源:互联网 发布:apache显示目录列表 编辑:程序博客网 时间:2024/06/06 03:42

本篇博文最后修改时间: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”)

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //******************************************************************************                              
  2. //name:             GUA_Timer3_PWM.c                 
  3. //introduce:        定时器3的PWM驱动          
  4. //author:           甜甜的大香瓜                       
  5. //email:            897503845@qq.com           
  6. //QQ group          香瓜单片机之STM8/STM32(164311667)                        
  7. //changetime:       2017.01.14        
  8. //******************************************************************************      
  9. #include "stm32f10x.h"   
  10. #include "GUA_Timer3_PWM.h"    
  11.     
  12. /*********************宏定义************************/      
  13. //引脚宏    
  14. #define GUA_TIMER3_PWM_PORT             GPIOB    
  15. #define GUA_TIMER3_PWM_PIN              GPIO_Pin_0    
  16. #define GUA_TIMER3_PWM_MODE             GPIO_Mode_AF_PP   
  17. #define GUA_TIMER3_PWM_GPIO_CLOCK               RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO   
  18. #define GUA_TIMER3_PWM_PERIPH_CLOCK         RCC_APB1Periph_TIM3    
  19.   
  20. //计数值    
  21. #define GUA_TIMER3_PWM_PERIOD                       (72 - 1)    
  22.   
  23. /*********************内部函数声明************************/     
  24. static void GUA_Timer3_PWM_IO_Init(void);  
  25. static void GUA_Timer3_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);  
  26.   
  27. //******************************************************************************                
  28. //name:             GUA_Timer3_PWM_IO_Init               
  29. //introduce:        定时器3的PWM的IO初始化             
  30. //parameter:        none                     
  31. //return:           none             
  32. //author:           甜甜的大香瓜                     
  33. //email:            897503845@qq.com         
  34. //QQ group          香瓜单片机之STM8/STM32(164311667)                      
  35. //changetime:       2017.01.14                          
  36. //******************************************************************************    
  37. static void GUA_Timer3_PWM_IO_Init(void)    
  38. {        
  39.     //IO结构体    
  40.     GPIO_InitTypeDef GPIO_InitStructure;    
  41.   
  42.     //时钟配置   
  43.     RCC_APB2PeriphClockCmd(GUA_TIMER3_PWM_GPIO_CLOCK, ENABLE);    
  44.   
  45.     //IO初始化  
  46.     GPIO_InitStructure.GPIO_Pin = GUA_TIMER3_PWM_PIN;  
  47.     GPIO_InitStructure.GPIO_Mode = GUA_TIMER3_PWM_MODE;  
  48.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  49.     GPIO_Init(GUA_TIMER3_PWM_PORT, &GPIO_InitStructure);                  
  50. }  
  51.   
  52. //******************************************************************************                
  53. //name:             GUA_Timer3_PWM_Config_Init               
  54. //introduce:        定时器3的PWM的配置初始化             
  55. //parameter:        nGUA_Timer3_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz   
  56. //return:           none             
  57. //author:           甜甜的大香瓜                     
  58. //email:            897503845@qq.com         
  59. //QQ group          香瓜单片机之STM8/STM32(164311667)                      
  60. //changetime:       2017.01.14                          
  61. //******************************************************************************    
  62. static void GUA_Timer3_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)    
  63. {        
  64.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;    
  65.     TIM_OCInitTypeDef  TIM_OCInitStructure;    
  66.     
  67.     //时钟配置  
  68.     RCC_APB1PeriphClockCmd(GUA_TIMER3_PWM_PERIPH_CLOCK, ENABLE);    
  69.       
  70.     //定时器配置  
  71.     TIM_TimeBaseStructure.TIM_Period = GUA_TIMER3_PWM_PERIOD;                               //设置计数值    
  72.     TIM_TimeBaseStructure.TIM_Prescaler = nGUA_Timer3_PWM_Prescaler - 1;        //设置预分频   
  73.     TIM_TimeBaseStructure.TIM_ClockDivision = 0;                                                        //设置时钟分频系数:不分频    
  74.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;                         //向上计数溢出模式    
  75.     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);    
  76.       
  77.     //PWM配置  
  78.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                                               //配置为PWM模式1(小于计数值时为有效电平)    
  79.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;                       //比较输出使能                  
  80.     TIM_OCInitStructure.TIM_Pulse = 0;                                                                          //设置待装入捕获比较寄存器的脉冲值    
  81.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;                                //有效电平为低电平    
  82.     TIM_OC3Init(TIM3, &TIM_OCInitStructure);                                                                //使能通道3        
  83.   
  84.     //默认关闭PWM         
  85.     GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);     
  86.       
  87.     //使能      
  88.     TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);                                               //CH3预装载使能    
  89.     TIM_ARRPreloadConfig(TIM3, ENABLE);                                                                         //使能TIM3重载寄存器ARR      
  90.     TIM_Cmd(TIM3, ENABLE);                                                                                                  //使能定时器3    
  91. }  
  92.   
  93. //******************************************************************************            
  94. //name:             GUA_Timer3_PWM_Status            
  95. //introduce:        定时器3的PWM开关        
  96. //parameter:        nGUA_Timer3_PWM_Status: GUA_TIMER3_PWM_STATUS_ON or GUA_TIMER3_PWM_STATUS_OFF          
  97. //return:           none          
  98. //author:           甜甜的大香瓜                 
  99. //email:            897503845@qq.com                    
  100. //QQ group          香瓜单片机之STM8/STM32(164311667)                        
  101. //changetime:       2017.01.14                          
  102. //******************************************************************************      
  103. void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status)    
  104. {    
  105.   //打开PWM    
  106.   if(nGUA_Timer3_PWM_Status == GUA_TIMER3_PWM_STATUS_ON)    
  107.   {     
  108.         TIM_SetCounter(TIM3, 0);          
  109.         TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Enable);          
  110.   }    
  111.   //关闭PWM  
  112.   else    
  113.   {    
  114.         TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Disable);                 
  115.   }    
  116. }    
  117.     
  118. //******************************************************************************            
  119. //name:             GUA_Timer3_PWM_SetDutyCycle            
  120. //introduce:        定时器3的PWM设置占空比        
  121. //parameter:        nGUA_Timer3_PWM_DutyCycle: 0~100为0%~100%          
  122. //return:           none          
  123. //author:           甜甜的大香瓜                 
  124. //email:            897503845@qq.com                    
  125. //QQ group          香瓜单片机之STM8/STM32(164311667)                        
  126. //changetime:       2017.01.14                           
  127. //******************************************************************************      
  128. void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle)    
  129. {    
  130.   TIM_SetCompare3(TIM3, GUA_TIMER3_PWM_PERIOD*nGUA_Timer3_PWM_DutyCycle/100);     
  131. }    
  132.     
  133. //******************************************************************************            
  134. //name:             GUA_Timer3_PWM_Init            
  135. //introduce:        定时器3的PWM初始化         
  136. //parameter:        nGUA_Timer3_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz          
  137. //return:           none          
  138. //author:           甜甜的大香瓜                 
  139. //email:            897503845@qq.com                    
  140. //QQ group          香瓜单片机之STM8/STM32(164311667)                        
  141. //changetime:       2017.01.14                           
  142. //******************************************************************************      
  143. void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)     
  144. {     
  145.     //初始化IO    
  146.     GUA_Timer3_PWM_IO_Init();    
  147.   
  148.     //初始化定时器配置   
  149.     GUA_Timer3_PWM_Config_Init(nGUA_Timer3_PWM_Prescaler);  
  150. }    
初始化后PWM默认是关闭的。

2)编写驱动头文件GUA_Timer3_PWM.h(存放在“……\HARDWARE”)
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //******************************************************************************                              
  2. //name:             GUA_Timer3_PWM.h                 
  3. //introduce:        定时器3的PWM驱动的头文件          
  4. //author:           甜甜的大香瓜                       
  5. //email:            897503845@qq.com           
  6. //QQ group          香瓜单片机之STM8/STM32(164311667)                        
  7. //changetime:       2017.01.14        
  8. //******************************************************************************      
  9. #ifndef _GUA_TIMER3_PWM_H_    
  10. #define _GUA_TIMER3_PWM_H_    
  11.      
  12. /*********************宏定义************************/  
  13. //类型宏  
  14. #ifndef GUA_U8          
  15. typedef unsigned char GUA_U8;          
  16. #endif      
  17.   
  18. #ifndef GUA_8          
  19. typedef signed char GUA_8;          
  20. #endif        
  21.         
  22. #ifndef GUA_U16          
  23. typedef unsigned short GUA_U16;          
  24. #endif   
  25.   
  26. #ifndef GUA_16          
  27. typedef signed short GUA_16;          
  28. #endif           
  29.         
  30. #ifndef GUA_U32          
  31. typedef unsigned long GUA_U32;          
  32. #endif   
  33.   
  34. #ifndef GUA_32          
  35. typedef signed long GUA_32;         
  36. #endif  
  37.   
  38. #ifndef GUA_U64      
  39. typedef unsigned long long GUA_U64;    
  40. #endif  
  41.   
  42. #ifndef GUA_64      
  43. typedef signed long long GUA_64;    
  44. #endif  
  45.   
  46. //PWM的开关宏    
  47. #define GUA_TIMER3_PWM_STATUS_ON                0       //PWM打开    
  48. #define GUA_TIMER3_PWM_STATUS_OFF               1       //PWM关闭    
  49.   
  50. /*********************外部函数声明************************/     
  51. void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status);    
  52. void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle);    
  53. void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);    
  54.     
  55. #endif    

3)工程中添加GUA_Timer3_PWM.c


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


2、添加库的驱动

1)添加库的驱动文件



2)添加库的驱动头文件(stm32f10x_conf.h 中)
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "stm32f10x_tim.h"  

3、在应用层中调用

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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "GUA_Timer3_PWM.h"  

2)添加测试代码(main.c的main函数中)
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. GUA_Timer3_PWM_Init(26);                                                    //设置PWM频率为1000000/26=38000Hz=38KHz  
  2. GUA_Timer3_PWM_SetDutyCycle(50);                                    //设置PWM占空比为50%  
  3. GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);    //使能PWM   
  4.   
  5. GUA_Timer3_PWM_SetDutyCycle(30);                                    //设置PWM占空比为30%    
  6. GUA_Timer3_PWM_SetDutyCycle(60);                                    //设置PWM占空比为60%    
  7. GUA_Timer3_PWM_SetDutyCycle(0);                                     //设置PWM占空比为0%    
  8. GUA_Timer3_PWM_SetDutyCycle(100);                                   //设置PWM占空比为100%       
  9.   
  10. GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);   //停止PWM       
  11. GUA_Timer3_PWM_SetDutyCycle(50);                                    //设置PWM占空比为50%  
  12. 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%。

因此,实验成功。