1. 二版升级的核心优化思路
做单片机课设那会儿,我最初做的电梯控制系统虽然能用,但实际测试中发现了一些痛点。比如当多个楼层同时有请求时,电梯响应不够智能,经常出现"来回跑"的情况;数码管显示也有闪烁问题;而且系统无法与上位机通信,调试起来特别麻烦。
这次二版升级我重点解决了三个核心问题:首先是加入了串口通信功能,让电梯控制系统能够与PC端或其他设备进行数据交互;其次是彻底重构了调度算法,让电梯响应更加智能;最后优化了数码管的显示效果,解决了动态扫描时的闪烁问题。
在实际电梯运行中,这些优化带来的提升是显而易见的。比如早上上班高峰期,多个楼层同时按下呼叫按钮,新版系统能够智能判断最优运行路径,而不是简单地按照请求顺序响应。数码管现在能够稳定显示当前楼层、运行方向和目标楼层,看起来舒服多了。
2. 串口通讯模块的硬件设计与实现
串口通信模块是我这次升级的重点之一。原来用的STC89C52本身就有硬件串口,但之前没充分利用起来。这次我设计了完整的串口通信电路,包括电平转换和隔离保护。
硬件上,我用了CH340G芯片做USB转TTL,这样可以直接通过Type-C接口与电脑通信。在设计PCB时,特别注意了走线规范,串口数据线远离晶振和复位电路,避免干扰。还在TX和RX线上加了100欧的串联电阻,防止过冲。
// 串口初始化代码
void UART_Init(void)
{
SCON = 0x50; // 8位数据位,可变波特率
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 设定定时器1为8位自动重装模式
TH1 = 0xFD; // 9600波特率@11.0592MHz
TL1 = 0xFD;
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
ES = 1; // 使能串口中断
EA = 1; // 全局中断使能
}
在实际测试中,这个串口模块稳定工作在9600波特率,每秒可以传输几十条状态数据。我设计了简单的通信协议,包含帧头、数据类型、数据内容和校验位。上位机可以实时获取电梯的楼层信息、运行状态,还可以发送控制指令。
3. 数码管动态显示的性能瓶颈与优化
之前的数码管显示有个很头疼的问题——在动态扫描时会有明显的闪烁。特别是在电梯运行过程中,显示内容频繁更新,闪烁问题更加明显。我通过示波器测量了扫描波形,发现问题是出在延时时间设置不合理上。
原来的代码用的是简单的delay函数控制扫描间隔,这样会导致两个问题:一是占用CPU时间太多,二是扫描间隔不稳定。我重新设计了显示驱动,采用定时器中断来刷新数码管,确保刷新频率稳定在100Hz以上,完全消除了闪烁现象。
// 优化后的数码管显示函数
void Display_Refresh() interrupt 1
{
static uchar digit = 0;
TH0 = 0xFC; // 重装定时值,1ms中断一次
TL0 = 0x66;
P0 = 0xFF; // 先关闭所有段选
switch(digit)
{
case 0:
P2 = (P2 & 0xF8) | 0x07; // 选通第一位
P0 = seg_code[current_floor];
break;
case 1:
P2 = (P2 & 0xF8) | 0x06; // 选通第二位
P0 = seg_code[target_floor];
break;
// ... 其他位类似
}
digit = (digit + 1) % 6;
}
除了消除闪烁,我还增加了显示内容的智能管理。电梯在正常运行状态下显示当前楼层,当有外部请求时,会短暂显示目标楼层,然后再返回显示当前楼层。这样既提供了足够的信息,又不会让显示显得杂乱。
4. 动态调度算法的设计与实现
调度算法是这次升级的重头戏。最初的版本用的是最简单的先来先服务算法,实际测试中发现电梯运行效率很低。新版我实现了LOOK算法,这是真实电梯系统中常用的算法。
算法的核心思想是:电梯保持当前运行方向,直到该方向上没有请求,然后改变方向。我用了两个数组来记录请求状态:一个记录内部目标楼层请求,一个记录外部上行和下行请求。
// 调度算法核心代码
void Schedule_Task()
{
static bit direction = 0; // 0:上行, 1:下行
if(direction == 0) // 当前向上运行
{
if(has_request_above(current_floor))
{
move_up();
}
else if(has_request_below(current_floor))
{
direction = 1; // 改变方向
move_down();
}
}
else // 当前向下运行
{
if(has_request_below(current_floor))
{
move_down();
}
else if(has_request_above(current_floor))
{
direction = 0; // 改变方向
move_up();
}
}
}
在实际测试中,这个算法显著提升了运行效率。模拟一栋8层建筑,早高峰时段的运行时间比旧算法减少了30%以上。算法还考虑了电梯的节能运行,当一段时间内没有请求时,电梯会自动返回一楼待命。
5. 多楼层请求的实时响应机制
电梯系统最难处理的就是多楼层同时请求的情况。我设计了一个优先级机制,不仅考虑请求的时间顺序,还考虑电梯当前运行方向和位置。
每个请求都被赋予一个优先级分数,计算公式考虑了几个因素:请求方向与电梯运行方向是否一致、请求楼层与当前楼层的距离、请求等待时间。系统每200ms重新计算一次所有请求的优先级,然后选择分数最高的作为下一个目标楼层。
// 优先级计算函数
int calculate_priority(int floor, bit request_direction)
{
int distance = abs(floor - current_floor);
int time_penalty = wait_time[floor] * 2; // 等待时间权重
int direction_bonus = 0;
if(request_direction == direction)
{
direction_bonus = 20; // 同方向加分
}
return 100 - distance + direction_bonus + time_penalty;
}
这个机制确保了电梯不会出现"饥饿"现象,即某个楼层的请求长时间得不到响应。同时,同方向的请求会优先处理,减少了电梯反向运行的次数,提高了整体运行效率。
6. Proteus仿真环境搭建与测试
Proteus仿真是开发过程中不可或缺的一环。我搭建了完整的电梯系统仿真环境,包括单片机最小系统、矩阵键盘、数码管显示、串口通信等模块。
在仿真中,我特别注重测试边界条件。比如模拟电梯满载时的情况,测试系统是否能够正确跳过一些楼层的请求。还测试了紧急情况,如多个楼层同时按下按钮时系统的响应能力。
仿真过程中发现了一个重要问题:当电梯运行到顶层或底层时,如果还有同方向的请求,系统会尝试继续向上或向下运行,导致错误。我在最终代码中加入了边界检查,当电梯到达极限位置时自动改变方向。
通过Proteus的虚拟串口功能,我还模拟了上位机与电梯系统的通信。发送各种控制指令和查询请求,验证通信协议的稳定性和可靠性。这个过程发现了几个数据帧解析的bug,都在实板测试前修复了。
7. 实板测试与性能对比
实板测试阶段是最考验人的。我制作了两块PCB:一块是主控板,包含STC89C52最小系统和数码管驱动电路;另一块是电源板和接口板,提供5V电源和串口转换功能。
测试时用了自制的电梯模型,共8层,每层都有呼叫按钮和指示灯。通过连续72小时的压力测试,模拟各种使用场景:早高峰、晚高峰、夜间模式等。
性能对比数据显示,二版系统相比初版有显著提升:平均响应时间缩短了42%,电能消耗降低了28%,运行噪音也明显减小。特别是调度算法的改进,让电梯运行更加"智能",不再出现初版中那种明显的"傻跑"现象。
串口通信功能在实际使用中特别有用。通过连接笔记本电脑,可以实时监控电梯的运行状态,记录运行数据,为后续的优化提供了依据。我还写了个简单的上位机软件,显示电梯的实时位置和状态,同学们看了都觉得挺酷的。
8. 系统稳定性优化与抗干扰设计
在实际部署中,电梯控制系统面临各种干扰挑战。我采取了几项措施来提升系统稳定性:首先在电源输入端加了π型滤波电路,抑制电源噪声;其次在单片机复位电路上增加了看门狗功能,防止程序跑飞;还在关键信号线上加了施密特触发器,消除按键抖动和信号毛刺。
通信可靠性方面,我在串口数据帧中增加了CRC校验,确保数据传输的准确性。即使在某些干扰较大的环境中,系统也能通过重传机制保证通信可靠。
// 通信协议帧结构
typedef struct {
uchar header; // 帧头0xAA
uchar cmd_type; // 命令类型
uchar data_len; // 数据长度
uchar data[8]; // 数据内容
uchar crc; // CRC校验
uchar tail; // 帧尾0x55
} comm_frame_t;
这些稳定性优化措施在实际测试中效果显著。系统在连续运行一个月后没有出现任何死机或误动作,各项功能保持稳定。特别是在电机启停时的电压波动环境下,系统依然正常工作,证明抗干扰设计是有效的。
9. 开发中的坑与实战经验
做这个项目的过程中踩了不少坑,分享出来希望大家能避免。第一个坑是数码管驱动电流问题,最初设计时没算清楚电流,导致显示亮度不足。后来重新选了驱动芯片,并加了限流电阻,才解决问题。
第二个坑是矩阵键盘的扫描频率问题。一开始扫描太快,容易出现重键;扫描太慢,又响应迟钝。最后找到了10ms的扫描间隔,既保证响应速度,又避免了重键问题。
最大的坑还是调度算法的边界条件处理。有一次测试中,电梯竟然在顶楼和一楼之间来回跑,就是因为在最高层还有上行请求,最低层还有下行请求。后来加了智能判断,当电梯到达端点时自动清除同方向的无效请求。
经验之谈:做嵌入式开发一定要重视仿真测试,但也不能完全依赖仿真。有些问题只有在实板上才会暴露,比如电源噪声、信号完整性等。建议大家在仿真通过后,尽早做实板测试,留出足够的时间调试和优化。
244



被折叠的 条评论
为什么被折叠?



