本篇博文最后修改时间: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”)
-
-
-
-
-
-
-
-
- #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_CLOCK RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO
- #define GUA_TIMER3_PWM_PERIPH_CLOCK RCC_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);
-
-
-
-
-
-
-
-
-
-
-
- static void GUA_Timer3_PWM_IO_Init(void)
- {
-
- GPIO_InitTypeDef GPIO_InitStructure;
-
-
- RCC_APB2PeriphClockCmd(GUA_TIMER3_PWM_GPIO_CLOCK, ENABLE);
-
-
- 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);
- }
-
-
-
-
-
-
-
-
-
-
-
- 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);
-
-
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = 0;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
- TIM_OC3Init(TIM3, &TIM_OCInitStructure);
-
-
- GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);
-
-
- TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
- TIM_ARRPreloadConfig(TIM3, ENABLE);
- TIM_Cmd(TIM3, ENABLE);
- }
-
-
-
-
-
-
-
-
-
-
-
- void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status)
- {
-
- if(nGUA_Timer3_PWM_Status == GUA_TIMER3_PWM_STATUS_ON)
- {
- TIM_SetCounter(TIM3, 0);
- TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Enable);
- }
-
- else
- {
- TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Disable);
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle)
- {
- TIM_SetCompare3(TIM3, GUA_TIMER3_PWM_PERIOD*nGUA_Timer3_PWM_DutyCycle/100);
- }
-
-
-
-
-
-
-
-
-
-
-
- void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)
- {
-
- GUA_Timer3_PWM_IO_Init();
-
-
- GUA_Timer3_PWM_Config_Init(nGUA_Timer3_PWM_Prescaler);
- }
初始化后PWM默认是关闭的。
2)编写驱动头文件GUA_Timer3_PWM.h(存放在“……\HARDWARE”)
-
-
-
-
-
-
-
-
- #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
-
-
- #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);
- GUA_Timer3_PWM_SetDutyCycle(50);
- GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);
-
- GUA_Timer3_PWM_SetDutyCycle(30);
- GUA_Timer3_PWM_SetDutyCycle(60);
- GUA_Timer3_PWM_SetDutyCycle(0);
- GUA_Timer3_PWM_SetDutyCycle(100);
-
- GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);
- GUA_Timer3_PWM_SetDutyCycle(50);
- GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);
七、注意事项
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%。
因此,实验成功。