小马哥robofly四轴代码解读:PWM电机输出

代码主要在这个文件里:C:\Users\DQ_SZU\Desktop\RoboFlyDEMO\Drive\src\motor.c
我们要利用mos管的特性,定义4个引脚复用推挽输出,同时要注意每一个引脚对应的时钟,接下来就是定义TIM3作为PWM波输出的计数器,通过其4个通道进行输出:
TIM_OC1Init(TIM3,&TIM_OCInitStruct); TIM_OC2Init(TIM3,&TIM_OCInitStruct); TIM_OC3Init(TIM3,&TIM_OCInitStruct); TIM_OC4Init(TIM3,&TIM_OCInitStruct);
输出极性低即一开始是从0开始的然后转速慢慢增大,大概可以如下理解(可能不准确)当你输入1000时,占空比为1,也就是主控接到电机的引脚一直是高电平(占空比=高电平时间/总的时间,简单的理解就是占空比越大能量输出持续时间越长,一个周期内转速越快)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
每个定时器有4个输出通道,所以只需要1个定时器即可控制4个电机
在这里插入图片描述

#define Moto_PwmMax 1000  输出最大
int16_t MOTO1_PWM = 0;
int16_t MOTO2_PWM = 0;
int16_t MOTO3_PWM = 0;
int16_t MOTO4_PWM = 0;

/************************************************************
* 函  数:void MOTOR_Init(void)
* 功  能:电机引脚初始化 以及TIM3 配置输出PWM
* 参  数:无
* 返回值:无
* 备  注:TIM3 CH1(PWM1) -> PA6
*         TIM3 CH2(PWM2) -> PA7
*         TIM3 CH3(PWM3) -> PB0
*         TIM3 CH4(PWM4) -> PB1
*******************************/
void MOTOR_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;   //定义GPIO结构体变量
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;   //定义定时器结构体变量
	TIM_OCInitTypeDef TIM_OCInitStruct;   //定义输出比较结构体变量
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);   //GPIOA、B、复用时钟使能
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);   //使能TIM3的时钟
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;   //配置GPIO第6、7引脚
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;   	  //配置GPIO为复用推挽输出
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;  	  //配置GPIO速率
	GPIO_Init(GPIOA,&GPIO_InitStruct);   //GPIO初始化函数
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;   //配置GPIO第0、1引脚
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;   	  //配置GPIO为复用推挽输出
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;   	  //配置GPIO速率
	GPIO_Init(GPIOB,&GPIO_InitStruct);   //GPIO初始化函数
	
	TIM_TimeBaseInitStruct.TIM_Period=1000-1;   	  //设置自动重装载的周期值
	TIM_TimeBaseInitStruct.TIM_Prescaler=100;   	  //设置预分频值
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;     //设置时钟分割
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);   		   //定时器初始化函数
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1
	TIM_OCInitStruct.TIM_Pulse=0;   						   //初始化占空比为0
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;   	   //输出比较极性低
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;   //比较输出使能
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);   					   //比较输出初始化函数
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较1预装载寄存器使能
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1
	TIM_OCInitStruct.TIM_Pulse=0;   					   		//初始化占空比为0
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;   		//输出比较极性低
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;   	//比较输出使能
	TIM_OC2Init(TIM3,&TIM_OCInitStruct);   						//比较输出初始化函数
	TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较2预装载寄存器使能
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1
	TIM_OCInitStruct.TIM_Pulse=0;   							//初始化占空比为0
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;   		//输出比较极性低
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;   	//比较输出使能
	TIM_OC3Init(TIM3,&TIM_OCInitStruct);   						//比较输出初始化函数
	TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较3预装载寄存器使能
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;   //PWM模式1
	TIM_OCInitStruct.TIM_Pulse=0;   							//初始化占空比为0
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;   		//输出比较极性低
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;   	//比较输出使能
	TIM_OC4Init(TIM3,&TIM_OCInitStruct);   						//比较输出初始化函数
	TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);   //输出比较4预装载寄存器使能
	
	TIM_Cmd(TIM3,ENABLE);   //TIM3使能
}

下面函数是将遥控器传输来的ADC值转化为输入比较的值,并对它进行限幅处理,因为电机不可能无限输出

/************************************************************************************************
* 函  数:void Moto_Pwm(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM)
* 功  能:电机要输出数值转换成PWM波形输出
* 参  数:MOTO1_PWM 电机1
*         MOTO2_PWM 电机2
*         MOTO3_PWM 电机3
*         MOTO3_PWM 电机4
* 返回值:无 
* 备  注:无
************************************************************************************************/
void Moto_Pwm(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM)
{		
	if(MOTO1_PWM>Moto_PwmMax)	MOTO1_PWM = Moto_PwmMax;
	if(MOTO2_PWM>Moto_PwmMax)	MOTO2_PWM = Moto_PwmMax;
	if(MOTO3_PWM>Moto_PwmMax)	MOTO3_PWM = Moto_PwmMax;
	if(MOTO4_PWM>Moto_PwmMax)	MOTO4_PWM = Moto_PwmMax;
	if(MOTO1_PWM<0)	MOTO1_PWM = 0;
	if(MOTO2_PWM<0)	MOTO2_PWM = 0;
	if(MOTO3_PWM<0)	MOTO3_PWM = 0;
	if(MOTO4_PWM<0)	MOTO4_PWM = 0;
	
	TIM3->CCR1 = MOTO1_PWM;
	TIM3->CCR2 = MOTO2_PWM;
	TIM3->CCR3 = MOTO3_PWM;
	TIM3->CCR4 = MOTO4_PWM;
}

整理一下思路:确定哪个TIM作为PWM输出,确定电机输出的最大转速,初始化时钟(自动转载值、预分频值、计数模式,设置TIM_OCInitStruct.TIM_OCMode模式为PWM1、设置初始占空比、设置输出比较极性,使能预转载寄存器,4个通道重复同样的操作,最后使能时钟),最后直接用寄存器赋值TIM3->CCRx = MOTOx_PWM;

typedef struct
{
  __IO uint16_t CR1;
  uint16_t  RESERVED0;
  __IO uint16_t CR2;
  uint16_t  RESERVED1;
  __IO uint16_t SMCR;
  uint16_t  RESERVED2;
  __IO uint16_t DIER;
  uint16_t  RESERVED3;
  __IO uint16_t SR;
  uint16_t  RESERVED4;
  __IO uint16_t EGR;
  uint16_t  RESERVED5;
  __IO uint16_t CCMR1;
  uint16_t  RESERVED6;
  __IO uint16_t CCMR2;
  uint16_t  RESERVED7;
  __IO uint16_t CCER;
  uint16_t  RESERVED8;
  __IO uint16_t CNT;
  uint16_t  RESERVED9;
  __IO uint16_t PSC;
  uint16_t  RESERVED10;
  __IO uint16_t ARR;
  uint16_t  RESERVED11;
  __IO uint16_t RCR;
  uint16_t  RESERVED12;
  __IO uint16_t CCR1;//注意这里
  uint16_t  RESERVED13;
  __IO uint16_t CCR2;
  uint16_t  RESERVED14;
  __IO uint16_t CCR3;
  uint16_t  RESERVED15;
  __IO uint16_t CCR4;
  uint16_t  RESERVED16;
  __IO uint16_t BDTR;
  uint16_t  RESERVED17;
  __IO uint16_t DCR;
  uint16_t  RESERVED18;
  __IO uint16_t DMAR;
  uint16_t  RESERVED19;
} TIM_TypeDef;

定时器补充资料:
stm32的定时器分为高级定时器(TIM1 TIM8)、通用定时器(TIM2-5)、基本定时器(TIM6-7),
高级定时器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通用定时器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本定时器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页