#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "math.h"
#include <stdio.h>
#include <stdlib.h>
#include "delay.h"
// 定义π常量
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// 步进电机参数
#define STEPS_PER_REV 200 // 步距角1.8° (360/1.8=200步/圈)
#define MICROSTEPS 16 // D36A驱动器细分设置
#define FULL_STEPS (STEPS_PER_REV * MICROSTEPS) // 每圈总步数
// 云台几何参数
#define BASE_DISTANCE 500.0f // 基准距离50cm (单位mm)
#define TARGET_RADIUS 60.0f // 画圆半径6cm
// 引脚定义
// 水平电机控制
#define HORIZ_DIR_GPIO GPIOB
#define HORIZ_DIR_PIN GPIO_Pin_12
#define HORIZ_STEP_GPIO GPIOB
#define HORIZ_STEP_PIN GPIO_Pin_13
#define HORIZ_EN_GPIO GPIOB
#define HORIZ_EN_PIN GPIO_Pin_14
// 垂直电机控制
#define VERT_DIR_GPIO GPIOB
#define VERT_DIR_PIN GPIO_Pin_15
#define VERT_STEP_GPIO GPIOA
#define VERT_STEP_PIN GPIO_Pin_8
#define VERT_EN_GPIO GPIOA
#define VERT_EN_PIN GPIO_Pin_1
// 激光控制
#define LASER_GPIO GPIOA
#define LASER_PIN GPIO_Pin_0
// 摄像头数据
volatile int targetX = 0; // 靶心X坐标 (像素)
volatile int targetY = 0; // 靶心Y坐标 (像素)
volatile float distance = 0.0f; // 当前云台到靶面距离
// 电机当前位置 (步数) - volatile声明
volatile int32_t horizPos = 0;
volatile int32_t vertPos = 0;
// 延时函数
void Delay(uint32_t nCount) {
for(; nCount != 0; nCount--);
}
// 初始化GPIO
void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
// 水平电机控制引脚
GPIO_InitStructure.GPIO_Pin = HORIZ_DIR_PIN | HORIZ_STEP_PIN | HORIZ_EN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 垂直电机控制引脚
GPIO_InitStructure.GPIO_Pin = VERT_STEP_PIN | VERT_EN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 垂直电机方向引脚 (PB15)
GPIO_InitStructure.GPIO_Pin = VERT_DIR_PIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 激光控制引脚
GPIO_InitStructure.GPIO_Pin = LASER_PIN;
GPIO_Init(LASER_GPIO, &GPIO_InitStructure);
// 使能电机
GPIO_SetBits(HORIZ_EN_GPIO, HORIZ_EN_PIN);
GPIO_SetBits(VERT_EN_GPIO, VERT_EN_PIN);
// 关闭激光
GPIO_ResetBits(LASER_GPIO, LASER_PIN);
}
// 初始化定时器
void TIM_Configuration(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 使能定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4, ENABLE);
// 水平电机定时器配置
TIM_TimeBaseStructure.TIM_Period = 1000;
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// 垂直电机定时器配置
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
}
// 初始化串口
void USART_Configuration(void) {
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// USART1 TX (PA9)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART1 RX (PA10)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART配置
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
// 使能串口中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_EnableIRQ(USART1_IRQn);
USART_Cmd(USART1, ENABLE);
}
// 移动步进电机 (修正volatile指针问题)
void moveStepper(TIM_TypeDef* TIMx, GPIO_TypeDef* dirGPIO, uint16_t dirPin,
volatile int32_t* currentPos, int32_t targetSteps, uint16_t speed) {
// 设置方向
if (targetSteps > *currentPos) {
GPIO_SetBits(dirGPIO, dirPin);
} else {
GPIO_ResetBits(dirGPIO, dirPin);
}
// 计算需要移动的步数
int32_t steps = abs(targetSteps - *currentPos);
// 生成脉冲
for (int i = 0; i < steps; i++) {
GPIO_SetBits((TIMx == TIM3) ? HORIZ_STEP_GPIO : VERT_STEP_GPIO,
(TIMx == TIM3) ? HORIZ_STEP_PIN : VERT_STEP_PIN);
Delay(10); // 脉冲宽度
GPIO_ResetBits((TIMx == TIM3) ? HORIZ_STEP_GPIO : VERT_STEP_GPIO,
(TIMx == TIM3) ? HORIZ_STEP_PIN : VERT_STEP_PIN);
// 速度控制延时
Delay(speed);
}
// 更新位置
*currentPos = targetSteps;
}
// 计算靶心坐标对应的电机步数
void calculateTargetPosition(float targetX, float targetY, float dist,
int32_t* horizSteps, int32_t* vertSteps) {
// 角度计算 (弧度)
float horizAngle = atan2f(targetX, dist);
float vertAngle = atan2f(targetY, dist);
// 转换为步数
*horizSteps = (int32_t)(horizAngle * (180.0f / M_PI) * FULL_STEPS / 360.0f);
*vertSteps = (int32_t)(vertAngle * (180.0f / M_PI) * FULL_STEPS / 360.0f);
}
// 瞄准靶心
void aimAtTarget(void) {
int32_t targetHorizSteps, targetVertSteps;
// 计算靶心位置对应的步数
calculateTargetPosition(targetX, targetY, distance,
&targetHorizSteps, &targetVertSteps);
// 移动云台 (修正volatile指针传递)
moveStepper(TIM3, HORIZ_DIR_GPIO, HORIZ_DIR_PIN,
&horizPos, targetHorizSteps, 500);
moveStepper(TIM4, VERT_DIR_GPIO, VERT_DIR_PIN,
&vertPos, targetVertSteps, 500);
// 开启激光
GPIO_SetBits(LASER_GPIO, LASER_PIN);
}
// 动态画圆函数
void drawCircle(float radius, uint32_t duration) {
const uint32_t steps = 100;
for (uint32_t i = 0; i <= steps; i++) {
float angle = 2 * M_PI * i / steps;
float targetX = radius * cosf(angle);
float targetY = radius * sinf(angle);
int32_t horizSteps, vertSteps;
calculateTargetPosition(targetX, targetY, distance, &horizSteps, &vertSteps);
moveStepper(TIM3, HORIZ_DIR_GPIO, HORIZ_DIR_PIN,
&horizPos, horizSteps, 200);
moveStepper(TIM4, VERT_DIR_GPIO, VERT_DIR_PIN,
&vertPos, vertSteps, 200);
Delay(duration / steps);
}
}
//// 主函数
//int main(void) {
// // 系统初始化
// SystemInit();
// GPIO_Configuration();
// TIM_Configuration();
// USART_Configuration();
//
// while (1) {
// aimAtTarget();
// delay(2000000);
// drawCircle(TARGET_RADIUS, 20000);
// }
//}
//// 串口中断处理
//void USART1_IRQHandler(void) {
// if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
// static char buffer[32];
// static uint8_t index = 0;
//
// char ch = USART_ReceiveData(USART1);
// if (ch == '\n') {
// buffer[index] = '\0';
// if (sscanf(buffer, "%d,%d,%f", &targetX, &targetY, &distance) != 3) {
// targetX = targetY = 0;
// distance = BASE_DISTANCE;
// }
// index = 0;
// } else if (index < sizeof(buffer) - 1) {
// buffer[index++] = ch;
// } else {
// index = 0;
// }
// USART_ClearITPendingBit(USART1, USART_IT_RXNE);
// }
//}
把该代码写成一个.c文件和一个.h文件,方便外部调用
最新发布