STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获

声明:本篇文章只是个人知识盲区、知识弱点、重点部分的归纳总结,望各位大佬不喜勿喷。梳理顺序是按照正点原子的视频和文档的实际顺序梳理,转载请注明出处。

作者:sumjess

适用:这个视频我已经看过3遍了,总会有忘记的,所以来写这本书的随手笔记,记录重点、易忘点。该博客可以当做字典,也可以当做笔记。

目前内容:定时器&定时器中断

 

一、STM32 PWM工作过程

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第1张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第2张图片

STM32 PWM工作过程(通道1为例)

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第3张图片

CCR1:捕获比较()寄存器(x=1,2,3,4):设置比较值。

CCMR1: OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1【110】或者PWM模式2【111】

CCER:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。

CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。

二、PWM模式1 & PWM模式2:

寄存器TIMx_CCMR1OC1M[2:0]位来分析:

 

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第4张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第5张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第6张图片

void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

(1)自动重载的预装载寄存器:

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第7张图片STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第8张图片

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

简单的说,ARPE=1,ARR立即生效。。。APRE=0,ARR下个比较周期生效。
(2)STM32 定时器3输出通道引脚:

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第9张图片

Datasheet中表格会有详细说明

三、PWM输出库函数概述:

(1)PWM输出库函数:

void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

typedef struct
{
  uint16_t TIM_OCMode;  //PWM模式1或者模式2
  uint16_t TIM_OutputState; //输出使能 OR失能
  uint16_t TIM_OutputNState;
  uint16_t TIM_Pulse; //比较值,写CCRx
  uint16_t TIM_OCPolarity; //比较输出极性
  uint16_t TIM_OCNPolarity; 
  uint16_t TIM_OCIdleState;  
  uint16_t TIM_OCNIdleState; 
} TIM_OCInitTypeDef;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure. TIM_Pulse=100;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

(2)设置比较值函数:

void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Compare2);

(3)使能输出比较预装载:

void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

(4)使能自动重装载的预装载寄存器允许位:

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

四、PWM输出配置步骤:

使能定时器3和相关IO口时钟。

         使能定时器3时钟:RCC_APB1PeriphClockCmd();

         使能GPIOB时钟:RCC_APB2PeriphClockCmd();

② 初始化IO口为复用功能输出。函数:GPIO_Init();

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      

这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,

     所以需要开启AFIO时钟。同时设置重映射。

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);

④  初始化定时器:ARR,PSC等:TIM_TimeBaseInit();

⑤  初始化输出比较参数:TIM_OC2Init();

 使能预装载寄存器 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

⑦  使能定时器:TIM_Cmd();

⑧  不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2();

五、STM32 PWM工作过程---输入捕获:

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第10张图片

附可直接使用的配置:(方便做各种智能车、擂台等4PWM)

1、底层配置:

void speed_Init(void)    //TIM3_CH1->PC6 CH2->PC7 CH3->PC8 CH4->PC9
{ 
		//**********电机驱动设置************//
		TIM_OCInitTypeDef  TIM_OCInitStructure;
		TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
		GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟  
		TIM_DeInit(TIM3);//初始化TIM3寄存器
	 
		GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer3完全重映射  TIM3_CH1->PC6 CH2->PC7 CH3->PC8 CH4->PC9
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; //TIM1_CH1  //设置该引脚为复用输出功能,输出TIM3 CH1的PWM脉冲波形 GPIOC.6
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO                
//**************************************************************************
//  定时器1设置: 72分频,频率10KHz,向上计数,105是为了速度为100时,PWM占空比不会到100,方便电机驱动自举生压。一般PWM频率大于1K,4-10K比较好。
//************************************************************************** 
    TIM_TimeBaseStructure.TIM_Period = 105-1;
    TIM_TimeBaseStructure.TIM_Prescaler = 71;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
// 主定时器T3为 PWM3 模式 
    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_High;
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
    
    TIM_OCInitStructure.TIM_Pulse = 0; 
    TIM_OC2Init(TIM3, &TIM_OCInitStructure); 
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
 
    TIM_OCInitStructure.TIM_Pulse = 0; 
    TIM_OC3Init(TIM3, &TIM_OCInitStructure); 
    TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
 
    TIM_OCInitStructure.TIM_Pulse = 0; 
    TIM_OC4Init(TIM3, &TIM_OCInitStructure); 
    TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
    
    TIM_ARRPreloadConfig(TIM3, ENABLE); //使能定时器3
    TIM_Cmd(TIM3, ENABLE);
}

2、函数调用:

#include "delay.h"
#include "sys.h"
#include "sumjess_pwm.h"
 int main(void)
 {	  
	 int b = 0;
	 delay_init();	
   speed_Configuration();

	while(1) 
	{		
		for(b=0;b<100;b+=10){
		TIM_SetCompare1(TIM3,b);   delay_ms(100);}
		for(b=100;b>1;b-=10){
		TIM_SetCompare1(TIM3,b);   delay_ms(100);}
    TIM_SetCompare1(TIM3,0);  delay_ms(2000);
		for(b=0;b<100;b+=10){
		TIM_SetCompare2(TIM3,b);   delay_ms(100);}
		for(b=100;b>1;b-=10){
		TIM_SetCompare2(TIM3,b);   delay_ms(100);}		
		TIM_SetCompare2(TIM3,0);  delay_ms(2000);
		for(b=0;b<100;b+=10){
		TIM_SetCompare3(TIM3,b);   delay_ms(100);}
		for(b=100;b>1;b-=10){
		TIM_SetCompare3(TIM3,b);   delay_ms(100);}
    TIM_SetCompare3(TIM3,0);  delay_ms(2000);
		for(b=0;b<100;b+=10){
		TIM_SetCompare4(TIM3,b);   delay_ms(100);}
		for(b=100;b>1;b-=10){
		TIM_SetCompare4(TIM3,b);   delay_ms(100);}
    TIM_SetCompare4(TIM3,0);  delay_ms(2000);		
	}
}

注:该函数满载为105,即:TIM_SetCompare1(TIM3,105);由于驱动半桥需要自举升压,占空比必须小于98%。最好在95%以下。所以写者留出5%,使用时只需写:0%~100%之间即可。

六、STM32 输入捕获工作过程(通道1为例):

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第11张图片

一句话总结工作过程:通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。

(1)步骤1:设置输入捕获滤波器(通道1为例)

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第12张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第13张图片

(2)步骤2:设置输入捕获极性(通道1为例)

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第14张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第15张图片

(3)步骤三:设置输入捕获映射通道(通道1为例):

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第16张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第17张图片

(4)步骤四:设置输入捕获分频器(通道1为例):

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第18张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第19张图片

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第20张图片

(5)步骤五:捕获到有效信号可以开启中断:

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第21张图片

(6)最后:看看定时器通道对应引脚TIM5为例:

STM32复习笔记(八)PWM输出(附可直接使用的配置)和 输入捕获_第22张图片

 

七、输入捕获通道初始化函数:

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

typedef struct
{
  uint16_t TIM_Channel; //捕获通道1-4   
  uint16_t TIM_ICPolarity; //捕获极性
  uint16_t TIM_ICSelection; //映射关系
  uint16_t TIM_ICPrescaler; //分频系数
  uint16_t TIM_ICFilter;  //滤波器
} TIM_ICInitTypeDef;
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM5_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInit(TIM5, &TIM5_ICInitStructure);

 

八、通道极性设置独立函数:

void TIM_OCxPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)

九、获取通道捕获值

uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx)

十、输入捕获的一般配置步骤:

① 初始化定时器和通道对应IO的时钟。

② 初始化IO口,模式为输入:GPIO_Init();

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入

③初始化定时器ARRPSC

   TIM_TimeBaseInit();

④初始化输入捕获通道

   TIM_ICInit();

⑤如果要开启捕获中断,

    TIM_ITConfig();

    NVIC_Init();

⑥使能定时器:TIM_Cmd();

⑦编写中断服务函数:TIMx_IRQHandler();

 

 

你可能感兴趣的:(STM32从入门到精通)