一、硬件架构设计
1. 系统组成
STM32主控模块 CAN总线网络 电机驱动模块
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ STM32F407 │◄───►│ CAN收发器 │◄───►│ 电机驱动器 │
│ (CAN控制器) │ │ (如TJA1050) │ │ (如DRV8825)│
└──────────────┘ └──────────────┘ └──────────────┘
2. 关键元器件选型
元件 |
型号 |
作用 |
MCU |
STM32F407VGT6 |
主控芯片(含CAN控制器) |
CAN收发器 |
TJA1050 |
电平转换与总线驱动 |
电机驱动器 |
DRV8825 |
步进电机控制 |
终端电阻 |
120Ω |
抑制信号反射 |
二、CAN总线配置
1. 初始化代码(HAL库)
// CAN1初始化函数
void MX_CAN1_Init(void)
{CAN_HandleTypeDef hcan1;hcan1.Instance = CAN1;hcan1.Init.Prescaler = 6; // 分频系数hcan1.Init.Mode = CAN_MODE_NORMAL; // 正常模式hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan1.Init.TimeSeg1 = CAN_BS1_8TQ; // 时间段1hcan1.Init.TimeSeg2 = CAN_BS2_3TQ; // 时间段2hcan1.Init.TimeTriggeredMode = DISABLE;hcan1.Init.AutoBusOff = DISABLE;hcan1.Init.AutoWakeUp = DISABLE;hcan1.Init.AutoRetransmission = ENABLE;hcan1.Init.ReceiveFifoLocked = DISABLE;hcan1.Init.TransmitFifoPriority = DISABLE;if (HAL_CAN_Init(&hcan1) != HAL_OK){Error_Handler();}
}// CAN过滤器配置
void MX_CAN_Filter_Init(void)
{CAN_FilterTypeDef sFilterConfig;sFilterConfig.FilterBank = 0;sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;sFilterConfig.FilterIdHigh = 0x0000;sFilterConfig.FilterIdLow = 0x0000;sFilterConfig.FilterMaskIdHigh = 0x0000;sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;sFilterConfig.FilterActivation = ENABLE;if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK){Error_Handler();}
}
2. 波特率计算公式
波特率 = APB1时钟频率 / [预分频系数 × (1 + BS1 + BS2)]
示例:APB1=42MHz,预分频=6,BS1=8tq,BS2=3tq → 42/(6×12)=576Kbps
三、电机控制协议设计
1. 自定义CAN帧结构
字段 |
长度(字节) |
描述 |
标准ID |
11位 |
功能码+节点ID(如0x101) |
数据长度 |
4位 |
数据字段长度(1-8) |
数据字段 |
8字节 |
控制指令与参数 |
CRC |
15位 |
循环冗余校验 |
四、核心代码实现
1. CAN发送函数
void CAN_SendMotorCmd(uint8_t nodeID, uint8_t cmd, int16_t param)
{CanTxMsgTypeDef txMsg;txMsg.StdId = (0x100 | nodeID); // 基地址0x100txMsg.IDE = CAN_ID_STD;txMsg.RTR = CAN_RTR_DATA;txMsg.DLC = 3; // 命令+参数txMsg.Data[0] = cmd;txMsg.Data[1] = (param >> 8) & 0xFF;txMsg.Data[2] = param & 0xFF;HAL_CAN_Transmit(&hcan1, &txMsg, 1000);
}
2. CAN接收中断处理
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CanRxMsgTypeDef rxMsg;HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxMsg);uint8_t nodeID = rxMsg.StdId & 0x0F;uint8_t cmd = rxMsg.Data[0];switch(cmd){case 0x01: // 位置模式SetMotorPosition(nodeID, (rxMsg.Data[1]<<8)|rxMsg.Data[2]);break;case 0x02: // 速度模式SetMotorSpeed(nodeID, (rxMsg.Data[1]<<8)|rxMsg.Data[2]);break;// 其他指令处理}
}
五、电机驱动实现
1. 步进电机控制(DRV8825)
void SetMotorPosition(uint8_t nodeID, int16_t steps)
{// 发送脉冲控制信号for(int i=0; i<abs(steps); i++){HAL_GPIO_WritePin(GPIOA, STEP_PIN, GPIO_PIN_SET);HAL_Delay(1); // 脉冲宽度HAL_GPIO_WritePin(GPIOA, STEP_PIN, GPIO_PIN_RESET);HAL_Delay(1); // 间隔时间}// 方向控制if(steps > 0)HAL_GPIO_WritePin(GPIOA, DIR_PIN, GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOA, DIR_PIN, GPIO_PIN_RESET);
}
2. 直流电机控制(PWM调速)
void SetMotorSpeed(uint8_t nodeID, int16_t speed)
{// 速度范围-1000~1000speed = constrain(speed, -1000, 1000);// PWM占空比映射uint16_t duty = (speed + 1000) * 100 / 2000;// 设置TIM1通道__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty);
}
六、多电机协同控制
1. 节点管理表
typedef struct {uint8_t nodeID;uint8_t status; // 0:空闲 1:运行中int16_t targetPos;
} MotorNode;MotorNode motorTable[CANOPEN_MAX_MOTOR] = {{0x01, 0, 0},{0x02, 0, 0},// 其他节点
};
2. 状态监控流程
主循环:
├─ 接收CAN指令
├─ 更新节点状态表
├─ 检查超时(>500ms无响应则标记故障)
└─ 执行安全保护(过流/过热检测)
参考代码 利用stm32芯片,通过can控制电机的运动 www.youwenfan.com/contentcnj/70473.html
七、工程文件结构
MotorControl/
├── Src/
│ ├── main.c
│ ├── can_driver.c
│ ├── motor_driver.c
│ └── protocols.h
├── Inc/
│ ├── can_driver.h
│ └── motor_driver.h
├── Middlewares/
│ └── CANopen/
└── Hardware/├── CAN_Config/└── Motor_Driver/