【STM32】STM32F407产生互补PWM输出

搜了一大堆,网上基本都是F103的例子,F4的很少,然而又需要用到,这里发一下调试过程吧

首先看一下什么是互补的PWM,直接上图,第二张是把Y轴移动了一下,方便理解(Multisim仿真截图),我的简单理解就是当A输出1B输出0,我高的时候你低,你低的时候我高。他们两的频率是一样的,振幅也是一样的。

【STM32】STM32F407产生互补PWM输出_第1张图片

【STM32】STM32F407产生互补PWM输出_第2张图片

1.关于输出通道问题

      由《STM32F4xx中文参考手册》可知(见下图),只有高级定时器TIM1和TIM8可以输出两路互补信号。其中OCx为主输出,OCxN为互补输出。这句话的意思是:如果我用TIM1输出两路互补的PWM信号。TIM1_CH1为主输出,那么TIM1_CH1N为互补输出。这是固定的。

【STM32】STM32F407产生互补PWM输出_第3张图片

                                         

     我在这里使用的是TIM1的通道1,查数据手册可知,用到的引脚为PA8(主输出),PA7(互补输出)。注:我的芯片为STM32F407VET6.

【STM32】STM32F407产生互补PWM输出_第4张图片

 

2.库函数配置

step1:结构体

// 结构体声明
GPIO_InitTypeDef GPIO_InitStructure;          // GPIO
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  // 定时器
TIM_OCInitTypeDef  TIM_OCInitStructure;       // 通道
TIM_BDTRInitTypeDef TIM_BDTRStructure;      // 刹车与死区

step2:时钟配置

// 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);  	// TIM1时钟使能    
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 	// 使能GPIOA时钟	

step3:时钟配置

// IO复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); // GPIOA7_8复用为定时器1
// IO复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM1); // GPIOA7_8复用为定时器1

step4:GPIO配置

// GPIO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;           // 引脚
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(GPIOA,&GPIO_InitStructure);              // 配置

step5:定时器1配置

// 定时器配置
TIM_TimeBaseStructure.TIM_Prescaler=84-1;  // 定时器分频84M/84=1M
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseStructure.TIM_Period=25000-1;   // 自动重装载值25000,1M / 25000 =40Hz
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);// 初始化定时器1

step6:死区和刹车配置

  死区:在这里理解为翻转变化时给的一个延时,如下图所示,

  刹车:  这里没有用到,不做赘述,大概意思是可以通过这个功能切断所有输出。

【STM32】STM32F407产生互补PWM输出_第5张图片

// 刹车死区配置
TIM_BDTRStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;// 自动输出功能使能
TIM_BDTRStructure.TIM_Break=TIM_Break_Disable;//失能刹车输入
//TIM_BDTRStructure.TIM_BreakPolarity=TIM_BreakPolarity_High; //刹车输入管脚极性高 
TIM_BDTRStructure.TIM_DeadTime=168; //输出打开和关闭状态之间的延时 84M/84=1us,84M/168=2us 
TIM_BDTRStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;// 锁电平参数: 不锁任何位
TIM_BDTRStructure.TIM_OSSIState=TIM_OSSIState_Disable; //设置在运行模式下非工作状态选项
TIM_BDTRStructure.TIM_OSSRState=TIM_OSSRState_Disable; //设置在运行模式下非工作状态选项
TIM_BDTRConfig(TIM3,&TIM_BDTRStructure);

死区时间配置及计算见下图:

  TIM_BDTRStructure.TIM_DeadTime=0x01; //死区时间1us

通过查找STM32F4的应用手册,我们可以看到,死区时间由寄存器BDTR的位UTG[7:0]控制,如下图所示,死区时间等于步长(Tdts)乘以用户设定的数字。

【STM32】STM32F407产生互补PWM输出_第6张图片

step7:PWM输出配置

  // 定时器比较输出通道配置
  TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; 
  TIM_OCInitStructure.TIM_Pulse=0; 	//占空比:12500/25000*100%=50%
  TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;  //输出极性高
  TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //输出使能
  TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset; // 输出空闲电平低

  // 互补输出配置
  TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable; //互补输出使能
  TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High;	// 互补端输出极性高
  TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset; //互补输出空闲电平低
  
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);  // OC1
  TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);   //配置

3.实验结果

       使用示波器对IO口进行测量,调至合适位置,用手机拍照记录如下:

【STM32】STM32F407产生互补PWM输出_第7张图片

【STM32】STM32F407产生互补PWM输出_第8张图片

全部代码如下:

// 函数名:TIM1_PWM_Init
// 参  数:None
// 返回值:None
// 描  述:使用TIM1的通道1输出两路互补的PWM
// 说  明:参考正点原子,野火论坛,在此感谢
void TIM1_PWM_Init()
{		 					 
	// 结构体声明
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
  TIM_BDTRInitTypeDef TIM_BDTRStructure;
  
	// 时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);  	//TIM3时钟使能    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 	//使能PORTC时钟	
	
  // IO复用
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); //
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM1); //
	
  // IO配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7 | GPIO_Pin_8;//6脚未使用
	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(GPIOA,&GPIO_InitStructure);              //初始化PF9
	 
   GPIO_ResetBits(GPIOA,GPIO_Pin_6);        //拉低刹车
  // 定时器配置
	TIM_TimeBaseStructure.TIM_Prescaler=84-1;  //自动重装载值1M / 25000 =40Hz
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=25000-1;   //定时器分频84M/84=1M
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//初始化定时器1
    
  // 定时器比较输出通道配置
  TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; 
  TIM_OCInitStructure.TIM_Pulse=0; 	//占空比:12500/25000*100%=50%
  TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;  //输出极性高
  TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //输出使能
  TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset; // 输出空闲电平低

  // 互补输出配置
  TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable; //互补输出使能
  TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High;	// 互补端输出极性高
  TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset; //互补输出空闲电平低
  
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);  // OC1
  TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);   //配置

  // 刹车死区配置
  TIM_BDTRStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;// 自动输出功能使能
  TIM_BDTRStructure.TIM_Break=TIM_Break_Disable;//失能刹车输入
  TIM_BDTRStructure.TIM_BreakPolarity=TIM_BreakPolarity_High; //刹车输入管脚极性高 
  TIM_BDTRStructure.TIM_DeadTime=0; //输出打开和关闭状态之间的延时 84-1us  168-2us 
  TIM_BDTRStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;// 锁电平参数: 不锁任何位
  TIM_BDTRStructure.TIM_OSSIState=TIM_OSSIState_Disable; //设置在运行模式下非工作状态选项
  TIM_BDTRStructure.TIM_OSSRState=TIM_OSSRState_Disable; //设置在运行模式下非工作状态选项
  TIM_BDTRConfig(TIM1,&TIM_BDTRStructure);
  

  TIM_ARRPreloadConfig(TIM1,ENABLE);//ARPE使能 
	
  TIM_Cmd(TIM1, ENABLE);  //使能TIM3
  TIM_CtrlPWMOutputs(TIM1, ENABLE); //开启OC和OCN输出										  
}  

//主函数

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);//初始化串口波特率为115200
 	TIM1_PWM_Init();	//84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz.   40  
  while(1)
	{
    TIM_SetCompare1(TIM1,12500);	//修改比较值,修改占空比50%
	}
}

 

你可能感兴趣的:(STM32单片机)