首页 > 其他分享 >基于并发电梯多媒体

基于并发电梯多媒体

时间:2024-09-20 10:54:48浏览次数:10  
标签:draw 多媒体 bmp 并发 电梯 lcd 楼层 array now

 功能实现伪代码

//大家可以参考一下大致实现过程

int floor_num[10] = {0}; //0表示楼层按键熄灭,1表示楼层按键点亮,10个元素对应10层楼
int cuccent_floor = 1; //当前楼层,默认在1楼
int floor_flag = 0;    //电梯运行标记  0表示停止,1表示向上,-1表示向下
int h_num = 0;    //当前楼层上面有多少楼层按键被按下了、
int l_num = 0;  //当前楼层下面有多少楼层按键被按下了

int main()
{
    设备初始化
        
    显示一个项目的进入界面或开机动画
        
    创建一个线程用于播放广告
        
    创建一个线程用于接受所按楼层信息并记录
    {
        while(1)
        {
            获取楼层信息(根据触摸屏按键,来判断是按下那个楼层)
            当前楼层不获取
            
            更新楼层数组中保存的标识符floor_num[]
            更新屏幕上的按键
                
            int h_n = 0, l_n = 0;
            for(int i = curren_foor+1; i < 11; i++)
            {
                if(floor_num[i-1] == 1)
                    h_n++; //记录当前楼层上面有多少楼层的按键被按下了
            }
            
            //记录当前楼层下面有多少楼层的按键被按下了  类比推导

            //加锁
            h_num = h_n; l_num = l_n;
            //解锁
        }
    }
    
    对记录的数据进行处理  --->  电梯开始运行
    while(1)
    {
        if(floor_flag == 0) //电梯停止
        {
            if(h_num > 0) //电梯有向上的请求
            {
                floor_flag = 1;
            }
            eles if(l_num > 0) //电梯有向下的请求
            {
                floor_flag = -1;
            }
        }
        
        //电梯向上运行
        if(floor_flag == 1)
        {
            for(; h_num != 0; current_floor++)
            {
                在屏幕中间显示当前楼层及向上的箭头
                    
                //如果当前楼层就是被按下的楼层  
                if(floor_num[current_floor-1] == 1)
                {
                    播放相应的提示语音/显示一张提示图片
                    延时一下,表示开门
                    更新楼层数组floor_num中的标志位
                    刷新屏幕中的按键情况(熄灭当前楼层对应的按键)
                    //加锁
                    h_num--;
                    //解锁
                }
                
                //延时一下,表示上楼
                
                //当到达按下的最高楼层
                if(h_num == 0)
                {
                    去掉屏幕中间的向上的箭头
                    
                    if(l_num == 0) //电梯没有向下的请求
                    {
                        floor_flag = 0; //电梯停止
                    }
                    else if(l_num > 0) //电梯有向下的请求
                    {
                        floor_flag = -1; //电梯向下
                    }
                }
            }
        }
        
        //电梯向下运行。。。。。
        if(floor_flag == -1)
        .......
    }   
}

"以下有关lcd的代码请参考2048项目中实现方法" 

main.c

头文件及定义

#include "touch.h"
#include "lcd.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
#include <stdbool.h>
#include <string.h>
#include <sys/wait.h>

#define FIFONAME "/home/work/elevator/vedio.fifo"
//定义一个互斥锁
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

struct array
{
	int x;//楼层按钮左上角的横坐标
	int y;//楼层按钮左上角的纵坐标
	bool flag;//0标识楼层未被按下或到达相应楼层, 1标识楼层被按下
}array[10];


int now = 1;//表示当前楼层
int target = 0;//表示目标楼层
int h_num = 0;//表示当前楼层上面有几个楼层被按下
int l_num = 0;//表示当前楼层下面有几个楼层被按下
int fd = -1;    //用于创建管道文件
char TTime[20] = {0};   //保存管道文件里的信息

int vedio = 0;
char* ad[] ={"./advertising.bmp","./ad1"};//左边广告图片
char* bmp[10] ={"./1.bmp","./2.bmp","./3.bmp","./4.bmp","./5.bmp","./6.bmp","./7.bmp","./8.bmp","./9.bmp","./10.bmp"};//中间按钮图标
char* bmp1[10] ={"./01.bmp","./02.bmp","./03.bmp","./04.bmp","./05.bmp","./06.bmp","./07.bmp","./08.bmp","./09.bmp","./010.bmp"};//白按钮图标
char* bmp2[10] ={"./001.bmp","./002.bmp","./003.bmp","./004.bmp","./005.bmp","./006.bmp","./007.bmp","./008.bmp","./009.bmp","./0010.bmp"};//黄按钮图标
char* mp4[] = {"1.mp4"};   //左边视频

创建有名管道来传输数据,将slave命令写入管道文件。

int create_FIFO()
{
    //创建有名管道
    int ret = mkfifo(FIFONAME, 0664);
    if(ret == -1 && errno != EEXIST)
    {
        perror("mkfifo error");
        return -1;
    }
}

//把slave命令写入管道文件
int slave_write_cmd(int fifo_fd,char *cmd)
{
    fd = open(FIFONAME, O_WRONLY);
    write(fd,cmd,strlen(cmd));
    close(fd);
    return 0;
}

初始化页面

//电梯按键初始化,坐标和标志位		
void array_init()
{
	array[0].x = 600;
	array[0].y = 384;
	array[0].flag = 0;
	
	array[1].x = 700;
	array[1].y = 384;
	array[1].flag = 0;
	
	array[2].x = 600;
	array[2].y = 288;
	array[2].flag = 0;
	
	array[3].x = 700;
	array[3].y = 288;
	array[3].flag = 0;
	
	array[4].x = 600;
	array[4].y = 192;
	array[4].flag = 0;
	
	array[5].x = 700;
	array[5].y = 192;
	array[5].flag = 0;
	
	array[6].x = 600;
	array[6].y = 96;
	array[6].flag = 0;
	
	array[7].x = 700;
	array[7].y = 96;
	array[7].flag = 0;
	
	array[8].x = 600;
	array[8].y = 0;
	array[8].flag = 0;
	
	array[9].x = 700;
	array[9].y = 0;
	array[9].flag = 0;
}

根据按下的坐标区域返回楼层数,display显示对应图片。

int eve()
{
    int e = -1;     //按下的楼层数
    int x = -1,y = -1;
    get_touch_xy_down(&x,&y);
    x /= 1.28;
    y /= 1.25;
    if(x >= 600 && x <= 700 && y >= 0 && y <= 96)
    {
        e = 9;
    }
    else if(x >= 700 && x <= 800 && y >= 0 && y <= 96)
    {
        e = 10;
    }
    else if(x > 600 && x < 700 && y > 96 && y < 192)
    {
        e = 7;
    }
    else if(x > 700 && x < 800 && y > 96 && y < 192)
    {
        e = 8;
    }
    else if(x > 600 && x < 700 && y > 192 && y < 288)
    {
        e = 5;
    }
    else if (x > 700 && x < 800 && y > 192 && y < 288)
    {
        e = 6;
    }
    else if(x > 600 && x < 700 && y > 288 && y < 384)
    {
        e = 3;
    }
    else if (x > 700 && x < 800 && y > 288 && y < 384)
    {
        e = 4;
    }
    else if(x > 600 && x < 700 && y > 384 && y < 480)
    {
        e = 1;
    }
    else if (x > 700 && x < 800 && y > 384 && y < 480)
    {
        e = 2;
    }
    return e;
}


void display(void)
{
    lcd_draw_bmp(600,384,bmp1[0]);
    lcd_draw_bmp(700,384,bmp1[1]);
    lcd_draw_bmp(600,288,bmp1[2]);
    lcd_draw_bmp(700,288,bmp1[3]);
    lcd_draw_bmp(600,192,bmp1[4]);
    lcd_draw_bmp(700,192,bmp1[5]);
    lcd_draw_bmp(600,96,bmp1[6]);
    lcd_draw_bmp(700,96,bmp1[7]);
    lcd_draw_bmp(600,0,bmp1[8]);
    lcd_draw_bmp(700,0,bmp1[9]);

}

 三个线程的实现函数分别是:检测到达的楼层并刷新图标,按键按下和再次按下的图标改变,和保存楼层上面或下面有多少层数的函数

 

//检测到达的楼层并刷新楼层图标
void* flash_lcd(void* f)
{
    while(1)
    {
        if(array[now - 1].flag)   //按下了该楼层
        {
            switch (now)
            {
            case 1:
                lcd_draw_bmp(600,384,bmp1[now - 1]);
                break;
            case 2:
                lcd_draw_bmp(700,384,bmp1[now - 1]);
                break;
            case 3:
                lcd_draw_bmp(600,288,bmp1[now - 1]);
                break;
            case 4:
                lcd_draw_bmp(700,288,bmp1[now - 1]);
                break;
            case 5:
                lcd_draw_bmp(600,192,bmp1[now - 1]);
                break;
            case 6:
                lcd_draw_bmp(700,192,bmp1[now - 1]);
                break;
            case 7:
                lcd_draw_bmp(600,96,bmp1[now - 1]);
                break;
            case 8:
                lcd_draw_bmp(700,96,bmp1[now - 1]);
                break;
            case 9:
                lcd_draw_bmp(600,0,bmp1[now - 1]);
                break;
            case 10:
                lcd_draw_bmp(700,0,bmp1[now - 1]);
                break;
            default:
                break;
            }
        }
    }
}

void* key_deal(void* k)
{
    while(1)
    {
        target = eve();
        array[target - 1].flag = !array[target - 1].flag;
        if(array[target - 1].flag)   //按下了该楼层
        {
            switch (target)
            {
            case 1:
                lcd_draw_bmp(600,384,bmp2[target - 1]);
                break;
            case 2:
                lcd_draw_bmp(700,384,bmp2[target - 1]);
                break;
            case 3:
                lcd_draw_bmp(600,288,bmp2[target - 1]);
                break;
            case 4:
                lcd_draw_bmp(700,288,bmp2[target - 1]);
                break;
            case 5:
                lcd_draw_bmp(600,192,bmp2[target - 1]);
                break;
            case 6:
                lcd_draw_bmp(700,192,bmp2[target - 1]);
                break;
            case 7:
                lcd_draw_bmp(600,96,bmp2[target - 1]);
                break;
            case 8:
                lcd_draw_bmp(700,96,bmp2[target - 1]);
                break;
            case 9:
                lcd_draw_bmp(600,0,bmp2[target - 1]);
                break;
            case 10:
                lcd_draw_bmp(700,0,bmp2[target - 1]);
                break;
            default:
                break;
            }
            continue;
        }
        else   //再次按下取消选择
        {
            switch (target)
            {
             case 1:
                lcd_draw_bmp(600,384,bmp1[target - 1]);
                break;
            case 2:
                lcd_draw_bmp(700,384,bmp1[target - 1]);
                break;
            case 3:
                lcd_draw_bmp(600,288,bmp1[target - 1]);
                break;
            case 4:
                lcd_draw_bmp(700,288,bmp1[target - 1]);
                break;
            case 5:
                lcd_draw_bmp(600,192,bmp1[target - 1]);
                break;
            case 6:
                lcd_draw_bmp(700,192,bmp1[target - 1]);
                break;
            case 7:
                lcd_draw_bmp(600,96,bmp1[target - 1]);
                break;
            case 8:
                lcd_draw_bmp(700,96,bmp1[target - 1]);
                break;
            case 9:
                lcd_draw_bmp(600,0,bmp1[target - 1]);
                break;
            case 10:
                lcd_draw_bmp(700,0,bmp1[target - 1]);
                break;
            default:
                break;
            }
            continue;
        }
    }
}

void* floor_info(void* f)//保存当前楼层上面或下面有多少层
{
    while(1)
    {
        int h_n = 0, l_n = 0;
        if(now ==target )
        {
             //lcd_draw_bmp(200,0,bmp1[now - 1]);
            continue;
        }

        else if(target > now)
        {
            for (int i = now + 1; i < 11; i++)
			{
				if (array[i-1].flag == 1)
				{
					h_n++;
				}
			}
            pthread_mutex_lock(&mutex1);
			h_num = h_n;
            pthread_mutex_unlock(&mutex1);
        }

        else if (target < now)
        {
            for (int i = now-1; i > 0; i--)
			{
				if (array[i-1].flag == 1)
				{
					l_n++;
				}
			}
            pthread_mutex_lock(&mutex2);
			l_num = l_n;
            pthread_mutex_unlock(&mutex2);
        }
    }
}

main函数建立线程,判断上下楼,初始化映射解除映射功能。

 

int main(int argc,char const* argv[])
{
    lcd_init();
    lcd_draw_bmp(0,0,"./main.bmp");

    sleep(2);
    lcd_draw_background(0xF5E2DC);
    lcd_draw_bmp(240,140,bmp[0]);
    lcd_draw_bmp(0,240,"./advertising.bmp");
    display();

    //创建有名管道,用来接收命令播放视频
    create_FIFO();
    
    pid_t ppid = fork();
    if(ppid > 0)
    {
        int flag = 0;
        int ret;
        pthread_t pid = -1; //保存线程的ID
        ret = pthread_create(&pid, NULL, key_deal, NULL);
        pthread_detach(pid);

        pthread_t pid1 = -1; //保存线程的ID
        ret = pthread_create(&pid1, NULL, floor_info, NULL);
        pthread_detach(pid1);

        pthread_t pid2 = -1; //保存线程的ID
        ret = pthread_create(&pid2, NULL, flash_lcd, NULL);
        pthread_detach(pid2);
        
    }   
    else if(ppid == 0)
    {
        int ret = execl("/usr/bin/mplayer", "mplayer",  "-quiet", 
        "-input","file=/home/work/elevator/vedio.fifo","-loop","0","-geometry", "0:0","-zoom","-x","200","-y","240",mp4[0], NULL);
        if(ret == -1)
        {
           exit(1);
        }
    }
    
    // pthread_join(pid,NULL);
    // pthread_join(pid1,NULL);
    while(1)
    {
        //上楼
        for( ; h_num > 0;now++)
        {
            //在屏幕中间显示向上的箭头
            lcd_draw_bmp(480,120,"./up.bmp");
            //在屏幕中间显示当前楼层
            lcd_draw_bmp(240,140,bmp[now-1]);
            if(array[now - 1].flag == 1)
            {
                //更新楼层中的标识位
                array[now-1].flag = 0;
               
                sleep(3);
                
                //恢复按键的颜色(白)
                lcd_draw_bmp(array[now-1].x,array[now-1].y,bmp1[now-1]);
                 //覆盖up,刷新屏幕中间的区域
                lcd_draw_bmp(480,120,"./restore_pic1.bmp");
                
                //sleep(5);
                pthread_mutex_lock(&mutex1);
                h_num--;
                pthread_mutex_unlock(&mutex1);
            }
            printf("上楼中\n");
            sleep(3);   //表示正在上楼

            if (h_num == 0)
            {
                lcd_draw_bmp(480,120,"./restore_pic1.bmp");//覆盖up,刷新屏幕中间的区域
                now--;
            }
        }
        //下楼
        for( ; l_num > 0;now--)
        {
            //在屏幕中间显示向下的箭头
            lcd_draw_bmp(480,120,"./down.bmp");
            //在屏幕中间显示当前楼层
            lcd_draw_bmp(240,140,bmp[now-1]);
            
            if(array[now - 1].flag == 1)
            {
                //更新楼层中的标识位
                array[now-1].flag = 0;

                sleep(3);
                

                //恢复按键的颜色(白)
                lcd_draw_bmp(array[now-1].x,array[now-1].y,bmp1[now-1]);
                                //覆盖up,刷新屏幕中间的区域
                lcd_draw_bmp(480,120,"./restore_pic1.bmp");
                
                //sleep(5);
                pthread_mutex_lock(&mutex2);
                l_num--;
                pthread_mutex_unlock(&mutex2);
            }
            printf("下楼中\n");
            sleep(3);   //表示正在下楼
            
            if (l_num == 0)
            {
                lcd_draw_bmp(480,120,"./restore_pic1.bmp");//覆盖down,刷新屏幕中间的区域
                now++;
            }
        }  
    }

    lcd_uninit();
    return 0;

}

全部代码:

链接:https://pan.baidu.com/s/1oPFlK_dykkqnwor5-4iO5w?pwd=j9h0 
提取码:j9h0

标签:draw,多媒体,bmp,并发,电梯,lcd,楼层,array,now
From: https://blog.csdn.net/qq_63147384/article/details/142378106

相关文章

  • 脏读!幻读!不可重复读!mysql并发事务引发的问题
    脏读!幻读!不可重复读!mysql并发事务引发的问题并发事务引发的三个问题①脏读脏读(DirtyRead)是数据库事务隔离级别中的一种现象。它发生在两个事务并发执行时,一个事务能够读取到另一个事务尚未提交的修改。脏读的具体情况事务A对某个数据进行了修改,但尚未提交。事务B在事务......
  • 高并发内存池
    个人主页:Lei宝啊 愿所有美好如期而遇一、项目介绍这个项目做的是什么?我们要实现一个高并发的内存池,当然,我们这个项目是参考google的一个开源项目tcmalloc而实现的一个迷你版的高并发内存池,实现高效的多线程内存管理,用于代替系统提供的malloc和free。 二、内存池1.......
  • Go语言grequests库并发请求的实战案例
    在当今快速发展的互联网时代,数据的获取和处理速度成为了衡量一个系统性能的重要标准。Go语言以其并发处理能力而闻名,而grequests库则为Go语言的HTTP请求提供了简洁易用的API。本文将通过一个实战案例,介绍如何使用Go语言的grequests库来实现高效的并发HTTP请求。1.引言在......
  • 【转】[C#] WebAPI 防止并发调用二(更多)
    转自:阿里的通义灵码接上篇:https://www.cnblogs.com/z5337/p/18181574在C#中防止接口的并发访问(即确保同一时间内只有一个线程能够访问某个资源或方法),可以通过多种方式实现。这里列出一些常见的方法:1.使用 lock 语句lock 是一种常用的同步原语,用于保护对共享资源的访问......
  • 优化下载性能:使用Python多线程与异步并发提升下载效率
    文章目录......
  • 揭秘:一行代码搞定.Net API高并发的烦恼!
            高并发下的接口请求重复提交问题在.Net开发中,我们经常遇到用户疯狂点击同一按钮,或者服务响应慢时重复发送请求,导致数据重复添加或混乱。这不仅浪费资源,更会得到错误的业务结果。如何高效解决这一普遍问题呢?        常规方案使用分布式锁 面对这问题......
  • 探索Go语言中的Goroutine并发机制
    什么是Goroutine在Go语言中,Goroutine是程序中最基本的并发单位。事实上,每个Go程序都会自动创建一个goroutine,那就是主goroutine,程序启动时会立即执行。Goroutine是Go语言中处理并发问题的核心工具,因此理解它的工作原理至关重要。简而言之,Goroutine是并发执行的函数,这些函......
  • 深入理解Go并发编程:避免Goroutine泄漏与错误处理
    Go语言以其强大的并发模型和高效的协程(goroutine)而闻名。协程的轻量级和易用性使得并发编程变得更加简单。然而,如果不正确管理协程,可能会导致Goroutine泄漏,从而消耗系统资源,影响程序性能。本文将深入探讨如何避免Goroutine泄漏,并提供实用的代码示例和技巧,帮助您编写更加健壮......
  • Go语言并发编程之Channels详解
    并发编程是Go语言的一大特色,而channel(通道)则是Go语言中用于实现并发的核心工具之一。它源于CSP(CommunicatingSequentialProcesses)的概念,旨在让多个goroutine之间能够高效地进行通信和同步。本文将深入探讨channel的用法、原理和最佳实践,通过丰富的示例代码和详细的解释,帮......
  • ChatGPT 多媒体应用设计师备考考点讲解(七):音视频编码与传输优化策略
    音视频编码与传输技术是多媒体应用设计中至关重要的环节。高效的音视频编码不仅能够保证内容质量,还可以减少带宽占用,提升传输效率。而在传输过程中,优化音视频流的传输策略可以降低延迟、减少丢包、保证播放的流畅性。在本篇文章中,我们将详细讲解音视频编码的基础知识、常见编码格式......