51单片机公交报站C程序、proteus仿真、报告、仿真演示视频! 支持按键设置上行、下行报站...
先上硬件配置图(Proteus里拖元件就行):单片机接16x2 LCD显示站名和时间,四个独立按键接P2口,P1口挂LED指示运行方向,蜂鸣器接P3.7做提示音。先看核心功能:按键切换上下行、手动报站、时间设置,这些都得靠GPIO口和定时器配合实现。最后在Proteus里跑起来,LED跟着方向变,LCD实时刷新,那效果跟真站牌似的!光标在时分秒之间跳转时,用反转显示实现,LCD_SetCursor
51单片机公交报站C程序、proteus仿真、报告、仿真演示视频! 支持按键设置上行、下行报站,手动播报! 支持按键设置当前时间!
公交报站系统用51单片机玩起来真带劲!今天咱们直接上干货,聊聊怎么用STC89C52实现这个功能。先看核心功能:按键切换上下行、手动报站、时间设置,这些都得靠GPIO口和定时器配合实现。
先上硬件配置图(Proteus里拖元件就行):单片机接16x2 LCD显示站名和时间,四个独立按键接P2口,P1口挂LED指示运行方向,蜂鸣器接P3.7做提示音。仿真时注意给LCD背光供电,不然黑屏给你看!
按键处理得讲究防抖,这里用状态机实现:
uchar key_scan(){
static uchar key_state = 0;
uchar key_press = (P2 & 0x0f);
switch(key_state){
case 0: //初始状态
if(key_press) key_state = 1;
break;
case 1: //消抖确认
if(key_press){
key_state = 2;
return key_press;
}
else key_state = 0;
break;
case 2: //等待释放
if(!key_press) key_state = 0;
break;
}
return 0;
}
这个扫描函数用静态变量保存状态,比delay消抖靠谱多了。按下的键值直接返回,主循环里根据键值切换模式。
51单片机公交报站C程序、proteus仿真、报告、仿真演示视频! 支持按键设置上行、下行报站,手动播报! 支持按键设置当前时间!
方向切换逻辑是关键,来看这个状态切换:
if(key == KEY_UP){
direction = UP;
LCD_ShowString(1,9,"UP ");
LED = 0; //LED亮表示上行
}
else if(key == KEY_DOWN){
direction = DOWN;
LCD_ShowString(1,9,"DOWN");
LED = 1;
}
上下行用不同站序数组存储,比如:
code uchar up_stations[] = {"1.Start 2.Mid 3.End"};
code uchar down_stations[] = {"3.End 2.Mid 1.Start"};
切换方向时直接换指针,报站索引也跟着重置,这样处理最省事。
时间设置有点意思,得进设置模式后调时分秒:
void time_set(){
LCD_Clear();
while(1){
show_time();
key = key_scan();
if(key == KEY_ESC) break;
if(key == KEY_UP) adjust_selected_part(1); //加
if(key == KEY_DOWN) adjust_selected_part(-1); //减
if(key == KEY_ENT) select_next_part(); //切换时分秒
}
}
光标在时分秒之间跳转时,用反转显示实现,LCD_SetCursor后发个0x0d命令让光标闪起来更直观。
报站触发用外部中断实现更稳当,但这里用查询方式也够用:
if(key == KEY_ENT){
play_station(direction, current_station);
current_station = (current_station+1)%TOTAL_STATIONS;
}
蜂鸣器驱动别傻傻的用delay,上PWM调声音:
void beep(uint freq){
uint period = 1000000 / freq; //单位微秒
for(uint i=0; i<200; i++){
BEEP = ~BEEP;
delay_us(period/2);
}
}
配合定时器0做基准时钟,1ms中断里更新站名显示。最后在Proteus里跑起来,LED跟着方向变,LCD实时刷新,那效果跟真站牌似的!

更多推荐



所有评论(0)