• 寄存器版本
    参考手册:
    STM32F4xx中文参考手册.pdf
    STM32F405xx,STM32F407xx.pdf
  • pwm.h
#ifndef __PWM_H
#define __PWM_H
#include "sys.h" 
 //模块使能宏
#define TIM1_NUM 1 
#define TIM5_NUM 1

#define PWM1  TIM1->CCR1   
#define PWM2  TIM1->CCR2  
#define PWM3  TIM1->CCR3   
#define PWM4  TIM1->CCR4  

#define PWM5  TIM5->CCR1   
#define PWM6  TIM5->CCR2  
#define PWM7  TIM5->CCR3   
#define PWM8  TIM5->CCR4  

//输出通道初始化
void out_pwm_io_init(u16 arr,u16 psc);
//TIM PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3);
#endif


  • pwm.c
#include"pwm.h"

void out_pwm_io_init(u16 arr,u16 psc)
{
	#if TIM1_NUM==1
	/*******	TIM1  CH1_E9	CH2_E11 CH3_E13 CH4_E14			*******/
	RCC->AHB1ENR|=1<<4;
	RCC->APB2ENR|=1<<0;
	GPIO_Set(GPIOE,PIN9|PIN11|PIN13|PIN14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
	GPIO_AF_Set(GPIOE,9|11|13|14,1);
	
	TIM1->ARR=arr;   //设定计数器自动重装值
	TIM1->PSC=psc;  //设定预分频系数
	
	TIM1->CCMR1 |=6<<4; //CH1 PWM1 模式
	TIM1->CCMR1 |=6<<12; //CH2 PWM1 模式
	TIM1->CCMR2 |=6<<4;	//CH3 PWM1
	TIM1->CCMR2 |=6<<12;//CH4 PWM1
	
	TIM1->CCMR1 |=1<<3; // ch1预装载使能
	TIM1->CCMR1 |=1<<11; // ch2预装载使能
	TIM1->CCMR2 |=1<<3;// ch3预装载使能
	TIM1->CCMR2 |=1<<11;// ch4预装载使能
	/****/
	TIM1->EGR|=1<<0;  //ug位置一  不知道加这一句有什么用 看手册需要加
	
	TIM1->CCER |=1<<0;  //oc1  输出使能
	TIM1->CCER |=0<<1;   //oc1 高电平有效
	TIM1->CCER |=1<<4;   //CH2输出使能	
	TIM1->CCER |=0<<5;   //oc2 高电平有效	
	TIM1->CCER |=1<<8;   //CH3输出使能	
	TIM1->CCER |=0<<9;   //oc3 高电平有效	
	TIM1->CCER |=1<<12;   //CH4输出使能	
	TIM1->CCER |=0<<13;   //oc4 高电平有效	
	//TIM4->BDTR |= 1<<15;       //TIM1必须要这句话才能输出PWM
	TIM1->CR1|=1<<7;  //arpe使能
	TIM1->CR1|=1<<0;  //使能定时器4
	
	#endif
	
#if TIM5_NUM==1 	
	
	//	TIM5  CH1_A0	CH2_A1 CH3_A2 CH4_A3	
	RCC->AHB1ENR|=1<<0;
	RCC->APB1ENR|=1<<3;
	GPIO_Set(GPIOA,PIN0|PIN1|PIN2|PIN3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
	GPIO_AF_Set(GPIOA,0|1|2|3,2);
	
	TIM5->ARR=arr;   //设定计数器自动重装值
	TIM5->PSC=psc;  //设定预分频系数
	
	TIM5->CCMR1 |=6<<4; //CH1 PWM1 模式
	TIM5->CCMR1 |=6<<12; //CH2 PWM1 模式
	TIM5->CCMR2 |=6<<4;	//CH3 PWM1
	TIM5->CCMR2 |=6<<12;//CH4 PWM1
	
	TIM5->CCMR1 |=1<<3; // ch1预装载使能
	TIM5->CCMR1 |=1<<11; // ch2预装载使能
	TIM5->CCMR2 |=1<<3;// ch3预装载使能
	TIM5->CCMR2 |=1<<11;// ch4预装载使能
	/****/
	TIM5->EGR|=1<<0;  //ug位置一  不知道加这一句有什么用 看手册需要加
	
	TIM5->CCER |=1<<0;  //oc1  输出使能
	TIM5->CCER |=0<<1;   //oc1 高电平有效
	TIM5->CCER |=1<<4;   //CH2输出使能	
	TIM5->CCER |=0<<5;   //oc2 高电平有效	
	TIM5->CCER |=1<<8;   //CH3输出使能	
	TIM5->CCER |=0<<9;   //oc3 高电平有效	
	TIM5->CCER |=1<<12;   //CH4输出使能	
	TIM5->CCER |=0<<13;   //oc4 高电平有效	
	

	//TIM4->BDTR |= 1<<15;       //TIM1必须要这句话才能输出PWM
	TIM5->CR1|=1<<7;  //arpe使能
	TIM5->CR1|=1<<0;  //使能定时器4
	#endif
	
}
//TIM PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3)
{
#if TIM1_NUM==1 	 	
	TIM1->CCR1=num0;  //修改比较值,修改占空比
	TIM1->CCR2=num1;  //修改比较值,修改占空比
	TIM1->CCR3=num2;	//修改比较值,修改占空比
	TIM1->CCR4=num3;  //修改比较值,修改占空比

#endif
#if TIM5_NUM==1 	
	TIM5->CCR1=num0;	//修改比较值,修改占空比
	TIM5->CCR2=num1;  //修改比较值,修改占空比
	TIM5->CCR3=num2;	//修改比较值,修改占空比
	TIM5->CCR4=num3;	//修改比较值,修改占空比


#endif
}

  • 飞控板有8路pwm输出,分别对应
 PE14    TIM1CH1	ESC_PWM_OUT1
 PE13    TIM1CH2	ESC_PWM_OUT2
 PE11    TIM1CH3	ESC_PWM_OUT3
 PE9     TIM1CH4	ESC_PWM_OUT4
 PA0     TIM5CH1	ESC_PWM_OUT5	
 PA1     TIM5CH2	ESC_PWM_OUT6
 PA2     TIM5CH3	ESC_PWM_OUT7
 PA3     TIM5CH4	ESC_PWM_OUT8
  • pwm_out相关电路

003_飞控_PWM_out
003_飞控_PWM_out

-库函数版本

  • PWM.C


#include "PWM.h"


//TIMx: TIM模块号
//arr:自动重装值
//psc:时钟预分频数
void TIMx_PWM_Init(uint32_t arr, uint32_t psc)
{		 					 
	//此部分需手动修改IO口设置	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;	
#if TIM1_NUM==1	
	/*******	TIM1  CH1_E9	CH2_E11 CH3_E13 CH4_E14			*******/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);  	//TIM1时钟使能  
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); 	//使能PORTE时钟	
		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14; 
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	
	GPIO_Init(GPIOE,&GPIO_InitStructure);              //初始化PE口
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1); //GPIOE9复用为定时器1
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1); //GPIOE11复用为定时器1
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1); //GPIOE13复用为定时器1
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1); //GPIOE14复用为定时器1
	

	
	TIM_TimeBaseStructure.TIM_Prescaler=psc*2;  //定时器分频(此时定时器的时钟为APB2时钟)
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 	
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;//重复计数器寄存器(TIM1和TIM8中才设置)
	
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//初始化定时器1
	
	//初始化TIM1 Channel1 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStructure.TIM_Pulse = (arr+1)/2;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性低
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_Low;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	
	//使能通道1    
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR1上的预装载寄存器
	
	//使能通道2
	TIM_OC2Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR1上的预装载寄存器
	
	//使能通道3
	TIM_OC3Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR1上的预装载寄存器
	
	//使能通道4
	TIM_OC4Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR1上的预装载寄存器
	
	TIM_ARRPreloadConfig(TIM1,ENABLE);//ARPE使能 

	TIM_Cmd(TIM1, ENABLE);  //使能TIM1
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);//启用TIM输出
	
#endif	

#if TIM5_NUM==1 
	/*******	TIM5  CH1_A0	CH2_A1 CH3_A2 CH4_A3					*******/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);  	//TIM5时钟使能  
 
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); 	//使能PORTA时钟	
		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //GPIOA0复用为定时器5
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM5); //GPIOA1复用为定时器5
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM5); //GPIOA2复用为定时器5
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM5); //GPIOA3复用为定时器5
	
	GPIO_Init(GPIOA,&GPIO_InitStructure);              //初始化PA口
		
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);//初始化定时器5
	
	//初始化TIM5 Channel1 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
	
	//使能通道1
	TIM_OC1Init(TIM5, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);  //使能TIM5在CCR1上的预装载寄存器
	
	//使能通道2
	TIM_OC2Init(TIM5, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable);  //使能TIM5在CCR1上的预装载寄存器
	
	//使能通道3
	TIM_OC3Init(TIM5, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 1OC1
	TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable);  //使能TIM5在CCR1上的预装载寄存器
	
	//使能通道4
	TIM_OC4Init(TIM5, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 1OC1
	TIM_OC4PreloadConfig(TIM5, TIM_OCPreload_Enable);  //使能TIM5在CCR1上的预装载寄存器
	
	TIM_ARRPreloadConfig(TIM5,ENABLE);//ARPE使能 

	TIM_Cmd(TIM5, ENABLE);  //使能TIM5
#endif
} 
//TIM PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3)
{
#if TIM1_NUM==1 	
	TIM_SetCompare1(TIM1,num0);	//修改比较值,修改占空比
	TIM_SetCompare2(TIM1,num1);	//修改比较值,修改占空比
	TIM_SetCompare3(TIM1,num2);	//修改比较值,修改占空比
	TIM_SetCompare4(TIM1,num3);	//修改比较值,修改占空比

#endif
#if TIM5_NUM==1 	
	TIM_SetCompare1(TIM5,num0);	//修改比较值,修改占空比
	TIM_SetCompare2(TIM5,num1);	//修改比较值,修改占空比
	TIM_SetCompare3(TIM5,num2);	//修改比较值,修改占空比
	TIM_SetCompare4(TIM5,num3);	//修改比较值,修改占空比
#endif
}




  • PWM.H
#ifndef _PWM_H_
#define _PWM_H_

#include "header.h"

 //模块使能宏
#define TIM1_NUM 1 
#define TIM5_NUM 1

//PWM输出初始化
void TIMx_PWM_Init(uint32_t arr, uint32_t psc);

//PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3);


#endif

相关文章: