OC全局宏配置路径

在TARGETS->Build Settings->Apple LLVM 7.0 - Language 项目 Prefix Header

 $(SRCROOT)/项目明细/文件名.pch

  • Precompile Prefix HeaderYES,那么pch会被预编译,预编译后的pch文件会被缓存起来,从而提高编译速度。当 Precompile Prefix Header 为NO时,那么pch不会被预编译,而是在每一个用到它导入的框架类库的.m文件中编译一次。
  • $(SRCROOT)代表你工程根目录,无需更改。后面分别是你的项目名称以及你的pch文件名


#include “stm32f10x.h” #include “math.h” #include “delay.h” // 舵机参数定义 #define PWM_PERIOD 20000 // 20ms周期 #define MIN_PULSE 500 // 0.5ms脉冲宽度 #define MAX_PULSE 2500 // 2.5ms脉冲宽度 #define ANGLE_RANGE 270.0f // 舵机角度范围 // 云台参数 #define CENTER_X 135.0f // 水平中心角度 #define CENTER_Y 135.0f // 垂直中心角度 #define RECT_WIDTH 10.0f // 矩形宽度 #define RECT_HEIGHT 10.0f // 矩形高度 #define STEPS_PER_SIDE 100 // 每条边的步数 // 函数声明 void PWM_Init(void); void Set_Servo_Angle(uint8_t servo_id, float angle); float LinearInterpolate(float start, float end, float ratio); void MoveToPoint(float x, float y, uint16_t steps); void DrawRectangle(void); // 确保起点终点重合的完整矩形 void Go_To_Center(uint16_t steps); // 当前位置存储全局变量) float current_x = CENTER_X; float current_y = CENTER_Y; /** 函 数:PWM初始化 / void PWM_Init(void) { / 开启时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /* GPIO初始化 */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置时钟源 */ TIM_InternalClockConfig(TIM2); /* 时基单元初始化 */ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = PWM_PERIOD - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); /* 输出比较初始化 */ TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_Cmd(TIM2, ENABLE); } /** 函 数:设置舵机角度 */ void Set_Servo_Angle(uint8_t servo_id, float angle) { if (angle < 0) angle = 0; if (angle > ANGLE_RANGE) angle = ANGLE_RANGE; uint16_t pulse = MIN_PULSE + (uint16_t)((MAX_PULSE - MIN_PULSE) * angle / ANGLE_RANGE); switch(servo_id) { case 0: TIM_SetCompare2(TIM2, pulse); break; case 1: TIM_SetCompare3(TIM2, pulse); break; } } /** 函 数:线性插值 */ float LinearInterpolate(float start, float end, float ratio) { return start + ratio * (end - start); } /** 函 数:移动到指定点 */ void MoveToPoint(float x, float y, uint16_t steps) { for (uint16_t i = 0; i <= steps; i++) { float ratio = (float)i / steps; float interp_x = LinearInterpolate(current_x, x, ratio); float interp_y = LinearInterpolate(current_y, y, ratio); Set_Servo_Angle(0, interp_x); Set_Servo_Angle(1, interp_y); delay_ms(2); } current_x = x; current_y = y; } /** 函 数:云台归中 */ void Go_To_Center(uint16_t steps) { MoveToPoint(CENTER_X, CENTER_Y, steps); } /** 函 数:绘制完整矩形(起点和终点重合) */ void DrawRectangle(void) { // 计算矩形的四个顶点 float top_left_x = CENTER_X - RECT_WIDTH/2; float top_left_y = CENTER_Y - RECT_HEIGHT/2; float top_right_x = CENTER_X + RECT_WIDTH/2; float top_right_y = CENTER_Y - RECT_HEIGHT/2; float bottom_right_x = CENTER_X + RECT_WIDTH/2; float bottom_right_y = CENTER_Y + RECT_HEIGHT/2; float bottom_left_x = CENTER_X - RECT_WIDTH/2; float bottom_left_y = CENTER_Y + RECT_HEIGHT/2; // 绘制完整矩形路径(4条边) MoveToPoint(top_left_x, top_left_y, STEPS_PER_SIDE); // 起点:左上角 MoveToPoint(top_right_x, top_right_y, STEPS_PER_SIDE); // 右上角 MoveToPoint(bottom_right_x, bottom_right_y, STEPS_PER_SIDE); // 右下角 MoveToPoint(bottom_left_x, bottom_left_y, STEPS_PER_SIDE); // 左下角 MoveToPoint(top_left_x, top_left_y, STEPS_PER_SIDE); // 终点:返回起点(左上角) } 我在云台上加了一个激光灯,请在此代码的基础上,补充代码,添加一个可以控制激光灯亮灭的代码
最新发布
07-30
<think>我们将在代码中添加控制激光灯的GPIO初始化函数和激光灯控制函数。 假设激光灯连接在GPIOA的Pin3上,使用推挽输出模式。 步骤: 1. 添加激光灯的宏定义(引脚和端口) 2. 在PWM_Init函数中初始化激光灯的GPIO(或者单独写一个激光灯初始化函数) 3. 编写激光灯控制函数(开和关) 4. 在需要的地方调用激光灯控制函数(例如在绘制矩形时开启激光,绘制完毕关闭激光) 修改后的代码:</think>### 添加激光灯控制代码 以下是修改后的代码,添加了激光灯的控制功能: ```c #include "stm32f10x.h" #include "math.h" #include "delay.h" // 舵机参数定义 #define PWM_PERIOD 20000 // 20ms周期 #define MIN_PULSE 500 // 0.5ms脉冲宽度 #define MAX_PULSE 2500 // 2.5ms脉冲宽度 #define ANGLE_RANGE 270.0f // 舵机角度范围 // 云台参数 #define CENTER_X 135.0f // 水平中心角度 #define CENTER_Y 135.0f // 垂直中心角度 #define RECT_WIDTH 10.0f // 矩形宽度 #define RECT_HEIGHT 10.0f // 矩形高度 #define STEPS_PER_SIDE 100 // 每条边的步数 // 激光灯控制引脚定义 #define LASER_PIN GPIO_Pin_3 #define LASER_PORT GPIOA // 函数声明 void PWM_Init(void); void Laser_Init(void); // 新增激光灯初始化 void Laser_On(void); // 新增激光开启 void Laser_Off(void); // 新增激光关闭 void Set_Servo_Angle(uint8_t servo_id, float angle); float LinearInterpolate(float start, float end, float ratio); void MoveToPoint(float x, float y, uint16_t steps); void DrawRectangle(uint8_t laser_enable); // 修改为可控制激光 void Go_To_Center(uint16_t steps); // 当前位置存储全局变量) float current_x = CENTER_X; float current_y = CENTER_Y; /** * 函 数:PWM初始化 */ void PWM_Init(void) { /* 开启时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /* GPIO初始化 */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置时钟源 */ TIM_InternalClockConfig(TIM2); /* 时基单元初始化 */ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = PWM_PERIOD - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); /* 输出比较初始化 */ TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_Cmd(TIM2, ENABLE); } /** * 函 数:激光灯初始化 */ void Laser_Init(void) { /* 开启GPIOA时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* 配置激光灯引脚为推挽输出 */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = LASER_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LASER_PORT, &GPIO_InitStructure); /* 初始状态关闭激光 */ GPIO_ResetBits(LASER_PORT, LASER_PIN); } /** * 函 数:开启激光灯 */ void Laser_On(void) { GPIO_SetBits(LASER_PORT, LASER_PIN); } /** * 函 数:关闭激光灯 */ void Laser_Off(void) { GPIO_ResetBits(LASER_PORT, LASER_PIN); } /** * 函 数:设置舵机角度 */ void Set_Servo_Angle(uint8_t servo_id, float angle) { if (angle < 0) angle = 0; if (angle > ANGLE_RANGE) angle = ANGLE_RANGE; uint16_t pulse = MIN_PULSE + (uint16_t)((MAX_PULSE - MIN_PULSE) * angle / ANGLE_RANGE); switch(servo_id) { case 0: TIM_SetCompare2(TIM2, pulse); break; case 1: TIM_SetCompare3(TIM2, pulse); break; } } /** * 函 数:线性插值 */ float LinearInterpolate(float start, float end, float ratio) { return start + ratio * (end - start); } /** * 函 数:移动到指定点 */ void MoveToPoint(float x, float y, uint16_t steps) { for (uint16_t i = 0; i <= steps; i++) { float ratio = (float)i / steps; float interp_x = LinearInterpolate(current_x, x, ratio); float interp_y = LinearInterpolate(current_y, y, ratio); Set_Servo_Angle(0, interp_x); Set_Servo_Angle(1, interp_y); delay_ms(2); } current_x = x; current_y = y; } /** * 函 数:云台归中 */ void Go_To_Center(uint16_t steps) { MoveToPoint(CENTER_X, CENTER_Y, steps); } /** * 函 数:绘制完整矩形(带激光控制) * 参 数:laser_enable - 是否开启激光 (1:开启, 0:关闭) */ void DrawRectangle(uint8_t laser_enable) { // 计算矩形的四个顶点 float top_left_x = CENTER_X - RECT_WIDTH/2; float top_left_y = CENTER_Y - RECT_HEIGHT/2; float top_right_x = CENTER_X + RECT_WIDTH/2; float top_right_y = CENTER_Y - RECT_HEIGHT/2; float bottom_right_x = CENTER_X + RECT_WIDTH/2; float bottom_right_y = CENTER_Y + RECT_HEIGHT/2; float bottom_left_x = CENTER_X - RECT_WIDTH/2; float bottom_left_y = CENTER_Y + RECT_HEIGHT/2; // 根据参数控制激光状态 if(laser_enable) { Laser_On(); // 开启激光 } else { Laser_Off(); // 关闭激光 } // 绘制完整矩形路径 MoveToPoint(top_left_x, top_left_y, STEPS_PER_SIDE); // 起点:左上角 MoveToPoint(top_right_x, top_right_y, STEPS_PER_SIDE); // 右上角 MoveToPoint(bottom_right_x, bottom_right_y, STEPS_PER_SIDE); // 右下角 MoveToPoint(bottom_left_x, bottom_left_y, STEPS_PER_SIDE); // 左下角 MoveToPoint(top_left_x, top_left_y, STEPS_PER_SIDE); // 终点:返回起点 } /** * 函 数:主函数 */ int main(void) { delay_init(); PWM_Init(); Laser_Init(); // 初始化激光灯 // 初始位置归中 Go_To_Center(50); delay_ms(500); while(1) { // 带激光绘制矩形 DrawRectangle(1); // 参数1表示开启激光 // 停留1秒(激光保持开启) delay_ms(1000); // 关闭激光并归中 Laser_Off(); Go_To_Center(100); // 不带激光绘制矩形(仅运动) DrawRectangle(0); // 参数0表示关闭激光 // 停留1秒 delay_ms(1000); // 激光闪烁效果 for(int i = 0; i < 5; i++) { Laser_On(); delay_ms(100); Laser_Off(); delay_ms(100); } } } ``` ### 关键修改说明: #### 1. 激光灯硬件配置 ```c // 激光灯控制引脚定义 #define LASER_PIN GPIO_Pin_3 #define LASER_PORT GPIOA ``` - 假设激光灯连接在GPIOA的Pin3上 - 可根据实际硬件连接修改引脚定义 #### 2. 激光灯初始化函数 ```c void Laser_Init(void) { /* 开启GPIOA时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* 配置激光灯引脚为推挽输出 */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = LASER_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LASER_PORT, &GPIO_InitStructure); /* 初始状态关闭激光 */ GPIO_ResetBits(LASER_PORT, LASER_PIN); } ``` - 初始化GPIO为推挽输出模式 - 初始状态设置为低电平(激光关闭) #### 3. 激光控制函数 ```c // 开启激光 void Laser_On(void) { GPIO_SetBits(LASER_PORT, LASER_PIN); } // 关闭激光 void Laser_Off(void) { GPIO_ResetBits(LASER_PORT, LASER_PIN); } ``` - 提供简单的开关接口 - 可直接在主程序或中断中调用 #### 4. 矩形绘制函数增强 ```c void DrawRectangle(uint8_t laser_enable) { // 根据参数控制激光状态 if(laser_enable) { Laser_On(); // 开启激光 } else { Laser_Off(); // 关闭激光 } // ...绘制矩形路径... } ``` - 添加`laser_enable`参数控制激光状态 - 在绘制前设置激光状态 - 保持激光状态直到绘制完成 #### 5. 主函数逻辑优化 ```c int main(void) { // ...初始化... while(1) { // 带激光绘制矩形 DrawRectangle(1); // 开启激光 // 停留1秒(激光保持开启) delay_ms(1000); // 关闭激光并归中 Laser_Off(); Go_To_Center(100); // 不带激光绘制矩形(仅运动) DrawRectangle(0); // 关闭激光 // 激光闪烁效果 for(int i = 0; i < 5; i++) { Laser_On(); delay_ms(100); Laser_Off(); delay_ms(100); } } } ``` - 演示多种激光控制模式 - 交替进行带激光和不带激光的绘制 - 添加闪烁效果展示 ### 激光控制模式示例: 1. **持续开启模式**: ```c // 绘制过程中持续开启激光 DrawRectangle(1); ``` 2. **闪烁模式**: ```c // 绘制时激光闪烁 for(int i = 0; i < 4; i++) { Laser_On(); MoveToPoint(/* 一段路径 */); Laser_Off(); MoveToPoint(/* 下一段路径 */); } ``` 3. **脉冲模式**: ```c // 以特定频率脉冲激光 for(int step = 0; step < steps; step++) { if(step % 10 == 0) Laser_On(); if(step % 10 == 5) Laser_Off(); // 移动云台... } ``` 4. **外部触发模式**: ```c // 通过按键控制激光 if(GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN)) { Laser_On(); } else { Laser_Off(); } ``` ### 硬件连接建议: 1. **激光模块接线**: - VCC: 3.3V/5V (根据激光模块规格) - GND: 接地 - SIG: 连接至GPIOA_Pin3 2. **电流考虑**: ```c // 如果激光功率较大,建议通过晶体管驱动 // 修改GPIO初始化: GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出 ``` - 大功率激光需使用外部电源和MOSFET驱动 - STM32 GPIO最大驱动电流约20mA 3. **保护电路**: - 在激光模块VCC端添加100μF电容 - 在GPIO和激光模块间添加100Ω限流电阻 ### 应用场景扩展: 1. **激光雕刻**: ```c void DrawText(char* text) { Laser_Off(); // 移动到起点 Laser_On(); // 绘制字符路径 } ``` 2. **激光指示演示**: ```c void PointAtTarget(float x, float y) { Laser_On(); MoveToPoint(x, y, 50); delay_ms(2000); Laser_Off(); } ``` 3. **安全激光幕**: ```c void SecurityScan() { Laser_On(); // 水平扫描 for(float x = 90; x <= 180; x += 0.5) { Set_Servo_Angle(0, x); delay_ms(10); } Laser_Off(); } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值