目录
前言
本项目是我学习完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);
}