ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

STM32智能停车场项目实战:传感器、状态机与调试指南

STM32智能停车场项目实战:传感器、状态机与调试指南

简介:一套基于STM32F103VET6的智能停车场毕业设计资源,面向嵌入式方向学生,解决停车场无人化管理、远程状态查询与短信控制问题。项目按硬件职责划分为主板、控制台指示板及场内红外检测板,实现了车辆进场自动播报欢迎并升起停车杆、完全驶入后自动降杆,通过红外检测车位占用状态并在控制台与车位处实时显示,屏幕同步呈现可用车位及环境温湿度;同时借助SIM800L模块每1小时短信报告车位情况与近1小时进出车辆数,并支持短信下发控制指令。资源共72个文件,以C语言源码为主(27个.c、30个.h),另含STM32标准外设库、MDK工程文件、链接映射文件、README说明及License等,压缩包仅304KB,项目目录清晰,可直接导入Keil进行编译与烧录验证。当前已有120人学习浏览,适合需要综合运用GPIO、定时器、USART中断和传感器数据处理的毕设开发者。项目还前瞻性地规划了停车计费、冲卡报警与实时时钟短信安排等进阶功能,可作为功能扩展与二次开发的清晰蓝本。

1. 这是什么资源:STM32 智能停车场项目的完整闭环

基于 STM32 的智能停车场,是电子类毕业设计里出场率很高的一个选题。它不像纯 LED 流水灯那么单薄,也不像图像识别那么卷,它恰好卡在一个很舒服的位置:传感器、执行器、人机交互、通信调试四件事全都沾一点,每一件都够你写进论文,但又不会难到做不完。这份 zip 资源给你的是一整套可落地的设计思路,从主控选型到硬件接线,从核心代码到常见故障排查,基本上照着走就能把系统跑起来。适合想把毕设做成“真能演示、能抗住答辩追问”的本科生,也适合想快速搭一套小型停车场样机练手的工程师。

2. 系统架构与主控选型:为什么 STM32F103C8T6 是多数毕设的最优解

我拆过不少毕设项目,发现一个普遍规律:一开始冲劲最足,最容易在选型上摇摆。今天觉得 F407 好,明天又想换国产 GD32,最后光是移植工程就耗掉一半时间。做智能停车场,主控的选择其实可以很干脆——STM32F103C8T6 是大多数情况下的最优解。它不是性能最强的,但它是资料最多、上手路径最成熟、出问题最好查的。

2.1 智能停车场的功能拆分与信号链路

把整个停车场系统拆开看,能分成四个层次。感知层负责判断“有没有车”,入口处用红外对管或超声波模块检测车辆接近,车位上方用超声波测距判断车位是否被占用。控制层跑核心逻辑,比如车到入口、开闸抬杆、车进入后落杆、车位计数更新。执行层就是舵机模拟道闸、LED 指示灯模拟车位状态。人机层则是一块 OLED 或 LCD1602 屏幕,显示剩余车位和计费信息,按键用来模拟取卡入场。如果题目要求联网,还可以加一个 ESP8266,把数据通过串口发到云平台。

信号链路由输入到输出非常清晰:传感器信号进来,经过 GPIO 或定时器捕获,进入逻辑判断,再输出到舵机和屏幕。这条链路越短,排查越容易。反过来看也一样,如果某一步输出不对,从传感器开始往回查,几乎不会走弯路。功能分层还有一个好处,答辩时你可以直接讲“我的系统分四层”,评委一听就知道你不是把代码全塞在 main 里。

2.2 STM32F103C8T6 的关键资源与选型边界

F103C8T6 是 Cortex-M3 内核,主频 72MHz,Flash 64KB,SRAM 20KB。这个配置跑停车场逻辑绰绰有余。它提供 3 个通用定时器加 1 个高级定时器、1 个 12 位 ADC、多个 USART、SPI 和 I2C 接口。超声波测距用定时器输入捕获,舵机用定时器 PWM 输出,OLED 用 I2C 或 SPI,这些外设全部够用,不需要为了凑功能去选更高端的芯片。

选型边界在于,如果题目明确要求摄像头图像识别、大尺寸触摸屏或者以太网,那 F103C8T6 就吃力了,此时建议升到 F103ZET6 或 F407 系列。如果只是停车场这套玩法,升到 F407 只会增加布线和调试成本,课堂演示看不出差别。还需要注意一个细节:F103C8T6 的 Flash 不大,不要在工程里塞全字库或动画 GUI,不然编译器会告诉你空间不够,到那时候改代码很痛苦。

下面是一个常见的模块与外设资源对照表,帮助你在设计阶段就把引脚规划清楚:

功能模块推荐外设关键参数引脚建议
超声波测距 Trig/EchoGPIO/TIM 输入捕获52ms 超时上限PA0/PA1,TIM2_CH1
舵机道闸TIM 通道 PWM50Hz,0.5~2.5ms 脉宽PB0,TIM3_CH3
OLED 显示I2C1地址 0x3C 或 0x78PB8/PB9
串口调试USART2115200-8-N-1PA2/PA3
红外对管GPIO 输入遮挡电平翻转PA4

这张表建议直接贴在电脑前,写代码时对照着初始化引脚,能少踩很多低级坑。

2.3 工程初始化:标准库还是 HAL 库、目录怎么组织

选库的问题我每次都跟学生强调一遍,因为它决定了你后面三个月的效率。用标准库手写,能深入理解寄存器操作,但初始化代码量很大,每换一个外设都要翻阅参考手册。用 HAL 库配合 CubeMX,图形化生成初始化代码,开发效率高,代码结构也更规范。毕设这种时间紧、还要保证演示稳定的场景,我强烈建议 HAL 库加 CubeMX 的组合。

工程目录我一般按三层组织:

Core/ 主函数、中断回调、系统时钟配置 Hardware/ 传感器、舵机、OLED 等外设驱动 App/ 停车场状态机、车位管理、计费逻辑

每个文件夹只放一类东西,排错的时候直接按目录找。比如 OLED 显示出了问题,先看 Hardware 里的驱动函数是否正常,不用去翻 App 层的业务代码。初始化顺序也要固定:先时钟,再 GPIO,然后定时器、中断、串口,最后才初始化传感器。这个顺序一旦乱了,后面极难排查,因为你不知道报错是引脚冲突还是时钟没起振。

3. 硬件接线与传感器落地:五个模块背后的三个共性问题

硬件部分是这个项目里最容易让人抓狂的地方。程序写得再漂亮,接线接错或供电不稳,表现出来就是数据乱跳、反复重启、屏幕花屏。这类问题很难用代码修复,只能靠硬件基本功解决。这一章把停车场核心模块的接线要点和参数边界讲清楚,你照着接就能避开一半的坑。

3.1 HC-SR04 超声波测距:接线、时序与参数边界

HC-SR04 是停车场车位检测最常用的超声波模块,测距范围约 2cm 到 4m,供电 5V,Trig 和 Echo 都是电平信号。工作流程是:Trig 收到一个至少 10us 的高电平脉冲后,模块发送 8 个 40kHz 的方波,随后 Echo 输出一个高电平,高电平持续时间等于超声波往返的总时间。距离与时间的换算公式是距离等于时间乘声速再除以 2,简化计算就是时间差(us)除以 58,得到厘米数,这里取的是声速 340m/s 下的近似值。

接线上有三个注意点。Trig 接任意 GPIO,Echo 必须接到支持输入捕获或外部中断的引脚。由于 HC-SR04 输出高电平是 5V,而 STM32F103 的 GPIO 工作电压是 3.3V,我一般会给 Echo 加一个分压电阻,1k 和 2k 串联,把 5V 分到约 3.3V,避免长期电平倒灌伤引脚。第三,模块的 5V 电源不要和单片机敏感电路混在一起,至少要在模块电源入口并联一个 100uF 电容。

注意:HC-SR04 在测距超时或障碍物太远时,Echo 高电平持续时间会异常长,代码里必须加超时判断,否则程序会卡死在等待 Echo 下降沿的中断里。

代码里要处理的边界包括:距离小于 2cm 时模块测不准,大于 4m 时回波太弱,都要在采集函数里做有效性校验。否则你会看到屏幕上偶尔蹦出一个 84cm 的假数据,这就是边界没处理好。

3.2 红外对管与光电检测:车位状态判断的另一条路

车位检测不只有超声波一种方案,红外对管在判断车是否进入某个区域时更直接。一对红外对管由发射管和接收管组成,车挡住光路时,接收管电平翻转,单片机只需读一次引脚电平就能判断“有车”。响应速度快、代码简单、成本低,这是它的优点。但它也对安装位置有要求,对阳光和强光敏感,黑色车身对红外吸收强,容易漏判。

我通常的建议是:入口检测用红外对管,车位检测用超声波。入口只要判断车辆经过,红外对管的响应速度优势正好发挥;车位要精确判断“是否有车占用”,超声波的距离数据更可靠。这种交叉选型还有一个隐性好处,答辩时你可以顺理成章地说“我根据场景差异选择了不同的传感方案”,比单纯堆同一种传感器有说服力得多。

接线方面,红外对管模块一般有 VCC、GND、DO 三个引脚,DO 输出数字电平,直接接 GPIO 输入。注意模块标准供电是 3.3V 到 5V,部分模块在 5V 下输出高电平是 5V,同样需要分压或用电平转换芯片,别硬接。

3.3 舵机、继电器与电机驱动:执行机构的共地与反向电压

模拟道闸最常用 SG90 舵机,5V 供电,转动角度由 PWM 脉宽决定。0.5ms 脉宽对应 0 度,1.5ms 对应 90 度,2.5ms 对应 180 度,PWM 周期固定在 20ms,也就是 50Hz。用 STM32 定时器的 PWM 输出通道很容易生成这个波形,但舵机的问题不在信号,而在电源。

舵机启动瞬间电流可能到几百毫安,如果和单片机共用同一个 5V 稳压源,一抬杆单片机就复位。我见过太多学生遇到“舵机一动,系统重启”的情况,原因基本都是供电顶不住。解决方法是舵机电源单独取一路,GND 和单片机共地,PWM 信号线直接连单片机 GPIO。共地是必须的,否则控制信号没有参考电平,舵机根本不会动作。

如果题目要求控制照明灯或风扇这类负载,需要用继电器。继电器线圈在断电瞬间会产生反向电动势,如果不加续流二极管,高压可能打坏 GPIO 或稳压芯片。线圈两端并联一个 1N4148 或 1N4007,方向要和电源相反。这个细节在原理图里很显眼,但自己手焊板子的时候最容易漏。

3.4 电源与接地网络:把“反复重启”掐在源头

整个智能停车系统里,最隐蔽的故障源是供电架构。STM32 正常工作几十毫安,OLED 背光亮起来也吃几十毫安,舵机瞬间几百毫安,蜂鸣器还要再加一笔。所有模块从一个稳压芯片后面取电,满载时输出电压就会被拉低,单片机检测到欠压就开始复位,表现出来就是“刚上电正常,一动作就重启”。

可靠的供电方案是分级。外部 5V 适配器或充电宝作为总电源,舵机和蜂鸣器直接挂 5V;3.3V 用 AMS1117 单独从 5V 转出来,给 MCU 和传感器供电。所有模块的 GND 必须严格连到同一网络,不要靠杜邦线“顺手搭”在邻近 GND 上。地线不稳最直接的后果是 ADC 采样乱跳和超声波测距严重失真。电源指示灯建议加在总电源入口,一眼能看出来当前系统是否在正常工作。

4. 核心代码实现:从 CubeMX 初始化到主状态机到串口调试

硬件板子搭好,接下来是代码。我把代码拆成四段:工程初始化、超声波采集、主状态机、串口显示。每一段都给出关键代码块和参数说明,你拿到资源包后可以直接对照着改。需要注意,不同版本资源包里的函数命名可能不完全一样,但逻辑结构基本是一致的。

4.1 用 CubeMX 配置引脚映射与时钟树

打开 CubeMX,选 STM32F103C8T6,在 Pinout 面板里配置引脚。PA0 设为 GPIO_Output,接超声波 Trig;PA1 设为 TIM2_CH1 输入捕获,接 Echo;PA2 和 PA3 设为 USART2_TX 和 USART2_RX;PB8、PB9 设为 I2C1_SCL 和 I2C1_SDA;PB0 设为 TIM3_CH3 复用推挽输出,接舵机。引脚规划这一步,建议严格按照模块表来,不要想到哪个配哪个,配乱了后面改起来非常痛苦。

时钟树配置,HSE 选择 8MHz 外部晶振,PLL 倍频到 72MHz。这里有个高频踩坑点:TIM3 挂载在 APB1 总线上,APB1 时钟默认 36MHz,如果 APB1 分频系数不是 1,定时器时钟会翻倍变成 72MHz。计算 PWM 频率时必须把这个倍率算进去,不然舵机输出频率不对。

初始化代码生成后,核心 GPIO 配置长这样:

void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; // PA0 Trig GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0; // PB0 舵机 PWM GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); }

这段代码做的事是打开 GPIOA、GPIOB 时钟,然后把引脚配置成需要的模式。Trig 用推挽输出,驱动能力足够;舵机引脚要用复用推挽输出,因为 PWM 信号由定时器硬件驱动,不是 GPIO 翻转。如果这里误配成普通推挽输出,你会看到舵机完全没有信号响应。

4.2 超声波测距代码:定时器输入捕获代替延时阻塞

超声波采集有两种实现方案。一种是在主循环里用 delay 等待 Echo 高电平结束,代码简单,但会阻塞整个程序,而且延时精度取决于主循环调度,很容易到 10cm 左右就开始波动。另一种是让定时器工作在输入捕获模式,记录 Echo 上升沿和下降沿的计数值,差值乘以定时器分辨率就是时间。第二种方案不阻塞主流程,数据稳定,推荐直接用。

volatile uint16_t rising_edge = 0; volatile uint16_t falling_edge = 0; volatile uint8_t capture_index = 0; volatile uint32_t echo_diff = 0; volatile float distance_cm = 0.0f; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { if (capture_index == 0) { rising_edge = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); capture_index = 1; __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); } else { falling_edge = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); capture_index = 0; __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); echo_diff = (falling_edge >= rising_edge) ? (falling_edge - rising_edge) : 0; distance_cm = echo_diff / 58.0f; } } } void HCSR04_Start(void) { HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET); delay_us(10); HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET); }

这段代码的核心逻辑是触发后,在中断回调里切换捕获极性。第一次捕获上升沿,第二次捕获下降沿,两次计数差值就是 Echo 高电平时长。除以 58 是经验公式,因为声速 340m/s 时往返 1cm 约 58us。如果环境温度变化明显,可以把声速换成温度补偿公式。

注意:TIM2 预分频必须设置成 72 分频,让计数频率到 1MHz,这样计数差值的单位才是微妙。预分频错了,后面除 58 得到的距离全是错的,而且错得没有任何规律。

4.3 停车场主逻辑状态机:入场、抬杆、落杆、计数

主循环里如果直接堆 if-else,代码会越写越长,到后来加一个功能就要动十几处地方。停车场这种场景适合用状态机组织,状态跳转清晰,答辩时也容易口头描述流程。状态定义我用枚举实现:

typedef enum { STATE_IDLE = 0, STATE_CAR_DETECTED, STATE_GATE_RAISING, STATE_CAR_ENTERING, STATE_GATE_LOWERING, STATE_PARKING_FULL } ParkingState;

主逻辑状态机如下,每隔几十毫秒调用一次,根据当前状态执行对应动作并切换下一个状态:

void Parking_StateMachine(ParkingState *state) { switch (*state) { case STATE_IDLE: if (HCSR04_GetDistance(ENTRANCE_CH) < 20.0f) { *state = STATE_GATE_RAISING; Servo_SetAngle(90); // 抬杆 } break; case STATE_GATE_RAISING: if (delay_task_is_done(1500)) { *state = STATE_CAR_ENTERING; } break; case STATE_CAR_ENTERING: if (HCSR04_GetDistance(ENTRANCE_CH) > 50.0f) { parking_slots_count--; *state = STATE_GATE_LOWERING; Servo_SetAngle(0); // 落杆 } break; default: *state = STATE_IDLE; break; } }

这段状态机的关键在于,延时不能放在状态内部用阻塞方式等待,否则整个系统在等待期间无法响应按键和串口。资源包里通常会有一个软延时任务模块,用系统节拍判断时间是否到,而不是死等。判定阈值也要注意,进入判定用 20cm,离开判定用 50cm,中间留出缓冲区间,避免车辆停在门口时数据轻微波动导致反复抬落杆。

车位管理逻辑一般放在 App 层独立文件里。每个车位一个变量记录占用状态,车进入后把对应车位置占用,出口检测到车离开后释放。如果题目要做计费,还需要记录入场时间戳,出场时按小时数或停车时长计算费用,显示在 OLED 上,这个业务逻辑建议也做成独立模块。

4.4 串口与 OLED 输出:printf 重定向和可读状态显示

串口打印是这个项目的生命线。数据不对时,第一件事就是看串口日志。要让 printf 从串口输出,必须先重定向 fputc。在 Keil 工程里加上这段:

#include <stdio.h> int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 100); return ch; }

重定向之后,printf 就能直接输出到串口。但这里有个隐蔽的坑:Keil 默认使用标准库的 printf,体积大,有时还会和 HAL 的底层实现冲突。解决方法是到 Options for Target 里勾选 Use MicroLIB,用微库替换标准库,输出立即变正常。这个坑几乎每个用 Keil 和 STM32 的新手都会踩一次,建议从一开始就勾上。

OLED 显示部分,推荐 SSD1306 驱动的 0.96 寸 I2C 屏,I2C 只要两根线,接线简单。初始化调用 OLED_Init,主循环里定期刷新剩余车位和计费信息。刷新频率要控制好,全屏刷新一次大约需要几十毫秒,如果每秒刷 20 次以上,I2C 总线被占满,超声波测距的时序就会受影响,测量数据开始出现毛刺。一般每秒刷 2 到 5 次足够,既能看到状态变化,又不干扰核心逻辑。

5. 避坑排查:停车场项目中最常翻车的 5 个现场

调试阶段才是真正考验人的地方。代码刚烧进去,问题往往不是逻辑错误,而是一些看起来没道理、查起来很耗时的硬件和配置问题。这一章我按“现象 → 原因 → 解决”的格式,把你最可能遇到的五个翻车现场提前排一遍。

5.1 超声波数据乱跳、距离显示明显不对

现象:OLED 或串口输出的距离值不停跳动,车就停在正下方,数据却从 10cm 跳到 4m,或稳定在某个完全不符的值。

原因:最常见的是接线和接地问题,Echo 引脚悬空,感应噪声直接耦合进定时器捕获通道;其次是波动回波,声波打到斜面或边界角产生多次反射,导致捕获到错误的时间戳;还有代码的问题,没有超时判断,Echo 在高电平期间被一次新触发打断,残留计数值被当作有效数据。

解决:先量一下 Echo 引脚空闲电平,正常应该是低电平。然后检查模块 GND 与单片机是否同一网络。代码层,测距函数里加有效范围判断,距离小于 2cm 或大于 400cm 直接丢弃;再做滤波,连续采集 5 次去掉最大值和最小值后求均值,打印出来的数据会稳定很多。超声波模块安装时还要保证探头前没有遮挡物,探头平面朝向车位地面。

5.2 上电即重启、舵机一动就复位

现象:USB 一接上,OLED 刚点亮系统就重启;或者每次抬杆,屏幕闪一下,串口开始打印乱码,紧接着整体软复位。

原因:这是供电问题。舵机或继电器动作瞬间电流峰值很高,把 5V 电源电压瞬间拉低,单片机检测到供电电压异常后触发掉电复位。串口乱码是因为电压跌落期间 UART 电平信号失真,错误数据被当作有效数据接收。

解决:把舵机从系统主电源上摘出去,单独供电,GND 仍然与单片机共地。入口总电源处并联一个 470uF 到 1000uF 的电解电容,用来扛瞬态压降。用万用表测量舵机动作时 5V 网络的最低电压,如果低于 4.5V,说明供电架构必须改。这一条属于物理层问题,调代码永远救不了。

5.3 串口 printf 没有输出或输出乱码

现象:Keil 编译下载后,串口助手界面无任何输出,或者输出的全是乱码。程序看起来在运行,OLED 正常刷新,但收不到日志。

原因:printf 没有重定向到串口,只是空调用;串口参数不匹配,波特率不一致是最常见的;还有引脚复用冲突,USART2 的 TX/RX 被配置成其他功能。有些调试口用的是 SWD,剩余引脚被初始化成了普通 GPIO,也会把 UART 线路占掉。

解决:按 4.4 节加入 fputc 重定向并勾选 MicroLIB,然后确认串口助手参数是 115200、8 位数据、无校验、1 位停止位。用示波器或逻辑分析仪看 TX 引脚是否在空闲状态保持高电平,如果空闲是低电平,说明 GPIO 配置或硬件接线有问题。

5.4 ADC 切换通道后数值错乱

现象:程序里先采集光敏电阻,再切换到电位器通道,切换到新通道后第一次读到的值明显偏低或偏高,过一会儿才恢复正常。

原因:ADC 内部采样保持电容里还残留着上一个通道的电荷。切换通道后如果立即读取,得到的是新旧混合结果,尤其是通道间阻抗差异大时更明显。

解决:切换通道后,先做一次空读或加一个几微秒的启动延时,等待采样电容完成充电,然后连续采样多次,去掉最大值最小值取平均。另一种方案是用 ADC 的扫描模式加 DMA,让硬件自动依次转换多个通道,避免代码手动切换带来时序问题。如果你的代码用的是裸金属循环切换,建议改成 DMA 模式。

5.5 OLED 白屏或只在角落显示字符

现象:OLED 上电后白屏,或者只有屏幕某一小部分显示字符,其他区域全黑或全乱码。

原因:SSD1306 的 I2C 地址不对。不同卖家模块的 I2C 地址可能是 0x3C 或 0x78,而驱动代码里写的是默认值,两者对不上就白屏。另一类原因是复位时序不完整,SSD1306 对复位引脚敏感,如果复位脚悬空,首次初始化可能失败。

解决:先用 I2C 扫描程序打印出实际设备地址,然后修改驱动头文件里的地址宏定义。如果模块有 RST 引脚,把它接到一个 GPIO,初始化前先拉低 10ms 再拉高,确保复位时序完整。刷新逻辑不要放在中断回调里,I2C 传输过程被中断打断会造成数据错位,表现为局部乱码。

6. 进阶调试:让毕设从“能跑”变成“能演示、能答辩”

代码能跑只是第一步,真正拉开差距的是调试规范和演示技巧。这一章给你三个实操习惯和验证方法,都是从做过的项目里沉淀下来的。

6.1 用串口协议打通数据验证

与其用 OLED 实时观察数据,不如把关键状态通过结构化的串口帧打出来。我一般会定义一套简单的文本协议:

printf("ENTRANCE:%d\n", entrance_cm); printf("SPOT_1:%d\n", spot1_status); printf("STATE:%d\n", current_state);

上位机这边用串口助手或 Python 脚本直接读,解析成表格。这样验证“传感器判定是否准确”时,不需要盯着屏幕看,直接把串口日志按时间排序,阈值是否触发一目了然。这份日志还能直接放进论文附录作为实测数据,比截图更有说服力。

6.2 答辩演示的顺序与关键指标

演示顺序不要乱来。我建议先展示 OLED 正常刷新剩余车位,让评委建立系统在稳定运行的第一印象。然后用手或纸板靠近入口超声波,等舵机抬杆,再把障碍物拿走,观察落杆动作和车位计数减少。最后切到串口助手,指着日志解释每个状态切换的触发条件。

被问到关键指标时,记住这几个数字:超声波测距量程 2cm 至 4m,系统判定阈值 20cm 和 50cm,舵机 PWM 频率 50Hz,串口波特率 115200。这些参数能对答如流,比你背十页论文都管用。

6.3 我的三条调试血缘习惯

最后讲三条我自己总结的调试习惯,不是为了教你理论,纯粹是踩坑换来的。第一,改代码前先备份,用 Git 或压缩包都行,改崩了还有后悔药。第二,上电前一定用万用表量电源和地之间是否短路,这个习惯帮我避免了好几次烧传感器。第三,传感器驱动、业务逻辑、调试输出分别放不同文件,每个文件只做一件事,排错时按文件定位,而不是在一个几百行的 main.c 里反复翻。有过一次调了一整晚超声波数据跳变,最后发现只是 Trig 引脚被误配置成了 ADC 模式之后,从那以后我每次新建 STM32 工程都会强制走一遍引脚复用检查清单,确认没有引脚冲突,再开始写业务代码。这三个习惯不一定能让你的毕设拿高分,但一定能让你少熬几个通宵。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表