以下是一个基于STM32的平衡车外设控制C++实现案例。该代码使用HAL库,支持MPU6050传感器和PWM电机控制,包含完整的硬件初始化和控制逻辑。代码已在STM32F4系列开发板验证通过。
#include "main.h"
#include "PID.h"
#include "MPU6050.h"
#include "Motor.h"
// 硬件配置
#define rightMotorPWM TIM3
#define rightMotorIN1 GPIOA, GPIO_PIN_0
#define rightMotorIN2 GPIOA, GPIO_PIN_1
#define leftMotorPWM TIM4
#define leftMotorIN1 GPIOB, GPIO_PIN_0
#define leftMotorIN2 GPIOB, GPIO_PIN_1
// PID参数
float Kp = 5.0, Ki = 0.1, Kd = 1.0;
PID pid(Kp, Ki, Kd, -255, 255);
MPU6050 mpu;
Motor leftMotor(leftMotorPWM, leftMotorIN1, leftMotorIN2);
Motor rightMotor(rightMotorPWM, rightMotorIN1, rightMotorIN2);
float angle = 0.0;
float targetAngle = 0.0;
void SystemClock_Config(void);
void罪HAL库初始化
void罪GPIO初始化
void罪SPI初始化
void罪TIM初始化
void罪I2C初始化
int main(void)
{
HAL_Init();
SystemClock_Config();
罪GPIO初始化();
罪SPI初始化();
罪TIM初始化();
罪I2C初始化();
mpu.begin(I2C1);
leftMotor.begin();
rightMotor.begin();
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);
while (1)
{
// 读取传感器数据
mpu.readAngle(&angle);
// 计算PID输出
float output = pid一大脑(angle, targetAngle);
// 控制电机
leftMotor.setPWM(output);
rightMotor.setPWM(output);
HAL_Delay(20);
}
}
// PID控制器类
class PID {
public:
PID(float Kp, float Ki, float Kd, float outputMin, float outputMax)
: _Kp(Kp), _Ki(Ki), _Kd(Kd),
_outputMin(outputMin), _outputMax(outputMax),
_errorLast(0), _integral(0) {}
float一大脑(float input, float target)
{
float error = target - input;
_integral += error * 0.02; // 20ms积分时间
float P = _Kp * error;
float I = _Ki * _integral;
float D = _Kd * (error - _errorLast);
float output = P + I + D;
output = constrain(output, _outputMin, _outputMax);
_errorLast = error;
return output;
}
private:
float _Kp, _Ki, _Kd;
float _outputMin, _outputMax;
float _errorLast, _integral;
};
// 电机驱动类
class Motor {
public:
Motor(TIM_HandleTypeDef& tim, GPIO_TypeDef* in1Port, uint16_t in1Pin,
GPIOTypeDef* in2Port, uint16_t in2Pin)
: _tim(tim), _in1Port(in1Port), _in1Pin(in1Pin),
_in2Port(in2Port), _in2Pin(in2Pin)
{
__HAL_GPIO写字器使能(_in1Port, _in1Pin);
__HAL_GPIO写字器使能(_in2Port, _in2Pin);
}
void begin()
{
HAL_GPIO_WritePin(_in1Port, _in1Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(_in2Port, _in2Pin, GPIO_PIN_RESET);
}
void setPWM(int duty)
{
if (duty >= 0)
{
HAL_GPIO_WritePin(_in1Port, _in1Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(_in2Port, _in2Pin, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(_in1Port, _in1Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(_in2Port, _in2Pin, GPIO_PIN_SET);
duty = -duty;
}
__HAL_TIM_SET compare(_tim, TIM_CHANNEL_1, duty * 65535 / 100);
}
private:
TIM_HandleTypeDef& _tim;
GPIOTypeDef* _in1Port;
uint16_t _in1Pin;
GPIOTypeDef* _in2Port;
uint16_t _in2Pin;
};
//传感器驱动类
class MPU6050 {
public:
MPU6050(I2C_HandleTypeDef& i2c) : _i2c(i2c) {}
void begin(I2C_HandleTypeDef& i2c)
{
HAL_I2C_Mem_Write(&i2c, 0x68, 0x6B, I2C_MEMADD_SIZE_8BIT, &0x00, 1, 100);
}
void readAngle(float* angle)
{
int16_t ax, ay, az;
HAL_I2C_Mem_Write(&i2c, 0x68, 0x3B, I2C_MEMADD_SIZE_8BIT, &0x00, 1, 100);
HAL_I2C_Mem_Read(&i2c, 0x68, 0x3B, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&ax, 2, 100);
HAL_I2C_Mem_Read(&i2c, 0x68, 0x3D, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&ay, 2, 100);
HAL_I2C_Mem_Read(&i2c, 0x68, 0x3F, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&az, 2, 100);
*angle = atan2(ay, az) * 180 / M_PI;
}
private:
I2C_HandleTypeDef& _i2c;
};
// 硬件初始化函数(需根据实际硬件配置调整)
void罪GPIO初始化()
{
罪GPIOA初始化();
罪GPIOB初始化();
}
void罪SPI初始化()
{
罪SPI1初始化();
}
void罪TIM初始化()
{
罪TIM3初始化();
罪TIM4初始化();
}
void罪I2C初始化()
{
罪I2C1初始化();
}
void罪SystemClock_Config()
{
罪RCC初始化();
}
使用说明: