正点原子MiniFly Firmware V1.5开源四轴代码硬件部分分析2:motor.c。

一些参考:电机控制基础——定时器基础知识与PWM输出原理 - 知乎 (zhihu.com)

#include "sys.h"
#include "delay.h"
#include "motors.h"
#include "pm.h"

/********************************************************************************	 
 * 本程序只供学习使用,未经作者许可,不得用于其它任何用途
 * ALIENTEK MiniFly
 * 电机驱动代码	
 * 正点原子@ALIENTEK
 * 技术论坛:www.openedv.com
 * 创建日期:2017/5/12
 * 版本:V1.3
 * 版权所有,盗版必究。
 * Copyright(C) 广州市星翼电子科技有限公司 2014-2024
 * All rights reserved
********************************************************************************/
/*
这种微型四轴目前多数采用这种空心杯电机,空心杯电机属于有刷电机,驱动的方式是MCU的PWM输出经过MOS管后直接驱动电机,
MCU的PWM输出占空比改变时加在电机两端的电压发生变化达到调速的目的
*/

/*
使用定时器,一般需要配置如下:
时基:也就是计数器的计数时钟
自动重装载值:每次计数的最大值
输出通道:当需要使用定时器输出某种波形时(如PWM)
输入通道:当需要使用定时器接收某种波形时(如电机编码器信号)
*/
static bool isInit = false;
u32 motor_ratios[] = {0, 0, 0, 0};
static const u32 MOTORS[] = { MOTOR_M1, MOTOR_M2, MOTOR_M3, MOTOR_M4 }; //四个电机



static u16 ratioToCCRx(u16 val)
{
	return ((val) >> (16 - MOTORS_PWM_BITS) & ((1 << MOTORS_PWM_BITS) - 1));
}

void motorsInit(void)	/*电机初始化*/
{//定义了GPIO初始化结构体 计时器初始化结构体 PWM通道设置结构体
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	 //使能GPIO总线时钟 使能端口定时器复用时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB, ENABLE);	//使能PORTA PORTB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM4,ENABLE);  	//TIM2和TIM4时钟使能    
	//初始化定时器TIM2 TIM4为默认状态
	TIM_DeInit(TIM4);	//重新初始化TIM4为默认状态
	TIM_DeInit(TIM2);	//重新初始化TIM2为默认状态
	
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_TIM4); 	//PB7 复用为TIM4 CH2	MOTOR1
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_TIM4); 	//PB6 复用为TIM4 CH1	MOTOR2
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_TIM2); 	//PB10复用为TIM2 CH3	MOTOR3
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM2); 	//PA5 复用为TIM2 CH1	MOTOR4
	 //根据复用功能 设置GPIO引脚 并初始化
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_10;	//PB6 7 10
	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(GPIOB,&GPIO_InitStructure);              				//初始化PB6 7 10
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;							//PA5
	GPIO_Init(GPIOA,&GPIO_InitStructure);              				//初始化PA5		
	/*
#define MOTORS_PWM_BITS           	8
#define MOTORS_PWM_PERIOD         	((1<<MOTORS_PWM_BITS) - 1)
	*/
	
    //设置并初始化计时器
	TIM_TimeBaseStructure.TIM_Period=MOTORS_PWM_PERIOD;			//自动重装载值
	TIM_TimeBaseStructure.TIM_Prescaler=MOTORS_PWM_PRESCALE;	//定时器分频
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;	//向上计数模式	
	TIM_TimeBaseStructure.TIM_ClockDivision=0; 					//时钟分频
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;				//重复计数次数
	
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);				//初始化TIM4
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);				//初始化TIM2
	 //设置并初始化计时器的PWM输出
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;				//PWM模式1
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;	//使能输出
	TIM_OCInitStructure.TIM_Pulse=0;							//CCRx
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;		//高电平有效
	TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;	//空闲高电平	
	TIM_OC2Init(TIM4, &TIM_OCInitStructure);  	//初始化TIM4 CH2输出比较
	TIM_OC1Init(TIM4, &TIM_OCInitStructure);  	//初始化TIM4 CH1输出比较
	TIM_OC3Init(TIM2, &TIM_OCInitStructure);  	//初始化TIM2 CH3输出比较
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);  	//初始化TIM2 CH1输出比较
	
	TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR2上的预装载寄存器
	TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR1上的预装载寄存器
	TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIM2在CCR3上的预装载寄存器
	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIM2在CCR1上的预装载寄存器
  
	TIM_ARRPreloadConfig(TIM4,ENABLE);	//TIM4	ARPE使能 
	TIM_ARRPreloadConfig(TIM2,ENABLE);	//TIM2	ARPE使能 
	
	TIM_Cmd(TIM4, ENABLE);  //使能TIM4
	TIM_Cmd(TIM2, ENABLE);  //使能TIM2	

	isInit = true;
}

/*电机测试*/
bool motorsTest(void)
{
	int i;
	
	for (i = 0; i < sizeof(MOTORS) / sizeof(*MOTORS); i++)
	{	
		motorsSetRatio(MOTORS[i], MOTORS_TEST_RATIO);
		delay_xms(MOTORS_TEST_ON_TIME_MS);
		motorsSetRatio(MOTORS[i], 0);
		delay_xms(MOTORS_TEST_DELAY_TIME_MS);
	}

	return isInit;
}

extern bool isExitFlip;

/*设置电机PWM占空比*/
void motorsSetRatio(u32 id, u16 ithrust)
{
	if (isInit) 
	{
		u16 ratio=ithrust;

	#ifdef ENABLE_THRUST_BAT_COMPENSATED		
		if(isExitFlip == true)		/*500Hz*/
		{
			float thrust = ((float)ithrust / 65536.0f) * 60;
			float volts = -0.0006239f * thrust * thrust + 0.088f * thrust;
			float supply_voltage = pmGetBatteryVoltage();
			float percentage = volts / supply_voltage;
			percentage = percentage > 1.0f ? 1.0f : percentage;
			ratio = percentage * UINT16_MAX;
			motor_ratios[id] = ratio;
		}		
	#endif
		
		switch(id)
		{
			case 0:		/*MOTOR_M1*/
				TIM_SetCompare2(TIM4,ratioToCCRx(ratio));
				break;
			case 1:		/*MOTOR_M2*/
				TIM_SetCompare1(TIM4,ratioToCCRx(ratio));
				break;
			case 2:		/*MOTOR_M3*/
				TIM_SetCompare3(TIM2,ratioToCCRx(ratio));
				break;
			case 3:		/*MOTOR_M4*/	
				TIM_SetCompare1(TIM2,ratioToCCRx(ratio));
				break;
			default: break;
		}	
	}
}

如果 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 您之前已经安装过了该驱动,请直接 跳到 第二部。 第二部。 STM32 USB STM32 USB STM32 USB STM32 USBSTM32 USB虚拟 串口驱动 串口驱动 串口驱动 路径 :“ATKATK -MiniFly MiniFly MiniFlyMiniFlyMiniFly微型四轴资料 微型四轴资料 \3,配套软件 ,配套软件 ,配套软件 ,配套软件 \3,STM32 STM32 STM32 USBUSBUSB虚拟串口驱动 虚拟串口驱动 虚拟串口驱动 虚拟串口驱动 ”。安装 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 过程这里就不详细说明,安装完成后将 USBUSBUSB线连接好四轴 连接好四轴 连接好四轴 或遥 控器 插入电脑。 入电脑。 入电脑。 电脑 提示发现新硬件 提示发现新硬件 提示发现新硬件 提示发现新硬件 并安装驱动,如果 安装驱动,如果 安装驱动,如果 安装驱动,如果 安装驱动,如果 安装 成功了 成功了 可以在设备 可以在设备 可以在设备 管理器 管理器 看到端 看到端 口号 ,如下图 ,如下图 ,如下图 2.1.1所示。 所示。 如果安装 如果安装 失败了, 失败了, 失败了, 请参考 路径下 的安装失败解决 的安装失败解决 的安装失败解决 的安装失败解决 办
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值