#include "stm32f10x.h" /************************** 引脚与参数定义 **************************/ // 循迹传感器引脚(PA0~PA4 → ADC通道0~4) #define SENSOR_CH1 ADC_Channel_0 #define SENSOR_CH2 ADC_Channel_1 #define SENSOR_CH3 ADC_Channel_2 #define SENSOR_CH4 ADC_Channel_3 #define SENSOR_CH5 ADC_Channel_4 // TB6612方向引脚定义 #define AIN1_PIN GPIO_Pin_5 // 左电机方向控制1(PA5) #define AIN2_PIN GPIO_Pin_6 // 左电机方向控制2(PA6) #define BIN1_PIN GPIO_Pin_0 // 右电机方向控制1(PB0) #define BIN2_PIN GPIO_Pin_1 // 右电机方向控制2(PB1) #define AIN_PORT GPIOA // 左电机方向端口 #define BIN_PORT GPIOB // 右电机方向端口 // TB6612 PWM引脚定义(3.9kHz,50%占空比) #define PWM_LEFT_TIM TIM3 // 左电机PWM定时器 #define PWM_RIGHT_TIM TIM2 // 右电机PWM定时器 #define PWM_PERIOD 255 // PWM周期(0~255) #define PWM_DUTY 128 // 占空比50%(128/255) #define ADC_THRESHOLD 2000 // ADC阈值(需校准) /************************** 全局变量 **************************/ uint8_t sensor_data[5] = {0}; // 传感器状态:1=黑线,0=白线 /************************** 函数声明 **************************/ void SystemInit(void); // 系统初始化(启动文件调用) void SystemClock_Config(void); // 时钟配置(72MHz) void GPIO_Config(void); // GPIO初始化 void ADC_Config(void); // ADC初始化 void TIM_Config(void); // PWM定时器初始化 void Read_Sensor(void); // 读取传感器数据 void Motor_Forward(void); // 前进 void Motor_Left(void); // 左转 void Motor_Right(void); // 右转 void Motor_Stop(void); // 停车 void Delay_ms(uint32_t ms); // 毫秒延时 /************************** 系统时钟配置(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); // PLL倍频9倍(8MHz→72MHz) RCC_PLLCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 设置系统时钟为PLL输出 RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB时钟=系统时钟 RCC_PCLK1Config(RCC_HCLK_Div2); // APB1时钟=36MHz RCC_PCLK2Config(RCC_HCLK_Div1); // APB2时钟=72MHz SystemCoreClockUpdate(); // 更新系统时钟变量 } /************************** GPIO初始化 **************************/ void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); // 1. TB6612方向引脚配置(推挽输出) GPIO_InitStructure.GPIO_Pin = AIN1_PIN | AIN2_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(AIN_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = BIN1_PIN | BIN2_PIN; GPIO_Init(BIN_PORT, &GPIO_InitStructure); // 2. 传感器引脚配置(模拟输入) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // 3. PWM引脚配置(复用推挽输出) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; // PA7 → TIM3_CH2(左电机PWM) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // PB3 → TIM2_CH3(右电机PWM) GPIO_Init(GPIOB, &GPIO_InitStructure); } /************************** ADC初始化(5路传感器) **************************/ void ADC_Config(void) { ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // ADC基本配置 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 多通道扫描 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐 ADC_InitStructure.ADC_NbrOfChannel = 5; // 5通道 ADC_Init(ADC1, &ADC_InitStructure); // 配置5路传感器通道(采样时间55.5周期) ADC_RegularChannelConfig(ADC1, SENSOR_CH1, 1, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, SENSOR_CH2, 2, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, SENSOR_CH3, 3, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, SENSOR_CH4, 4, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, SENSOR_CH5, 5, ADC_SampleTime_55Cycles5); // 使能ADC并校准 ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); } /************************** PWM定时器初始化 **************************/ void TIM_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 使能定时器时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); // 左电机PWM(TIM3_CH2,PA7) TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; // 周期255 TIM_TimeBaseStructure.TIM_Prescaler = 71; // 72MHz/72=1MHz TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = PWM_DUTY; // 50%占空比 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM3, ENABLE); TIM_Cmd(TIM3, ENABLE); // 右电机PWM(TIM2_CH3,PB3) TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; TIM_TimeBaseStructure.TIM_Prescaler = 71; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = PWM_DUTY; // 50%占空比 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM_Cmd(TIM2, ENABLE); } /************************** 读取传感器数据 **************************/ void Read_Sensor(void) { uint16_t adc_val; ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 启动ADC转换 while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待转换完成 // 依次读取5路传感器ADC值并判断黑白线 adc_val = ADC_GetConversionValue(ADC1); // 最左传感器 sensor_data[0] = (adc_val > ADC_THRESHOLD) ? 1 : 0; adc_val = ADC_GetConversionValue(ADC1); // 左传感器 sensor_data[1] = (adc_val > ADC_THRESHOLD) ? 1 : 0; adc_val = ADC_GetConversionValue(ADC1); // 中间传感器 sensor_data[2] = (adc_val > ADC_THRESHOLD) ? 1 : 0; adc_val = ADC_GetConversionValue(ADC1); // 右传感器 sensor_data[3] = (adc_val > ADC_THRESHOLD) ? 1 : 0; adc_val = ADC_GetConversionValue(ADC1); // 最右传感器 sensor_data[4] = (adc_val > ADC_THRESHOLD) ? 1 : 0; } /************************** 电机控制函数 **************************/ // 前进(双电机正转,50%占空比) void Motor_Forward(void) { // 方向控制:左电机AIN1=高,AIN2=低;右电机BIN1=高,BIN2=低 GPIO_SetBits(AIN_PORT, AIN1_PIN); GPIO_ResetBits(AIN_PORT, AIN2_PIN); GPIO_SetBits(BIN_PORT, BIN1_PIN); GPIO_ResetBits(BIN_PORT, BIN2_PIN); // 设置PWM占空比50% TIM_SetCompare2(PWM_LEFT_TIM, PWM_DUTY); TIM_SetCompare3(PWM_RIGHT_TIM, PWM_DUTY); } // 左转(左电机50%,右电机25%占空比) void Motor_Left(void) { Motor_Forward(); // 继承前进方向 TIM_SetCompare2(PWM_LEFT_TIM, PWM_DUTY); // 左电机全速 TIM_SetCompare3(PWM_RIGHT_TIM, PWM_DUTY/2); // 右电机半速 } // 右转(右电机50%,左电机25%占空比) void Motor_Right(void) { Motor_Forward(); // 继承前进方向 TIM_SetCompare2(PWM_LEFT_TIM, PWM_DUTY/2); // 左电机半速 TIM_SetCompare3(PWM_RIGHT_TIM, PWM_DUTY); // 右电机全速 } // 停车(PWM=0,方向引脚低电平) void Motor_Stop(void) { GPIO_ResetBits(AIN_PORT, AIN1_PIN | AIN2_PIN); GPIO_ResetBits(BIN_PORT, BIN1_PIN | BIN2_PIN); TIM_SetCompare2(PWM_LEFT_TIM, 0); TIM_SetCompare3(PWM_RIGHT_TIM, 0); } /************************** 毫秒延时函数 **************************/ void Delay_ms(uint32_t ms) { uint32_t i, j; for(i = 0; i < ms; i++) for(j = 0; j < 7200; j++); // 72MHz下约1ms(需校准) } /************************** 主函数 **************************/ int main(void) { SystemClock_Config(); // 配置72MHz系统时钟 GPIO_Config(); // 初始化GPIO ADC_Config(); // 初始化ADC TIM_Config(); // 初始化PWM定时器 while (1) { Read_Sensor(); // 读取传感器状态 // 循迹逻辑判断 if (sensor_data[2]) { // 中间传感器检测到黑线 → 前进 Motor_Forward(); } else if (sensor_data[0] || sensor_data[1]) { // 左侧检测到 → 右转 Motor_Right(); } else if (sensor_data[3] || sensor_data[4]) { // 右侧检测到 → 左转 Motor_Left(); } else { // 无黑线 → 停车 Motor_Stop(); } Delay_ms(50); // 50ms控制周期(20Hz) } }将这个改进
时间: 2025-06-12 09:48:03 浏览: 29
### 优化STM32F10x循迹小车代码的策略
在改进基于STM32F10x的循迹小车代码时,可以从性能调优和代码可读性两个方面入手。以下是一些具体的优化方法:
#### 1. 性能调优
通过使用Keil μVision提供的工具来分析程序性能,可以显著提升程序的运行效率。
- **性能分析**:利用“Performance Analyzer”功能,在调试模式下监控程序执行时间消耗,找出耗时较长的函数或代码段[^1]。根据分析结果,对这些部分进行针对性优化。
- **代码覆盖率**:通过“Code Coverage”功能检查代码覆盖率,确保所有逻辑分支都被测试到[^1]。未覆盖的代码可能是潜在的性能瓶颈或错误来源。
#### 2. 硬件与软件结合优化
- **外设配置优化**:合理配置定时器、PWM输出等外设参数,减少不必要的中断和服务时间。例如,调整TIMx的预分频值以匹配电机控制频率。
- **DMA传输**:对于数据量较大的操作(如ADC采样或串口通信),尽量使用DMA代替轮询方式,从而释放CPU资源[^2]。
#### 3. 提高代码可读性
清晰的代码结构不仅便于维护,还能间接提升开发效率。
- **模块化设计**:将不同功能划分为独立的模块,例如电机驱动、循迹传感器处理、避障逻辑等。每个模块应具有明确的输入输出接口[^2]。
```c
// 示例:模块化函数定义
void motor_control(int speed_left, int speed_right);
uint8_t track_sensor_read(void);
void obstacle_avoidance(void);
```
- **注释与文档**:为关键算法和复杂逻辑添加详细注释,说明其工作原理及参数含义。同时,编写简要的设计文档,概述系统架构和各模块交互关系。
- **统一命名规范**:采用一致的变量、函数命名规则,避免混淆。推荐使用描述性强的名字,如`sensor_value`而非`s_val`。
#### 4. 算法优化
- **路径规划算法**:如果当前使用的路径规划较为简单,可以考虑引入更高效的算法,如PID控制用于速度调节,A*或Dijkstra算法用于全局路径规划[^2]。
- **传感器数据处理**:优化循迹传感器的数据处理流程,减少冗余计算。例如,使用滑动平均滤波平滑传感器读数,降低噪声影响。
```c
// 示例:滑动平均滤波实现
#define FILTER_SIZE 5
static uint16_t filter_buffer[FILTER_SIZE];
static uint8_t filter_index = 0;
uint16_t smooth_sensor_value(uint16_t new_value) {
filter_buffer[filter_index++] = new_value;
if (filter_index >= FILTER_SIZE) filter_index = 0;
uint16_t sum = 0;
for (int i = 0; i < FILTER_SIZE; i++) sum += filter_buffer[i];
return sum / FILTER_SIZE;
}
```
#### 5. 编译器优化选项
合理设置编译器优化级别,可以在一定程度上提高程序运行效率。通常,`-O2`或`-Os`是不错的选择,前者侧重整体性能优化,后者则优先考虑代码尺寸。
---
###
阅读全文
相关推荐



















