sensor_2026/HARDWARE/MOTOR/motor_driver.c

183 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// motor_driver.c
#include "motor_driver.h"
#include "delay.h"
// 全局变量
static uint8_t pwm_duty = 0; // PWM占空比 0-100
static MotorState motor_dir = MOTOR_STOP;
// GPIO初始化
void DRV8832_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOE时钟
RCC_AHB1PeriphClockCmd(MOTOR_IN1_GPIO_CLK, ENABLE);
// 配置IN1 (PE9) 和 IN2 (PE13) 为输出
GPIO_InitStructure.GPIO_Pin = MOTOR_IN1_GPIO_PIN | MOTOR_IN2_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(MOTOR_IN1_GPIO_PORT, &GPIO_InitStructure);
// 配置FAULTN (PE4) 为输入
GPIO_InitStructure.GPIO_Pin = MOTOR_FAULT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
GPIO_Init(MOTOR_FAULT_GPIO_PORT, &GPIO_InitStructure);
// 初始状态:停止电机
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
}
// 初始化DRV8832
void DRV8832_Init(void) {
DRV8832_GPIO_Init();
}
//=====================================================================================
// 电机基础控制函数
void Motor_Control(MotorState state) {
switch(state) {
case MOTOR_STOP: // IN1=0, IN2=0
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
break;
case MOTOR_FORWARD: // IN1=1, IN2=0
GPIO_SetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
break;
case MOTOR_REVERSE: // IN1=0, IN2=1
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_SetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
break;
case MOTOR_BRAKE: // IN1=1, IN2=1
GPIO_SetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_SetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
break;
}
}
// 获取故障状态
uint8_t Motor_GetFaultStatus(void) {
// FAULTN引脚为低电平时表示故障
if (GPIO_ReadInputDataBit(MOTOR_FAULT_GPIO_PORT, MOTOR_FAULT_GPIO_PIN) == Bit_RESET) {
return 1; // 故障
}
return 0; // 正常
}
// 安全的方向切换(避免电流冲击)
void Motor_SafeDirectionChange(MotorState new_direction) {
// 先刹车
Motor_Control(MOTOR_BRAKE);
delay_ms(5); // 5ms延迟
// 再切换到新方向
Motor_Control(new_direction);
}
// 使用TIM2实现软件PWM
#define PWM_FREQUENCY 20000 // 20kHz PWM频率
#define PWM_RESOLUTION 100 // 100级调速分辨率
static uint8_t pwm_counter = 0; // PWM计数器
// 定时器初始化
void PWM_Timer_Init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能TIM2时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / (2 * PWM_FREQUENCY)) - 1; // 168MHz/2/20kHz
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 使能定时器更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// 配置NVIC
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
}
// 定时器中断处理函数
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
pwm_counter++;
if (pwm_counter >= PWM_RESOLUTION) {
pwm_counter = 0;
}
// 根据占空比和方向控制电机
if (motor_dir == MOTOR_FORWARD) {
if (pwm_counter < pwm_duty) {
// 正转IN1=1, IN2=0
GPIO_SetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
} else {
// 停止(滑行)
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
}
}
else if (motor_dir == MOTOR_REVERSE) {
if (pwm_counter < pwm_duty) {
// 反转IN1=0, IN2=1
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_SetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
} else {
// 停止(滑行)
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
}
}
else {
// 停止状态
GPIO_ResetBits(MOTOR_IN1_GPIO_PORT, MOTOR_IN1_GPIO_PIN);
GPIO_ResetBits(MOTOR_IN2_GPIO_PORT, MOTOR_IN2_GPIO_PIN);
}
}
}
// 设置电机速度和方向
void Motor_SetSpeed(uint8_t speed, MotorState direction) {
// 限制速度范围
if (speed > 100) speed = 100;
// 如果速度为0或100%,直接使用基础控制
if (speed == 0) {
motor_dir = MOTOR_STOP;
pwm_duty = 0;
Motor_Control(MOTOR_STOP);
}
else if (speed == 100) {
motor_dir = direction;
pwm_duty = 100;
Motor_Control(direction);
}
else {
// 设置PWM参数
motor_dir = direction;
pwm_duty = speed; // 直接使用百分比
}
}