1、 PWM 是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调制,简称脉宽调制。
它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式,
其应用领域包括测量,通信,功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此研究基于 PWM 技术的正负脉宽数控调制信号发生器具有十分重要的现实意义。
2、PWM 是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用, 方波的占空比被调制用来对一个具体模拟信号的电平进行编码。
PWM 信号仍然是数字的, 因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。
电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。
通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。
3、STM32的定时器除了TIM6和7。其他的定时器都可以用来产生PWM输出。
其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。
而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出!
4、STM32 的PWM是TIMx_ARR寄存器确定频率(周期)、由TIMx_CCRx寄存器确定占空比的信号
5、PWM 模式
脉冲宽度调制模式可以产生一个由 TIM1_ARR 寄存器确定频率、由TIM1_CCRx寄存器确定占空比的信号。在 TIM1_CCMRx寄存器中的OCxM位写入“110”(PWM 模式 1)或“111”(PWM 模式 2),
能够独立地设置每个通道工作在 PWM模式,每个 OCx 输出一路 PWM。必须通过设置 TIM1_CCMRx 寄存器 OCxPE 位使能相应的预装载寄存器,
最后还要设置 TIM1_CR1 寄存器的 ARPE 位使能自动重装载的预装载寄存器(在向上计数或中心对称模式中)。
(1)PWM 边沿对齐模式
a. 向上计数的配置
当 TIM1_CR1 寄存器中的 DIR 位为低的时候执行向上计数。
在 PWM 模式 1,当 TIM1_CNT<TIM1_CCRx 时 PWM 参考信号,OCxREF 为高,否则为低。如果 TIM1_CCRx中的比较值大于自动重装载值(TIM1_ARR),则 OCxREF 保持为“1"。
如果比较值为 0,则 OCxREF 保持为“0"。
b. 向下计数的配置
当 TIM1_CR1 寄存器的 DIR 位为高时执行向下计数。
在 PWM 模式 1,当 TIM1_CNT>TIM1_CCRx 时参考信号 OCxREF 为低,否则为高。如果 TIM1_CCRx 中的比较值大于 TIM1_ARR 中的自动重装载值,则 OCxREF保持为“1"。
该模式下不能产生 0%的 PWM 波形。
(2)PWM 中央对齐模式
当TIM1_CR1寄存器中的CMS位不为 00时为中央对齐模式(所有其他的配置对OCxREF/OCx信号都有相同的作用)。
根据不同的CMS位的设置,比较标志可能 在计数器向上计数时被置 1、在计数器向下计数时被置 1、或在计数器向上和向下计数时被置 1。
TIM1_CR1寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。
6、PWM初始化函数TIM_OCInit
7、复用功能映射函数GPIO_PinRemapConfig
8、示例代码:
1 /*************************************************************************************************************************************
2 *
3 * 文件名称:main.c
4 * 文件功能:主函数文件
5 *
6 ***************************************************************************************************************************************/
7
8 #include "pbdata.h"//调用自定义公共函数库
9
10
11 /*********************************************************************************
12 *
13 * 初始化操作
14 *
15 *********************************************************************************/
16 void RCC_Configuration(void);//系统时钟初始化函数声明
17 void GPIO_Configuration(void);//GPIO初始化函数声明
18 void TIM3_Configuration(void);//定时器中断配置函数声明
19
20
21 /********************************************************************************
22 *
23 * 函数名称:main(void)
24 * 函数功能:主函数
25 * 函数说明:不能用void定义主函数
26 *
27 ********************************************************************************/
28 int main(void)//void不能void定义主函数
29 {
30 u8 led_fx=1;
31 u16 led_dt=0;
32
33 RCC_Configuration(); //系统时钟初始化
34
35 GPIO_Configuration();//端口初始化
36
37 TIM3_Configuration();//定时器T3配置
38
39 while(1)//主函数不做任何处理,等待进入中断函数
40 {
41 delay_ms(10);//每间隔10ms,改变值
42 if(led_fx==1)
43 {
44 led_dt++;
45 }
46 else
47 {
48 led_dt--;
49 }
50
51 if(led_dt>300) led_fx=0;
52 if(led_dt==0) led_fx=1;
53
54 TIM_SetCompare2(TIM3,led_dt);//送入PWM
55
56 }
57 }
58
59
60
61
62 /********************************************************************************
63 *
64 * 函数名称:RCC_Configuration(void)
65 * 函数功能:系统时钟高初始化函数
66 *
67 ********************************************************************************/
68 void RCC_Configuration(void)//系统时钟高初始化函数
69 {
70
71 SystemInit();//系统初始化
72 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//对应GPIO时钟使能
73 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//对应定时器T3时钟使能
74 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//端口复用时钟使能
75 }
76
77
78
79 /*******************************************************************************
80 *
81 * 函数名称:GPIO_Configuration(void)
82 * 函数功能:GPIO初始化函数
83 *
84 ********************************************************************************/
85
86 void GPIO_Configuration(void)//GPIO初始化函数
87 {
88 GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量
89
90 /*对LED引脚初始化*/
91 /*结构体变量赋值*/
92 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;////引脚配置
93 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率
94 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽输出,端口复用输出,用于PWM和推挽
95 /*对应的GPIO初始化*/
96 GPIO_Init(GPIOB,&GPIO_InitStructure);
97
98 }
99
100
101 /*********************************************************************************
102 *
103 * 中断相关子函数部分
104 *
105 *********************************************************************************/
106
107
108 /**********************************************
109 *
110 * 函数名称:TIM3_Configuration(void)
111 * 函数功能:配置定时器
112 *
113 ***********************************************/
114 void TIM3_Configuration(void)
115 {
116 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义一个结构体配置变量
117 TIM_OCInitTypeDef TIM_OCInitStructure;
118
119 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//端口映射
120
121 TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//使用前清空标志位
122
123 /*定时器初始化*/
124 TIM_TimeBaseStructure.TIM_Period = 899;//初值:72MHZ,预分频设为0,分频后频率72Mhz,初值900,也就是以此计数(1/72000000)*900s
125 TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频,分频数-1;
126 TIM_TimeBaseStructure.TIM_ClockDivision = 0;//时钟
127 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//模式
128
129 TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure);//初始化配置
130
131
132
133 /*PWM初始化*/
134 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//PWM模式
135 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能
136 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//输出极性,为低时发光二极管亮
137
138 TIM_OC2Init(TIM3,&TIM_OCInitStructure);//初始化执行
139
140
141 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能TIM3在PWM上的预装载寄存器
142
143
144 TIM_Cmd(TIM3,ENABLE);//打开定时器
145
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
View Code
/****************************************************************************************************************
*
* 文件名称:pbdata.c
* 文件功能:自定义函数或者全局变量的初始化
*
****************************************************************************************************************/
/*头文件声明*/
#include "pbdata.h"
/********************************************************************************************
*
* 自定义全局变量
*
********************************************************************************************/
u8 dt=0;
/******************************************************************************************
*
* 自定义函数
*
******************************************************************************************/
/**************************************************
*
* 函数名称:delay_us(u32 nus)
* 函数功能:微秒延时函数
* 输入参数:输入值为延时us
*
***************************************************/
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD = 9*nus;//载入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是执行9次
SysTick->VAL=0X00;//清空计数器,清空后,就自动设置自己设定的计数器的值
SysTick->CTRL=0X01;//使能,减到零动作(不发生中断),采用外部时钟
do
{
temp=SysTick->CTRL;//标志位,等到一直减到0
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
/***************************************************
*
* 函数名称:delay_ms(u16 nms)
* 函数功能:毫秒级延时
* 输入参数:输入值位延时ms
*
****************************************************/
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD = 9000*nms;//载入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是执行9000次
SysTick->VAL=0X00;//清空计数器,清空后,就自动设置自己设定的计数器的值
SysTick->CTRL=0X01;//使能,减到零动作(不发生中断),采用外部时钟
do
{
temp=SysTick->CTRL;//标志位,等到一直减到0
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
View Code
1 /*pbdata.h*/
2 /***************************************************************************************************
3 *
4 * 文件名称:pbdata.h
5 * 文件功能:自定义的函数和全局变量的声明头文件
6 *
7 ***************************************************************************************************/
8
9 #ifndef _pbdata_H
10 #define _pbdata_H
11
12 #include "stm32f10x.h"
13 #include "misc.h"
14 #include "stm32f10x_exti.h"
15 #include "stm32f10x_tim.h"
16
17
18
19 /********************************************************************
20 *
21 * 自定义全局变量声明
22 *
23 ********************************************************************/
24 extern u8 dt;
25
26
27
28
29
30 /********************************************************************
31 *
32 * 自定义全函数声明
33 *
34 ********************************************************************/
35 void delay(u32 nCount);
36 void delay_us(u32 nus);
37 void delay_ms(u16 nms);
38
39
40
41
42 #endif
View Code