基于C语言的电梯多媒体呼叫系统

目录

前言

一、开发环境

二、开发工具

三、技术要点

四、功能代码

1.主界面显示

2.电梯操作

        1、电梯主界面

2、电梯运行

3、触摸屏

 

总结

 



前言

本项目是我学习完C语言、数据结构、文件IO、系统编程部分内容,独立开发出来的一个项目,该项目功能主要是:

模拟电梯运行,

电梯到达相应楼层播报,

电梯广告投放,

广告实时切换,

响应多个楼层按键要求。


一、开发环境

VScode、wsL(windows下的linux系统)

二、开发工具

GEC6818开发板 800*480
交叉编译工具:arm-linux-gnueabi-5.4.0.tar.xz
串口:secure CRT
传输:tftp技术

三、技术要点

C语言 ,文件IO ,数据结构、系统编程

四、功能代码

1.主界面显示

图示:

代码:

void main_into(LCD* lcd)
{
    int change_signal_fun;
    
    //播放欢迎音频
    system("madplay mp3/1.mp3 &"); 

    //显示界面
    show_anybmp(800, 480, 0, 0, "photo/main.bmp", lcd);
    change_signal_fun = get_xy(lcd,NULL);//获取下一步操作
    if(change_signal_fun == main_click)
    {
        fun_select = operation_fun;
    }
}

2.电梯操作

1、电梯主界面
图示:

2、电梯运行

图示:

代码:
void elevator_operation(LCD* lcd)  
{ 
    // 创建共享内存  
    int shmid = shmget(10, sizeof(struct elevator), IPC_CREAT | 0777);  
    if (shmid == -1) 
    {  
        perror("shmget");  
        return;
    }  

    // 将共享内存附加到进程的地址空间  
    struct elevator *shm = shmat(shmid, NULL, 0);  
    if (shm == (struct elevator *) -1) 
    {  
        perror("shmat");  
        return; 
    }  

    // 初始化电梯信息  
    shm->cur_floor = one;// 刚开始在第一楼  
    shm->cur_floor_last = one;  
    shm->direction = up;  
    memset(shm->elevator_status, 0, sizeof(shm->elevator_status));//初始化按钮状态  

    // 显示工作界面  
    show_anybmp(800, 480, 0, 0, "photo/elevatorinterface.bmp", lcd);  
    // 显示初始楼层  
    show_anybmp(200, 200, 258, 130, "photo/1.bmp", lcd);  
    
    pid_t pid_one = fork();  
    if (pid_one > 0)
    {  
        // 创建显示广告的子进程  
        pid_t pid_two = fork();  
        if (pid_two > 0) // 父进程:电梯运行  
        {  
            while (1)   
            {  

                shm->cur_floor_last = shm->cur_floor;  

                // 根据电梯当前方向判断新楼层  
                if (shm->direction == up)   
                {  
                    shm->cur_floor = judge_high(shm->cur_floor, shm->elevator_status);  
                    if(shm->cur_floor == shm->cur_floor_last)
                    {
                        shm->direction = down;
                    }
                }   
                else   
                {  
                    shm->cur_floor = judge_low(shm->cur_floor, shm->elevator_status);  
                    if(shm->cur_floor == shm->cur_floor_last)
                    {
                        shm->direction = up;
                    } 
                }  

                elevator_move(shm->cur_floor_last, shm->cur_floor, lcd, shm->elevator_status);
                sleep(0.1);//减少cpu的耗费
            }  
        }   
        else if (pid_two == 0) // 子进程:显示广告   
        {  
            while (1)   
            {  
                show_anybmp(200, 480, 0, 0, "photo/ad2.bmp", lcd);  
                sleep(3);  
                show_anybmp(200, 480, 0, 0, "photo/ad1.bmp", lcd);  
                sleep(3);  
            }  
        }   
    }  
    else if (pid_one == 0) // 子进程获取按键状态   
    {  
        while (1)   
        {
            sleep(0.2);//减除父子进程的竞态  
            get_xy(lcd, shm->elevator_status); // 获取按键状态并更新 shm->elevator_status  
        }  
    }  
 
    shmdt(shm); // 解除共享内存的映射  
    shmctl(shmid, IPC_RMID, NULL); // 删除共享内存   
}  
解释:此部分代码是电梯运行的主函数,其中代码运用进程创建函数fork,创建了两个子进程和一个父进程;其中父进程用于电梯运行,一个子进程用于广告播放,一个子进程用于电梯按键坐标的获取。
代码:
//判断高楼层是否有人按楼层
int judge_high(int change_signal_fun, int* elevator_staus)
{
    if(change_signal_fun == ten)  return change_signal_fun;
    for(int i=change_signal_fun; i<=ten; i++)
    {
        if(elevator_staus[i])
           return i;
    }
    return change_signal_fun;
}

//判断低楼层是否有人按楼层
int judge_low(int change_signal_fun, int* elevator_staus)
{
    if(change_signal_fun == one)  return change_signal_fun;
    for(int i=change_signal_fun; i>=one; i--)
    {
        if(elevator_staus[i])
           return i;
    }
    return change_signal_fun;
}
解释:此部分代码用于判断高楼层和低楼层是否有人按电梯,然后反馈给电梯运行主函数,做出相应的响应。
代码:
void elevator_move(int change_signal_fun_last, int change_signal_fun, LCD* lcd, int* elevator_staus)
{
    char buf[100]= {""};
    if(change_signal_fun > change_signal_fun_last)
    {
        for(int i=change_signal_fun_last; i<=change_signal_fun; i++)
        {
          //显示相关图片(向上图片,楼层变化图片)
          show_anybmp(120, 120, 470, 78, "photo/up.bmp", lcd);//向上
          sprintf(buf, "photo/%d.bmp", i+1);
          show_anybmp(200, 200, 258, 130, buf, lcd);//楼层
          sleep(1);
           if(1==elevator_staus[i])
           {
                //相应楼层播报,楼层按键恢复,状态归0
                switch(i)
                {
                    case one: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 384, "photo/01.bmp", lcd);
                        system("madplay  mp3/01.mp3 &");
                        elevator_staus[0] = 0;
                        break;
                    case two: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 384, "photo/02.bmp", lcd);
                        system("madplay  mp3/02.mp3 &");
                        elevator_staus[1] = 0;
                        break;
                    case three: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 288, "photo/03.bmp", lcd);
                        system("madplay  mp3/03.mp3 &");
                        elevator_staus[2] = 0;
                        break;
                    case four: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 288, "photo/04.bmp", lcd);
                        system("madplay  mp3/04.mp3 &");
                        elevator_staus[3] = 0;
                        break;
                    case five: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 192, "photo/05.bmp", lcd);
                        system("madplay  mp3/05.mp3 &");
                        elevator_staus[4] = 0;
                        break;
                    case six: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 192, "photo/06.bmp", lcd);
                        system("madplay  mp3/06.mp3 &");
                        elevator_staus[5] = 0;
                        break;
                    case seven: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 96, "photo/07.bmp", lcd);
                        system("madplay  mp3/07.mp3 &");
                        elevator_staus[6] = 0;
                        break;
                    case eight: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 96, "photo/08.bmp", lcd);
                        system("madplay  mp3/08.mp3 &");
                        elevator_staus[7] = 0;
                        break;
                    case nine: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 0, "photo/09.bmp", lcd);
                        system("madplay  mp3/09.mp3 &");
                        elevator_staus[8] = 0;
                        break;
                    case ten: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 0, "photo/010.bmp", lcd);
                        system("madplay  mp3/010.mp3 &");
                        elevator_staus[9] = 0;
                        break;
                }
                sleep(1);
           }
        }
    }
    else if(change_signal_fun < change_signal_fun_last)
    {
        for(int i=change_signal_fun_last; i>=change_signal_fun; i--)
        {
          //显示相关图片(向下图片,楼层变化图片)
          show_anybmp(120, 120, 470, 282, "photo/down.bmp", lcd);//向下
          sprintf(buf, "photo/%d.bmp", i+1);
          show_anybmp(200, 200, 258, 130, buf, lcd);//楼层
          sleep(1);
           if(1==elevator_staus[i])
           {
                //相应楼层播报,楼层按键恢复,状态归0
                switch(i)
                {
                    case one: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 384, "photo/01.bmp", lcd);
                        system("madplay  mp3/01.mp3 &");
                        elevator_staus[0] = 0;
                        break;
                    case two: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 384, "photo/02.bmp", lcd);
                        system("madplay  mp3/02.mp3 &");
                        elevator_staus[1] = 0;
                        break;
                    case three: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 288, "photo/03.bmp", lcd);
                        system("madplay  mp3/03.mp3 &");
                        elevator_staus[2] = 0;
                        break;
                    case four: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 288, "photo/04.bmp", lcd);
                        system("madplay  mp3/04.mp3 &");
                        elevator_staus[3] = 0;
                        break;
                    case five: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 192, "photo/05.bmp", lcd);
                        system("madplay  mp3/05.mp3 &");
                        elevator_staus[4] = 0;
                        break;
                    case six: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 192, "photo/06.bmp", lcd);
                        system("madplay  mp3/06.mp3 &");
                        elevator_staus[5] = 0;
                        break;
                    case seven: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 96, "photo/07.bmp", lcd);
                        system("madplay  mp3/07.mp3 &");
                        elevator_staus[6] = 0;
                        break;
                    case eight: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 96, "photo/08.bmp", lcd);
                        system("madplay  mp3/08.mp3 &");
                        elevator_staus[7] = 0;
                        break;
                    case nine: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 0, "photo/09.bmp", lcd);
                        system("madplay  mp3/09.mp3 &");
                        elevator_staus[8] = 0;
                        break;
                    case ten: 
                        show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 0, "photo/010.bmp", lcd);
                        system("madplay  mp3/010.mp3 &");
                        elevator_staus[9] = 0;
                        break;
                }
                sleep(1);
           }
        }
    }
    else //就在某一层按电梯
    {
        for(int i=change_signal_fun_last; i<=change_signal_fun; i++)
        {
            if(1==elevator_staus[i])
            {
                    //相应楼层播报,楼层按键恢复,状态归0
                    switch(i)
                    {
                        case one: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 384, "photo/01.bmp", lcd);
                            system("madplay  mp3/01.mp3 &");
                            elevator_staus[0] = 0;
                            break;
                        case two: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 384, "photo/02.bmp", lcd);
                            system("madplay  mp3/02.mp3 &");
                            elevator_staus[1] = 0;
                            break;
                        case three: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 288, "photo/03.bmp", lcd);
                            system("madplay  mp3/03.mp3 &");
                            elevator_staus[2] = 0;
                            break;
                        case four: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 288, "photo/04.bmp", lcd);
                            system("madplay  mp3/04.mp3 &");
                            elevator_staus[3] = 0;
                            break;
                        case five: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 192, "photo/05.bmp", lcd);
                            system("madplay  mp3/05.mp3 &");
                            elevator_staus[4] = 0;
                            break;
                        case six: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 192, "photo/06.bmp", lcd);
                            system("madplay  mp3/06.mp3 &");
                            elevator_staus[5] = 0;
                            break;
                        case seven: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 96, "photo/07.bmp", lcd);
                            system("madplay  mp3/07.mp3 &");
                            elevator_staus[6] = 0;
                            break;
                        case eight: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 96, "photo/08.bmp", lcd);
                            system("madplay  mp3/08.mp3 &");
                            elevator_staus[7] = 0;
                            break;
                        case nine: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 0, "photo/09.bmp", lcd);
                            system("madplay  mp3/09.mp3 &");
                            elevator_staus[8] = 0;
                            break;
                        case ten: 
                            show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 0, "photo/010.bmp", lcd);
                            system("madplay  mp3/010.mp3 &");
                            elevator_staus[9] = 0;
                            break;
                    }
                sleep(1);
            }
        }
    }
    if(change_signal_fun > change_signal_fun_last)
        show_anybmp(120, 120, 470, 78, "photo/restore_pic1.bmp", lcd);//遮盖方向图片
    else
        show_anybmp(120, 120, 470, 282, "photo/restore_pic2.bmp", lcd);//遮盖方向图片
}
解释:此部分代码用于实现电梯移动,也就是根据上述判断楼层代码,模拟出电梯运行的相关响应。

3、触摸屏

#include "myhead.h"


//获取坐标
int get_xy(LCD* lcd, int* elevator_staus)
{
    int cur_x, cur_y;
    int tsfd;
	//定义一个结构体存放触摸屏的坐标
	struct input_event myevent;
	
	//第一步;打开触摸屏的驱动
	tsfd=open("/dev/input/event0",O_RDWR);
	if(tsfd == -1)
	{
		perror("打开触摸屏失败\n");
	}
	
	while(1)
	{
		//读取触摸屏点击的坐标位置
		read(tsfd,&myevent,sizeof(myevent));
		
		//判断事件类型
		if(myevent.type==EV_ABS) //说明是触摸屏的驱动
		{
			//判断是x坐标,还是y坐标
			if(myevent.code==ABS_X) //说明读取的x坐标
            {
                printf("x坐标是: %d\n",(myevent.value*800)/1024);
                cur_x = (myevent.value*800)/1024;
            }
			if(myevent.code==ABS_Y) //说明读取的y坐标
            {
				printf("y坐标是: %d\n",(myevent.value*480)/600);
                cur_y = (myevent.value*480)/600;
            }

            //判断在哪个区域,从而执行哪个功能函数
	        switch(fun_select)
			{
				case main_fun:
				               if((0<=cur_x&&cur_x<=800) && (0<=cur_y&&cur_y<=480))
							   {
								  return main_click;
							   }
				               break;
				case operation_fun:
				               if((600<=cur_x&&cur_x<=700) && (384<=cur_y&&cur_y<=480))//按一楼,显示按了一楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 384, "photo/001.bmp", lcd);
								  elevator_staus[0] = 1;
								  return one;
							   }
							   else if((700<=cur_x&&cur_x<=800) && (384<=cur_y&&cur_y<=480))//按二楼,显示按了二楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 384, "photo/002.bmp", lcd);
								  elevator_staus[1] = 1;
								  return two;
							   }
							   else if((600<=cur_x&&cur_x<=700) && (288<=cur_y&&cur_y<=384))//按三楼,显示按了三楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 288, "photo/003.bmp", lcd);
								  elevator_staus[2] = 1;
								  return three;
							   }
							   else if((700<=cur_x&&cur_x<=800) && (288<=cur_y&&cur_y<=384))//按四楼,显示按了四楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 288, "photo/004.bmp", lcd);
								  elevator_staus[3] = 1;
								  return four;
							   }
							   else if((600<=cur_x&&cur_x<=700) && (192<=cur_y&&cur_y<=288))//按五楼,显示按了五楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 192, "photo/005.bmp", lcd);
								  elevator_staus[4] = 1;
								  return five;
							   }
							   else if((700<=cur_x&&cur_x<=800) && (192<=cur_y&&cur_y<=288))//按六楼,显示按了六楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 192, "photo/006.bmp", lcd);
								  elevator_staus[5] = 1;
								  return six;
							   }
							   else if((600<=cur_x&&cur_x<=700) && (96<=cur_y&&cur_y<=192))//按七楼,显示按了七楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 96, "photo/007.bmp", lcd);
								  elevator_staus[6] = 1;
								  return seven;
							   }
							   else if((700<=cur_x&&cur_x<=800) && (96<=cur_y&&cur_y<=192))//按八楼,显示按了八楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 96, "photo/008.bmp", lcd);
								  elevator_staus[7] = 1;
								  return eight;
							   }
							   else if((600<=cur_x&&cur_x<=700) && (0<=cur_y&&cur_y<=96))//按九楼,显示按了九楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 600, 0, "photo/009.bmp", lcd);
								  elevator_staus[8] = 1;
								  return nine;
							   }
							   else if((700<=cur_x&&cur_x<=800) && (0<=cur_y&&cur_y<=96))//按十楼,显示按了十楼的图片
							   {
								  show_anybmp(PHOTO_WIDTH, PHOTO_HIGH, 700, 0, "photo/0010.bmp", lcd);
								  elevator_staus[9] = 1;
								  return ten;
							   }
				               break;
			}
		}
	}
	//关闭
	close(tsfd);
}
解释:获取点击区域,从而模拟出电梯按键,比如点击一楼,那么显示按键为一楼的按钮变为黄色,表示按了一楼,其中数组elevator_staus表示电梯1-10楼的状态,1表示有人按了此楼电梯,0表示没有,因为用了一个子进程来获取点击坐标,更新电梯状态;用了一个父进程来进行电梯运行,而且两个进程都要用到这个数组,那么就要让父子进程通信,这里用的方法是共享内存的方法。

总结

在做这个项目遇到的最大的问题,就是父子进程之间通信的竞争状态问题,这个问题困扰了很久。它最主要造成的问题就是按键状态显示随机,不能正确显示,后来经过网上查询,通过使用sleep函数,采用延时技术,让父子进程执行时间不一样,就可以避免父子进程的竞争。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值