#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "math.h"
#define MPI 3.1415926535f
// 系统时钟配置 (72MHz)
void SystemClock_Config(void) {
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
SystemCoreClockUpdate();
}
// 细分设置 (根据D36A拨码开关实际位置)
#define MICROSTEPPING 16 // 可选: 1,2,4,8,16,32
// 步进电机参数
#define STEP_ANGLE 1.8f // 基本步距角(度)
#define STEPS_PER_REV 200 // 每转步数 (360/1.8)
// 计算实际步距角和每转步数
#define ACTUAL_STEP_ANGLE (STEP_ANGLE / MICROSTEPPING)
#define ACTUAL_STEPS_PER_REV (STEPS_PER_REV * MICROSTEPPING)
// 机械参数 (根据实际云台结构设置)
#define SCREW_LEAD 5.0f // 丝杠导程(mm/转)
#define STEPS_PER_MM (ACTUAL_STEPS_PER_REV / SCREW_LEAD)
// 引脚定义
#define X_STEP_PIN GPIO_Pin_6
#define X_STEP_PORT GPIOA
#define X_DIR_PIN GPIO_Pin_7
#define X_DIR_PORT GPIOA
#define X_EN_PIN GPIO_Pin_0
#define X_EN_PORT GPIOB
#define Y_STEP_PIN GPIO_Pin_6
#define Y_STEP_PORT GPIOB
#define Y_DIR_PIN GPIO_Pin_7
#define Y_DIR_PORT GPIOB
#define Y_EN_PIN GPIO_Pin_1
#define Y_EN_PORT GPIOB
// 运动控制结构体
typedef struct {
volatile int32_t target_steps; // 目标步数
volatile int32_t current_steps; // 当前步数
volatile uint16_t frequency; // 脉冲频率(Hz)
volatile uint8_t moving; // 运动标志
TIM_TypeDef* TIMx; // 定时器指针
} StepperAxis;
StepperAxis x_axis, y_axis;
// 延时函数
void Delay_ms(uint32_t ms) {
for(uint32_t i = 0; i < ms * 7200; i++);
}
// GPIO初始化
void GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
// 配置X轴步进引脚为复用推挽输出
GPIO_InitStructure.GPIO_Pin = X_STEP_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(X_STEP_PORT, &GPIO_InitStructure);
// 配置X轴方向和控制引脚为推挽输出
GPIO_InitStructure.GPIO_Pin = X_DIR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(X_DIR_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = X_EN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(X_EN_PORT, &GPIO_InitStructure);
// 配置Y轴步进引脚为复用推挽输出
GPIO_InitStructure.GPIO_Pin = Y_STEP_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(Y_STEP_PORT, &GPIO_InitStructure);
// 配置Y轴方向和控制引脚为推挽输出
GPIO_InitStructure.GPIO_Pin = Y_DIR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(Y_DIR_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Y_EN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(Y_EN_PORT, &GPIO_InitStructure);
// 使能电机 (高电平使能)
GPIO_SetBits(X_EN_PORT, X_EN_PIN);
GPIO_SetBits(Y_EN_PORT, Y_EN_PIN);
}
// 定时器配置
void TIM_Config(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4, ENABLE);
// 通用定时器配置
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 1000 - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 1MHz计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// 配置X轴定时器 (TIM3)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 50%占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
// 配置Y轴定时器 (TIM4)
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
// 配置中断
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3, DISABLE);
TIM_Cmd(TIM4, DISABLE);
}
// 步进电机控制函数
void Stepper_Move(StepperAxis* axis, int32_t steps, uint16_t freq) {
if(steps == 0) return; // 无移动
// 设置方向
if(axis == &x_axis) {
GPIO_WriteBit(X_DIR_PORT, X_DIR_PIN, (steps > 0) ? Bit_SET : Bit_RESET);
} else {
GPIO_WriteBit(Y_DIR_PORT, Y_DIR_PIN, (steps > 0) ? Bit_SET : Bit_RESET);
}
// 设置运动参数
axis->target_steps = abs(steps);
axis->current_steps = 0;
axis->frequency = freq;
axis->moving = 1;
// 计算ARR值 (ARR = 1e6 / freq - 1)
uint32_t arr_val = (1000000 / freq) - 1;
if(arr_val < 10) arr_val = 10; // 防止过小
// 使用库函数设置定时器参数
TIM_SetAutoreload(axis->TIMx, arr_val);
TIM_SetCounter(axis->TIMx, 0); // 重置计数器
// 启动定时器
TIM_Cmd(axis->TIMx, ENABLE);
}
// 停止电机
void Stepper_Stop(StepperAxis* axis) {
TIM_Cmd(axis->TIMx, DISABLE);
axis->moving = 0;
axis->target_steps = 0;
axis->current_steps = 0;
}
// 检查是否运动完成
uint8_t Motion_Complete(void) {
return (x_axis.moving == 0) && (y_axis.moving == 0);
}
// 定时器中断处理
void TIM3_IRQHandler(void) {
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
if(x_axis.current_steps < x_axis.target_steps) {
x_axis.current_steps++;
} else {
Stepper_Stop(&x_axis);
}
}
}
void TIM4_IRQHandler(void) {
if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
if(y_axis.current_steps < y_axis.target_steps) {
y_axis.current_steps++;
} else {
Stepper_Stop(&y_axis);
}
}
}
// 画圆函数
void Draw_Circle(float radius_mm, uint16_t speed) {
const uint16_t segments = 200; // 圆的分段数
float angle_step = 2.0f * MPI / segments;
float last_x = radius_mm, last_y = 0;
for(int i = 1; i <= segments; i++) {
float angle = i * angle_step;
float x = radius_mm * cosf(angle);
float y = radius_mm * sinf(angle);
// 计算增量 (mm)
float dx = x - last_x;
float dy = y - last_y;
// 转换为步数 (考虑细分)
int32_t x_steps = (int32_t)(dx * STEPS_PER_MM);
int32_t y_steps = (int32_t)(dy * STEPS_PER_MM);
// 启动双轴运动
Stepper_Move(&x_axis, x_steps, speed);
Stepper_Move(&y_axis, y_steps, speed);
// 等待运动完成
while(!Motion_Complete());
last_x = x;
last_y = y;
}
}
// 移动到指定位置
void Move_To_Position(float x_mm, float y_mm, uint16_t speed) {
// 转换为步数
int32_t x_steps = (int32_t)(x_mm * STEPS_PER_MM);
int32_t y_steps = (int32_t)(y_mm * STEPS_PER_MM);
// 启动运动
Stepper_Move(&x_axis, x_steps, speed);
Stepper_Move(&y_axis, y_steps, speed);
// 等待完成
while(!Motion_Complete());
}
//// 主函数
//int main(void) {
// // 系统初始化
// SystemClock_Config();
// GPIO_Config();
// TIM_Config();
//
// // 初始化轴结构体
// x_axis.TIMx = TIM3;
// y_axis.TIMx = TIM4;
// x_axis.moving = 0;
// y_axis.moving = 0;
//
// // 设置初始位置
// float current_x = 0, current_y = 0;
//
// while(1) {
// // 示例动作序列
// Move_To_Position(30.0f, 30.0f, 1500); // 移动到(30,30)
// Delay_ms(1000);
//
// Draw_Circle(20.0f, 2000); // 画半径20mm的圆
// Delay_ms(1000);
//
// Move_To_Position(0.0f, 0.0f, 1500); // 返回原点
// Delay_ms(2000);
// }
//}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line) {
while(1);
}
#endif
使用库函数,不能直接操作寄存器
最新发布