生产实习-电梯演示系统设计

电梯演示系统设计

背景

本次设计采用 Ubuntu18.04.4-x64 +GEC6818开发板设计开发

学习步骤如下:

所需的linux的基本知识:

命令:https://blog.youkuaiyun.com/weixin_51165960/article/details/126781536

函数:https://blog.youkuaiyun.com/weixin_51165960/article/details/126916855

bmp文件和开发板上显示图片的学习:

https://blog.youkuaiyun.com/weixin_51165960/article/details/126917209

电梯界面设计和触摸屏的学习:

https://blog.youkuaiyun.com/weixin_51165960/article/details/126917828

创建广告循环播放线程的学习:

https://blog.youkuaiyun.com/weixin_51165960/article/details/126918074

总体设计

1.设备初始化

2.显示初始化界面

3.创建一个线程循环播放广告

4.创建一个线程获取按下的楼层

5.分析按下某一楼层后,当前所在楼层上下合剩下多少楼层需要到达

6.电梯运行,显示当前到达的楼层和向上向下运行箭头

7.每到达一层楼,暂停一秒,表示乘客进出电梯

8.分析到达后,当前所在楼层上下合剩下多少楼层需要到达,若没有需要到达的楼层,则运行箭头小时,电梯运行停止。

9.设备解除初始化

详细设计:

0.设计中所用的bmp.h bmp.c touch.h touch.c main.c介绍

bmp.h:定义一个bmp图片信息相关的结构体类型和所需有关屏幕初始化和其他有关图片显示的函数。

//定义一个bmp图片信息相关的结构体类型
typedef struct BMP
{
    char* bmpname;          //保存bmp图片的名称
    int size;               //文件的总大小
    int width;              //文件的宽
    int height;             //文件的高
    short bpp;              //色深
    char* data;             //像素数组的首地址
}BMP;

//屏幕初始化
void lcd_init();
//解除屏幕初始化
void lcd_uninit();
//画点
void lcd_point(int x,int y,int color);
//获取bmp图片信息
BMP get_bmp_info(char* bmpname);
//画一张bmp图片
void lcd_draw_bmp(char* bmpname, int x, int y);

bmp.c:对bmp.h各个方法的具体实现。

touch.h:定义有关触摸屏的初始化及其他方法所需的函数。

//初始化触摸屏
void touch_init();
//解除触摸屏初始化
void touch_uninit();
//获取触摸点坐标 x表示触摸点的横坐标 y表示触摸点的纵坐标
void get_xy(int* x, int* y);
//获取手指离开开发板时的坐标
void get_xy1(int* x, int* y);

touch.c:对touch.c中各个方法的具体实现。

mian.c:

定义几个全局变量和数组

int j[10]={0};//用来标识楼层是否被按下
int nowf= 1; //当前楼层
int h_num = 0; //当前楼层上面有几个楼层被按下
int l_num = 0; //当前楼层下面有几个楼层被按下
char *onbmp[10]={"001.bmp","002.bmp","003.bmp","004.bmp","005.bmp","006.bmp","007.bmp","008.bmp","009.bmp","010.bmp",};//灭
char *keybmp[10]={"01.bmp","02.bmp","03.bmp","04.bmp","05.bmp","06.bmp","07.bmp","08.bmp","09.bmp","10.bmp",};//灭
char *numbmp[10]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp","6.bmp","7.bmp","8.bmp","9.bmp","0010.bmp",};//数字
int x7,y7;//x7用于保存对应楼层计算后的对应结果(非坐标);y7用于保存对应楼层计算后的对应结果(坐标)//y0是个内建函数
int x;//触摸的点x坐标
int y;//触摸的点y坐标

调用bmp.c和touch.c中的方法和其他设计实现电梯运行系统演示。

1.设备初始化

初始化设备:

//初始化显示屏
lcd_init();
//初始化触摸屏
touch_init();

2.显示初始化界面

定义一个showbmp()用于显示初始化界面:

//启动进入界面
showbmp();

void showbmp()
{
	//在屏幕上显示一张图片
	lcd_draw_bmp("./main.bmp",0,0);
	sleep(5);
	lcd_draw_bmp("./bg3.bmp",0,0);
	lcd_draw_bmp("./01.bmp",600,0);
	lcd_draw_bmp("./02.bmp",700,0);
	lcd_draw_bmp("./03.bmp",600,96);
	lcd_draw_bmp("./04.bmp",700,96);
	lcd_draw_bmp("./05.bmp",600,192);
	lcd_draw_bmp("./06.bmp",700,192);
	lcd_draw_bmp("./07.bmp",600,288);
	lcd_draw_bmp("./08.bmp",700,288);
	lcd_draw_bmp("./09.bmp",600,384);
	lcd_draw_bmp("./10.bmp",700,384);
	lcd_draw_bmp(numbmp[nowf-1],200,120);//显示初次所在楼层,因nowf初始为1,故初次显示在一楼
}
	

3.创建一个线程循环播放广告

定义一个广告循环线程:

void* ad(void* arg)//广告循环
{
	
char *adbmp[2]={"ad1.bmp","ad2.bmp"};
	int i=0;
	while(1)
	{
		lcd_draw_bmp(adbmp[i++], 0,0);
		sleep(3);
		if(i==2)
			i=0;
	}
}

4.创建一个线程获取按下的楼层

(1)

获取按下的位置X,Y并转化为对应楼层的数值n

通过analyz()解析出n楼层对应位置的图片的写入点X7,Y7,以便修改按键的显示状态

(2)

通过修改数组j中的值的0、1状态(标志位)来表示对应按键是否被按下。0表示未被按下,1表示被按下。

(3)

当按下的楼层为当前楼层时,楼层按键显示先亮后灭,不修改对应j数组中的标志。电梯不运行。

(4)

当按下的楼层不为当前楼层时,修改对应j数组中的标志,调用fenxi()分析上下有多少楼层需要到达,同时所按楼层按键变亮。

(5)

当按下的楼层标志位已经是1时(即已经被按下,需要到达),再次按下修改标志位为0(表示不再需要去到达)同时依然调用fenxi()分析。

void* run(void* arg)
{
	int x1;//用于计算按下的楼层位置(非坐标)
	int y1;//用于计算按下的楼层位置(坐标)
	int n;
	printf("进入按键判断\n");
	while(1)
	{	
		get_xy1(&x,&y);
		printf("获取坐标值了\n");
		x=(x*800)/1024;
		y=(y*480)/600;
		printf("x=%d y=%d\n",x,y);
		if(x>=600&&x<700&&y>=0&&y<96)
			n=1;
		if(x>=700&&x<800&&y>=0&&y<96)
			n=2;
		if(x>=600&&x<700&&y>=96&&y<192)
			n=3;
		if(x>=700&&x<800&&y>=96&&y<192)
			n=4;
		if(x>=600&&x<700&&y>=192&&y<288)
			n=5;
		if(x>=700&&x<800&&y>=192&&y<288)
			n=6;
		if(x>=600&&x<700&&y>=288&&y<384)
			n=7;
		if(x>=700&&x<800&&y>=288&&y<384)
			n=8;
		if(x>=600&&x<700&&y>=384&&y<480)
			n=9;
		if(x>=700&&x<800&&y>=384&&y<480)
			n=10;
		printf("当前按下的是%d\n",n);
		analyz(n);
	if(j[n-1]==0)
	{
		if(nowf==n)
		{
			if(x7==1)
			{
			lcd_draw_bmp(onbmp[n-1], 600,y7);//对应楼层亮
			sleep(1);
			lcd_draw_bmp(keybmp[n-1], 600,y7);//对应楼层灭
			}
			if(x7==0)
			{
			lcd_draw_bmp(onbmp[n-1], 700,y7);//对应楼层亮
			sleep(1);
			lcd_draw_bmp(keybmp[n-1], 700,y7);//对应楼层灭
			}
		}
		if(nowf!=n)
		{
			j[n-1]=1;
			fenxi();
			if(x7==1)
			{
			lcd_draw_bmp(onbmp[n-1], 600,y7);//对应楼层亮
			}
			if(x7==0)
			{
			lcd_draw_bmp(onbmp[n-1], 700,y7);//对应楼层亮
			}
		}
	}
	else
	{
		//取消楼层
			j[n-1]=0;
			if(x7==1)
			{
			lcd_draw_bmp(keybmp[n-1], 600,y7);//对应楼层灭
			}
			if(x7==0)
			{
			lcd_draw_bmp(keybmp[n-1], 700,y7);//对应楼层灭
			}
			fenxi();
			
	}
	
	n=0;	
}
}

5.分析按下某一楼层后,当前所在楼层上下合剩下多少楼层需要到达

通过循环遍历数组从当前位置到最高和最低之间有多少个1(即有多少楼层按键被按下)。用h_num表示上面还有少楼层要达到,用l_num表示下面还有少楼层要达到。

void fenxi()//上下还有多少楼层分析函数
{
			int nowftemp;
			nowftemp=nowf;
			int *p=j;
			int h_n = 0, l_n = 0;
			for (int i = nowftemp; i < 11; i++)//当前楼层上面有几个楼层被按下
				{
					if (p[i-1] == 1)
					{
						h_n++;
					}
				}
			for (int i = nowftemp; i > 0; i--)//当前楼层下面有几个楼层被按下
				{
					if (p[i-1] == 1)
					{
						l_n++;
					}
				}
				h_num = h_n;
				l_num = l_n;
				printf("分析:现在在:%d\n",nowf);
				printf("分析:上面有:%d 下面有%d\n",h_num,l_num);
				
}

6.电梯运行,显示当前到达的楼层和向上向下运行箭头

电梯向上运行:

(1)

通过判断h_num值是非为零判断电梯是非需要运行,若需要则nowf++,表示电梯在往上运行。同时显示向上运行图标和当前楼层

(2)

当到达需到达的楼层时,延时一秒表示开门,更新j数组的值,通过analyz()解析出当前楼层对应位置的图片的写入点X7,Y7,更新当前按键的状态。

(3)

到达一层后h_num的值减一,并调用fenxi()分析。

(4)

延时一秒表示电梯往上运行

(5)

当到达最高需到达的楼层时,刷新中间的显示屏幕以便去掉屏幕的向上箭头,并显示当前的楼层。

while(1)
	{
	//电梯向上运行
			for (; h_num != 0; nowf++)
			{
				printf("电梯运行中现在是在:%d层\n",nowf);
				printf("电梯运行中上面还有 %d层\n",h_num);
				//在屏幕中间显示向上的箭头和当前楼层
				lcd_draw_bmp("up.bmp",200,0);
				lcd_draw_bmp(numbmp[nowf-1],200,120);			
			if (j[nowf-1] == 1)
			{
				//播放相应的提示语言
				//延时一下, 表示开门
				sleep(1);
				//更新数组中的标识位
				j[nowf-1]=0;
				//刷新屏幕上的按键情况
				analyz(nowf);
				x1=x7;
				y1=y7;
				printf("x1=%d  y1=%d\n",x1,y1);
				if(x1==1)
				{
				lcd_draw_bmp(keybmp[nowf-1], 600,y1);//到了对应楼层灭
			
				}
				if(x1==0)
				{
				lcd_draw_bmp(keybmp[nowf-1], 700,y1);//到了对应楼层灭
				
				}
				h_num--;
				fenxi();
			}
			//延时一下, 表示正在上楼
			sleep(1);
			if (h_num == 0)
			{
					//去掉屏幕中间向上的箭头
					//1. 只刷新屏幕中间的区域, 然后显示当前楼层
					printf("现在在:%d\n",nowf);
					lcd_draw_bmp("refresh.bmp", 200,0);
					lcd_draw_bmp(numbmp[nowf-1],200,120);
					break;
					//2. 将整个界面都刷新一遍

电梯向下运行亦是如此。

7.设备解除初始化

结果:

在这里插入图片描述
电梯运行到第7层:

在这里插入图片描述
附上整个项目的开发文件压缩包:https://download.youkuaiyun.com/download/weixin_51165960/86543461

完结。

【资源说明】 毕设项目基于ARM-Linux的模拟电梯系统源码+项目说明.zip 开发环境:VScode、Ubuntu20.04、S5P6818开发板ARM架构-Linux操作系统) 技术栈:C++,饿汉模式,多线程,LCD显示屏,触摸屏, madplay移植,cmake 功能简介: (一)运行程序,电梯默认在1楼,显示屏左边可以循环播放广告,显示屏右边显示所有的楼层按键,有1楼~10楼。显示屏中间显示目前所在楼层,如果电梯在移动中,会显示上升或者下降的图标。 (二)按下对应楼层的按键后,按键会高亮显示。如果按下当前所在楼层的按键,则没有任何反应。再次按下已经高亮的按键,如果该楼层不是目前正在前往的楼层,则会取消前往该楼层,同时按键高亮取消。 (三)到达对应楼层,进行语音播报,如:“1楼到了”。 (四)乱序按下多个楼层的按键,则电梯运行顺序与正常电梯运行顺序完全一致。如: 1.当前在1楼,依次按下10,8,6,4,则电梯依次到达:4,6,8,10。 2.当前在5楼,依次按下10,7,2,4,则电梯依次到达:7,10,4,2。 3.当前在从6楼下降至5楼的过程中,依次按下9,7,1,3,则电梯依次到达:5,3,1,7,9。 代码结构: elevator.h elevator.cpp:电梯类的封装。实现记录当前所在楼层,按下的所有楼层,即将前往的楼层,以及电梯移动的逻辑控制。 lcd.h lcd.cpp:屏幕类的封装。以饿汉模式进行封装,保证只能创建一个单例对象,保证硬件资源的有序调用。实现LCD、触摸屏的硬件初始化以及资源释放,显示任意合理大小的bmp图片,获取手指按下的坐标或者滑动的方向 main.cpp:主循环不断获取来自触摸屏的信息,以更新电梯的运行状态。一条线程实现电梯的移动,一条线程循环播放广告, CMakeLists.txt:进入build文件夹,终端输入“cmake ..”,接着输入make,然后可执行文件target会生成在当前路径下 pic文件夹:所有用到的图片。 mp3文件夹:所有用到的播报音频。 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风-世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值