【51单片机】【protues仿真】基于51单片机公交报站系统

目录

一、主要功能

二、使用步骤

三、硬件资源

四、软件设计

五、实验现象

一、主要功能

主要功能如下:

1、LCD12864显示时间、日期、公交车车站、温度等

2、按键设置时间,显示公交车信息

3、串口播报相应站点信息

4、按键控制上行、下行、手动播报站

5、LED指示上行、下行信息

二、使用步骤

基于51单片机的公交报站系统,lcd屏幕显示时间,温度,站点信息等等,通过按键来控制对应信息报站。

三、硬件资源

1、51单片机核心模块

2、按键模块

3、温度传感器

4、蜂鸣器模块

5、时钟模块

6、LCD12864显示模块

四、软件设计

#include <reg51.h>

#define uint unsigned int

#define uchar unsigned char

#include "value.h"

#include <UART.h>

sbit x_key=P1^3;

sbit s_key=P1^4;

sbit bz_key=P1^5;

sbit gb_key=P1^6;

sbit x_LED=P2^6;

sbit s_LED=P2^7;

sbit key_zhantai=P3^7;

sbit key_gongjiao=P1^7;

uchar x_mode,s_mode;

uchar x_num,s_num;

bit flag_200ms = 1;

uchar flag_c_en;

bit flag_100ms;

sbit dq=P3^2; //18b20 IO口的定义

uint temperature ; //温度变量

uint flag_zhantai ; //站台显示标志位

uint flag_gongjiao ; //公交显示标志位

/************ 延时函数 *****************/

void delay_uint(uint z)

{

while(z--);

}

/********************************************************************

* 名称 : delay_1ms()

* 功能 : 延时1ms函数

* 输入 : q

* 输出 : 无

***********************************************************************/

void delay_1ms(uint q)

{

uint i,j;

for(i=0;i<q;i++)

for(j=0;j<115;j++);

}

uchar dis_lcd[10];

#include "lcd12864bu.h"

/******************显示时间函数***************************/

void dis_shijian() //显示时间

{

write_shu16(0,0*8,shi,0);

write_shuzi(1,0*2,2*8,fuhao[1],0);

write_shu16(0,3*8,fen,0);

write_shuzi(1,0*2,5*8,fuhao[1],0);

write_shu16(0,6*8,miao,0);

write_yhanzi(2,0,5*16,qita[6]-1); //星期

//write_shu16(0,14*8,week,0);

if(week==0)

{

write_yhanzi(1,0,7*16,xingqi[0]);

}

if(week==1)

{

write_yhanzi(1,0,7*16,xingqi[1]);

}

if(week==2)

{

write_yhanzi(1,0,7*16,xingqi[2]);

}

if(week==3)

{

write_yhanzi(1,0,7*16,xingqi[3]);

}

if(week==4)

{

write_yhanzi(1,0,7*16,xingqi[4]);

}

if(week==5)

{

write_yhanzi(1,0,7*16,xingqi[5]);

}

if(week==6)

{

write_yhanzi(1,0,7*16,xingqi[6]);

}

write_shu16(1*2,0*8,0x20,0);

write_shu16(1*2,2*8,nian,0);

write_shuzi(1,1*2,4*8,fuhao[0],0);

write_shu16(1*2,5*8,yue,0);

write_shuzi(1,1*2,7*8,fuhao[0],0);

write_shu16(1*2,8*8,ri,0);

write_shu18b20(1*2,12*8,temperature,0);

write_shuzi(1,1*2,14*8,dian,0);

}

/************初始化显示*****************/

void init_12864_dis() //初始化显示

{

cs1=1; //左屏开显示

cs2=0;

dis_shijian(); //显示时间

}

/***********************18b20初始化函数*****************************/

void init_18b20()

{

bit q;

dq=1; //把总线拿高

delay_uint(1); //15us

dq=0; //给复位脉冲

delay_uint(80); //750us

dq=1; //把总线拿高 等待

delay_uint(10); //110us

q=dq; //读取18b20初始化信号

delay_uint(20); //200us

dq=1; //把总线拿高 释放总线

}

/*************写18b20内的数据***************/

void write_18b20(uchar dat)

{

uchar i;

for(i=0;i<8;i++)

{ //写数据是低位开始

dq=0; //把总线拿低写时间隙开始

dq=dat&0x01; //向18b20总线写数据了

delay_uint(5); // 60us

dq=1; //释放总线

dat>>=1;

}

}

/*************读取18b20内的数据***************/

uchar read_18b20()

{

uchar i,value;

for(i=0;i<8;i++)

{

dq=0; //把总线拿低读时间隙开始

value>>= 1; //读数据是低位开始

dq=1; //释放总线

if(dq==1) //开始读写数据

value|=0x80;

delay_uint(5); //60us 读一个时间隙最少要保持60us的时间

}

return value; //返回数据

}

/*************读取温度的值 读出来的是小数***************/

uint read_temp()

{

uint value;

uchar low; //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序

init_18b20(); //初始化18b20

write_18b20(0xcc); //跳过64位ROM

write_18b20(0x44); //启动一次温度转换命令

delay_uint(50); //500us

init_18b20(); //初始化18b20

write_18b20(0xcc); //跳过64位ROM

write_18b20(0xbe); //发出读取暂存器命令

EA=0;

low=read_18b20(); //读温度低字节

value=read_18b20(); //读温度高字节

EA =1;

value<<=8; //把温度的高位左移8位

value|=low; //把读出的温度低位放到value的低八位中

value*=0.625; //转换到温度值 小数

return value; //返回读出的温度 带小数

}

/******************显示时间函数***************************/

void dis_shijian_set() //显示时间

{

write_shu16(0*2,0*8,0x20,0);

write_shu16(1*2,2*8,shi,0);

write_shu16(1*2,6*8,fen,0);

write_shu16(1*2,10*8,miao,0);

write_shu16(0*2,2*8,nian,0);

write_shu16(0*2,6*8,yue,0);

write_shu16(0*2,10*8,ri,0);

write_yhanzi(1,4,5*16,xingqi[week]);

}

/******************时间芯片显示函数**********************/

void ds1302_dis()

{

uchar miao_1;

if(menu_1 == 0)

{

read_time();

if(miao_1 != miao)

{

miao_1 = miao;

dis_shijian(); //显示时间

}

}

}

/********************独立按键程序*****************/

uchar key_can; //按键值

void key() //独立按键程序

{

static uchar key_new;

key_can=20; //按键值还原

P3|=0x78; //对应的按键IO口输出为1

if((P3&0x78)!=0x78) //按键按下

{

delay_1ms(1); //按键消抖动

if(((P3&0x78)!=0x78)&&(key_new==1))

{ //确认是按键按下

key_new=0;

switch(P3&0x78)

{

case 0x70:key_can=1;break; //得到按键值

case 0x68:key_can=2;break; //得到按键值

case 0x58:key_can=3;break; //得到按键值

case 0x38:key_can=4;break; //得到按键值

}

}

}

else

key_new=1;

}

/**********************设置函数************************/

void key_with()

{

if(key_can==4) //退出键

{

qingling();

init_12864_dis(); //初始化显示

flag_200ms=1;

menu_1=0;

}

if(key_can==1) //设置键

{

menu_1 ++;

flag_200ms=1;

if(menu_1==1)

{

x_num=0;

s_num=0;

x_mode=0;

s_mode=0;

qingling();

init_12864_set1();

}

if(menu_1>7)

menu_1 = 1;

}

if(menu_1!=0)

{

if(menu_1==1) //设置年

{

if(key_can==2) //加

set_ds1302time(1,&nian,0x99);

if(key_can==3) //减

set_ds1302time(0,&nian,0x99);

}

if(menu_1==2) //设置月

{

if(key_can==2) //加

set_ds1302time(1,&yue,0x13);

if(key_can==3) //减

set_ds1302time(0,&yue,0x13);

}

if(menu_1==3) //设置日

{

if(key_can==2) //加

set_ds1302time(1,&ri,0x32);

if(key_can==3) //减

set_ds1302time(0,&ri,0x32);

}

if(menu_1==4) //设置时

{

if(key_can==4) //加

set_ds1302time(1,&shi,0x24);

if(key_can==3) //减

set_ds1302time(0,&shi,0x24);

}

if(menu_1==5) //设置分

{

if(key_can==2) //加

set_ds1302time(1,&fen,0x60);

if(key_can==3) //减

set_ds1302time(0,&fen,0x60);

}

if(menu_1==6) //设置秒

{

if(key_can==2) //加

set_ds1302time(1,&miao,0x60);

if(key_can==3) //减

set_ds1302time(0,&miao,0x60);

}

if(menu_1==7) //设置星期

{

if(key_can==2) //加

set_ds1302time(1,&week,0x8);

if(key_can==3) //减

set_ds1302time(0,&week,0x8);

}

dis_shijian_set(); //显示时间

switch(menu_1) // 光标显示

{

case 1:write_shu16(0*2,2*8,nian,1);break;

case 2:write_shu16(0*2,6*8,yue,1);break;

case 3:write_shu16(0*2,10*8,ri,1);break;

case 4:write_shu16(1*2,2*8,shi,1);break;

case 5:write_shu16(1*2,6*8,fen,1);break;

case 6:write_shu16(1*2,10*8,miao,1);break;

case 7:write_yhanzi(1,4,5*16,xingqi[week]);break;

}

write_time(); //把时间写进去

}

}

/*********************定时器0、定时器1初始化******************/

void time0_init()

{

EA=1; //开总中断

TMOD=0X11; //定时器0、定时器1工作方式1

ET0=1; //开定时器0中断

TR0=1; //允许定时器0定时

}

void baozhan()

{

if(key_zhantai==0)

{

delay_1ms(20);

if(key_zhantai==0)

{

qingling();

x_mode=1;

s_mode=0;

x_num=0;

s_num=0;

x_LED=0;

s_LED=0;

write_yhanzi(1,4,0*16,yihaozhan[0]); //一

write_yhanzi(1,4,1*16,yihaozhan[1]); //号

write_yhanzi(1,4,2*16,yihaozhan[2]); //站

write_yhanzi(1,4,4*16,erhaozhan[0]); //二

write_yhanzi(1,4,5*16,erhaozhan[1]); //号

write_yhanzi(1,4,6*16,erhaozhan[2]); //站

write_yhanzi(1,6,0*16,sanhaozhan[0]); //三

write_yhanzi(1,6,1*16,sanhaozhan[1]); //号

write_yhanzi(1,6,2*16,sanhaozhan[2]); //站

write_yhanzi(1,6,4*16,sinhaozhan[0]); //四

write_yhanzi(1,6,5*16,sinhaozhan[1]); //号

write_yhanzi(1,6,6*16,sinhaozhan[2]); //站

}

while(!key_zhantai);

}

if(x_key==0 || key_gongjiao==0)

{

delay_1ms(20);

if(x_key==0 || key_gongjiao==0)

{

qingling();

x_mode=1;

s_mode=0;

x_num=0;

s_num=0;

x_LED=0;

s_LED=1;

write_yhanzi(1,4,0*16,daoda[0]); //到

write_yhanzi(1,4,1*16,daoda[1]); //达

write_shuzi(1,2*2,4*8,fuhao[1],0);//:

write_yhanzi(1,6,0*16,xiayizhan[0]); //下

write_yhanzi(1,6,1*16,xiayizhan[1]); //站

write_shuzi(1,3*2,4*8,fuhao[1],0); //:

}

while((!x_key) || (!key_gongjiao));

}

if(s_key==0 || key_gongjiao==0)

{

delay_1ms(20);

if(s_key==0 || key_gongjiao==0)

{

qingling();

x_mode=0;

s_mode=1;

x_num=0;

s_num=0;

x_LED=1;

s_LED=0;

write_yhanzi(1,4,0*16,daoda[0]); //到

write_yhanzi(1,4,1*16,daoda[1]); //达

write_shuzi(1,2*2,4*8,fuhao[1],0);//:

write_yhanzi(1,6,0*16,xiayizhan[0]); //下

write_yhanzi(1,6,1*16,xiayizhan[1]); //站

write_shuzi(1,3*2,4*8,fuhao[1],0); //:

}

while((!s_key) || (!key_gongjiao));

}

if((bz_key==0)&&(x_mode==1))

{

delay(20);

if((bz_key==0)&&(x_mode==1))

{

x_num++;

x_num%=6;

}

while(!bz_key);

}

if((bz_key==0)&&(s_mode==1))

{

delay(20);

if((bz_key==0)&&(s_mode==1))

{

s_num++;

s_num%=6;

}

while(!bz_key);

}

if(gb_key==0)

{

delay_1ms(20);

if(gb_key==0)

{

x_mode=0;

s_mode=0;

x_num=0;

s_num=0;

x_LED=1;

s_LED=1;

qingling();

}

}

}

void yuyin()

{

/******************************下行报站显示***********/

if(x_num==1)

{

write_yhanzi(1,4,3*16,yihaozhan[0]); //一

write_yhanzi(1,4,4*16,yihaozhan[1]); //号

write_yhanzi(1,4,5*16,yihaozhan[2]); //站

write_yhanzi(1,6,3*16,erhaozhan[0]); //二

write_yhanzi(1,6,4*16,erhaozhan[1]); //号

write_yhanzi(1,6,5*16,erhaozhan[2]); //站

delay(500);

}

if(x_num==2)

{

write_yhanzi(1,4,3*16,erhaozhan[0]); //二

write_yhanzi(1,4,4*16,erhaozhan[1]); //号

write_yhanzi(1,4,5*16,erhaozhan[2]); //站

write_yhanzi(1,6,3*16,sanhaozhan[0]); //三

write_yhanzi(1,6,4*16,sanhaozhan[1]); //号

write_yhanzi(1,6,5*16,sanhaozhan[2]); //站

}

if(x_num==3)

{

write_yhanzi(1,4,3*16,sanhaozhan[0]); //三

write_yhanzi(1,4,4*16,sanhaozhan[1]); //号

write_yhanzi(1,4,5*16,sanhaozhan[2]); //站

write_yhanzi(1,6,3*16,sinhaozhan[0]); //四

write_yhanzi(1,6,4*16,sinhaozhan[1]); //号

write_yhanzi(1,6,5*16,sinhaozhan[2]); //站

}

if(x_num==4)

{

write_yhanzi(1,4,3*16,sinhaozhan[0]); //四

write_yhanzi(1,4,4*16,sinhaozhan[1]); //号

write_yhanzi(1,4,5*16,sinhaozhan[2]); //站

write_yhanzi(1,6,3*16,zhongdianzhan[0]); //终

write_yhanzi(1,6,4*16,zhongdianzhan[1]); //点

write_yhanzi(1,6,5*16,zhongdianzhan[2]); //站

}

if(x_num==5)

{

write_yhanzi(1,4,3*16,zhongdianzhan[0]); //终

write_yhanzi(1,4,4*16,zhongdianzhan[1]); //点

write_yhanzi(1,4,5*16,zhongdianzhan[2]); //站

write_yhanzi(1,6,0*16,ganxiechengzuo[0]); //感

write_yhanzi(1,6,1*16,ganxiechengzuo[1]); //谢

write_yhanzi(1,6,2*16,ganxiechengzuo[2]); //乘

write_yhanzi(1,6,3*16,ganxiechengzuo[3]); //坐

write_yhanzi(1,6,4*16,ganxiechengzuo[4]); //本

write_yhanzi(1,6,5*16,ganxiechengzuo[5]); //公

write_yhanzi(1,6,6*16,ganxiechengzuo[6]); //车

}

/******************************上行报站显示***********/

if(s_num==1)

{

write_yhanzi(1,6,0*16,xiayizhan[0]); //下

write_yhanzi(1,6,1*16,xiayizhan[1]); //站

write_shuzi(1,3*2,4*8,fuhao[1],0); //:

write_yhanzi(1,4,3*16,sinhaozhan[0]); //四

write_yhanzi(1,4,4*16,sinhaozhan[1]); //号

write_yhanzi(1,4,5*16,sinhaozhan[2]); //站

write_yhanzi(1,6,3*16,sanhaozhan[0]); //三

write_yhanzi(1,6,4*16,sanhaozhan[1]); //号

write_yhanzi(1,6,5*16,sanhaozhan[2]); //站

}

if(s_num==2)

{

write_yhanzi(1,4,3*16,sanhaozhan[0]); //三

write_yhanzi(1,4,4*16,sanhaozhan[1]); //号

write_yhanzi(1,4,5*16,sanhaozhan[2]); //站

write_yhanzi(1,6,3*16,erhaozhan[0]); //二

write_yhanzi(1,6,4*16,erhaozhan[1]); //号

write_yhanzi(1,6,5*16,erhaozhan[2]); //站

}

if(s_num==3)

{

write_yhanzi(1,4,3*16,erhaozhan[0]); //二

write_yhanzi(1,4,4*16,erhaozhan[1]); //号

write_yhanzi(1,4,5*16,erhaozhan[2]); //站

write_yhanzi(1,6,3*16,yihaozhan[0]); //一

write_yhanzi(1,6,4*16,yihaozhan[1]); //号

write_yhanzi(1,6,5*16,yihaozhan[2]); //站

}

if(s_num==4)

{

write_yhanzi(1,4,3*16,yihaozhan[0]); //一

write_yhanzi(1,4,4*16,yihaozhan[1]); //号

write_yhanzi(1,4,5*16,yihaozhan[2]); //站

write_yhanzi(1,6,3*16,zhongdianzhan[0]); //终

write_yhanzi(1,6,4*16,zhongdianzhan[1]); //点

write_yhanzi(1,6,5*16,zhongdianzhan[2]); //站

}

if(s_num==5)

{

write_yhanzi(1,4,3*16,zhongdianzhan[0]); //终

write_yhanzi(1,4,4*16,zhongdianzhan[1]); //点

write_yhanzi(1,4,5*16,zhongdianzhan[2]); //站

write_yhanzi(1,6,0*16,ganxiechengzuo[0]); //感

write_yhanzi(1,6,1*16,ganxiechengzuo[1]); //谢

write_yhanzi(1,6,2*16,ganxiechengzuo[2]); //乘

write_yhanzi(1,6,3*16,ganxiechengzuo[3]); //坐

write_yhanzi(1,6,4*16,ganxiechengzuo[4]); //本

write_yhanzi(1,6,5*16,ganxiechengzuo[5]); //公

write_yhanzi(1,6,6*16,ganxiechengzuo[6]); //车

}

}

void main()

{

x_key=1;

s_key=1;

bz_key=1;

gb_key=1;

x_LED=1;

s_LED=1;

P0=P1=P2=P3=0xff; //单片机IO口初始化为1

init_ds1302();

delay_1ms(5);

init_lcd();

delay_1ms(5);

Clr_Scr();

time0_init();

delay_1ms(5);

init_12864_dis(); //初始化显示

delay_1ms(5);

uart_cfg();

while(1)

{

baozhan(); //显示上站和下站字头

yuyin(); //显示上站和下站是哪一站

key(); //改变key_san的值,判断K1-K4哪个键按下即设置时间的4个键哪个被按下

if(key_can<10)

{

key_with(); //根据key_san的值执行相应程序

}

if(flag_100ms==1)

{

flag_100ms=0;

}

if(flag_200ms==1) //200ms

{

flag_200ms=0;

temperature=read_temp(); //先读出温度的值

ds1302_dis(); //时钟显示函数,同时显示温度函数也在里面

}

}

}

五、实验现象

演示视频:

相关推荐
写点什么呢3 小时前
Cubemx+Fatfs(解决挂载Fatfs失败的问题)
单片机·嵌入式硬件
物随心转3 小时前
ARM的big.LITTLE架构
嵌入式硬件
月阳羊4 小时前
【硬件-笔试面试题-81】硬件/电子工程师,笔试面试题(知识点:详细讲讲同步时钟与异步时钟通信)
java·经验分享·单片机·嵌入式硬件·面试
猪八戒1.04 小时前
4.2 I2C通信协议
stm32·单片机·嵌入式硬件
然后,是第八天4 小时前
[模块教学]VK16K33_8×16LED矩阵屏的驱动以及技术文档,矩阵屏, 详细配置说明
stm32·单片机·iic·8×16点阵屏
指针刺客4 小时前
串口数据收发的设计
单片机·嵌入式硬件
文火冰糖的硅基工坊6 小时前
[硬件电路-170]:50Hz工频干扰:本质、产生机制与影响
嵌入式硬件·系统架构·电路·跨学科融合
longxiangam8 小时前
墨水屏程序
单片机·嵌入式硬件·rust·risc-v
兆龙电子单片机设计12 小时前
【STM32项目开源】STM32单片机智能恒温箱控制系统
stm32·单片机·物联网·开源·毕业设计