测试环境:Keil 5.20.0.0 STM32F103RBT6 固件库版本:STM32F10x_StdPeriph_Lib_V3.5.0(2011)
本文使用TIM1的通道1,通道2,产生两路1khz,死区时间1us的互补PWM波。
所使用的IO口:由下图知,我们使用引脚为PA9,PA10,互补输出使用PB14,PB15
部分代码如下:
1 /* 配置TIM1复用输出PWM时用到的I/O */
2 static void TIM1_GPIO_Config(void)
3 {
4 GPIO_InitTypeDef GPIO_InitStructure;
5
6 /* TIM1 clock enable */
7 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
8
9 /* GPIOA and GPIOB clock enable */
10 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
11
12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
13 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
14 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
15
16 GPIO_Init(GPIOA, &GPIO_InitStructure);
17
18 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
19 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
20 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
21
22 GPIO_Init(GPIOB, &GPIO_InitStructure);
23
24 }
初始化定时器功能配置
1 u16 CCR2_Val = 500;
2 u16 CCR3_Val = 500;//占空比,周期为1000
3
4 /*配置TIM1输出的PWM信号的模式,如周期、极性、占空比 */
5 void TIM1_Mode_Config(void)
6 {
7 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
8 TIM_BDTRInitTypeDef TIM1_BDTRInitStruct;
9 TIM_OCInitTypeDef TIM_OCInitStructure;
10
11 /* Time base configuration */
12 TIM_TimeBaseStructure.TIM_Period = 1000-1; //计数周期,向上记到此数,计数值清零
13 TIM_TimeBaseStructure.TIM_Prescaler = 72-1;//定时器分频系数,Ftimer = 72M/(TIM_Prescaler+1) = 1ms
14 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//与死区时间分频有关
15 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
16 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
17
18 /****** 配置BDTR寄存器,配置死区时间****************/
19 /*
20 定时器时钟 72M TIM_ClockDivision = TIM_CKD_DIV1时, Tdts = 13.89ns
21 0 - 1.764us 用算法一
22 1.778us - 3.505us 用算法二
23 3.556us - 7.000us 用算法三
24 7.1117us - 14us 用算法四
25 需要更长时间,使用TIM_ClockDivision分频
26 */
27 TIM1_BDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Disable;
28 TIM1_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Disable;
29 TIM1_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
30 TIM1_BDTRInitStruct.TIM_DeadTime = 205; //死区时间 72:1us 172:3us 205:5us
31 TIM_BDTRConfig(TIM1,&TIM1_BDTRInitStruct);
32
33 // TIM1->BDTR |= 72; //设置死区 注:上面那种方法也可以,这种快且简单
34
35 /* PWM1 Mode configuration: Channel2 */
36 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//PWM2模式
37 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
38 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//比较互补输出使能
39 TIM_OCInitStructure.TIM_Pulse = CCR2_Val; //比较值,即占空比
40 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性
41 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;//互补输出极性
42 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;//指定空闲状态下的TIM输出比较的引脚状态。
43 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;//指定空闲状态下的TIM互补输出比较的引脚状态。
44 TIM_OC2Init(TIM1, &TIM_OCInitStructure); //初始化通道二比较输出
45 TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); //配置通道二,自动重装载使能
46
47
48 /* PWM1 Mode configuration: Channel3 */
49 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
50 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
51 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
52 TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
53 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
54 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
55 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
56 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
57 TIM_OC3Init(TIM1, &TIM_OCInitStructure);
58 TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
59
60 TIM_ARRPreloadConfig(TIM1, ENABLE);//重载装载值 ENABLE 立即生效,DISABLE 下一个比较周期生效
61
62 /* TIM1 enable counter */
63 TIM_Cmd(TIM1, ENABLE);//使能定时器1
64
65 TIM_CtrlPWMOutputs(TIM1, ENABLE);//使能PWM外围输出
66 }
1 int main(void)
2 {
3 TIM1_GPIO_Config();
4 TIM1_Mode_Config();
5 while(1)
6 {
7 TIM1->CCR2 = CCR2_Val;
8 TIM1->CCR3 = CCR3_Val;
9 CCR2_Val+=5;
10 CCR3_Val+=10;
11 if(CCR2_Val>900) CCR2_Val = 100;
12 if(CCR3_Val>900) CCR3_Val = 100;
13 Delay_mS(200);
14 }
15 }
关于死区时间计算:
先贴几张关于TIM时钟的图:
第一张图:关于死区时间分频因子。(代码见,初始化定时器功能配置代码部分第14行所示)
第二张图:死区时间计算
定时器1时钟挂在APB2总线上,时钟为72M 当TIM_ClockDivision = TIM_CKD_DIV1时, Tdts = 1/72M = 13.89ns
0 - 1.764us 用算法一
1.778us - 3.505us 用算法二
3.556us - 7.000us 用算法三
7.1117us - 14us 用算法四
需要更长时间,使用TIM_ClockDivision分频后(可2分,4分频),设置死区时间。
测试数据:
实验现象:产生了两路死区时间为1us的互补PWM信号,其频率都是1kHz,占空比在10% - 90%不断变化,通道三比通道二变化要快。
死区时间(以通道二为例):(黄:PA10 绿:PB15)
通道二抓拍波形 (黄:PA10 绿:PB15)
通道三抓拍波形 (黄:PA9 绿:PB14)
通道二和通道三 (黄:PA9 绿:PA10)