IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于GEC6818的嵌入式智能系统设计[开关灯/消消乐小游戏/蓝牙通信] -> 正文阅读

[嵌入式]基于GEC6818的嵌入式智能系统设计[开关灯/消消乐小游戏/蓝牙通信]

一、主要功能

进入主界面后,主界面是个人UI设计,有四个功能按钮模块,分别是:信息、灯光、娱乐(消消乐)、蓝牙。

二、涉及知识

C语言,文件io,bmp/jpg图片解析,Linux串口通信,linux基础

三、开发环境

嵌入式开发板型号GEC6818,开发平台Ubuntu18.04,代码编辑器source?insight 4.0

四、主要模块

1.LCD显示模块

????????通过open打开开发板LCD屏幕驱动,驱动文件(/dev/fb0),进行屏幕初始化。

/***************************************
	显示屏相关的一些功能函数
***************************************/


#include "lcd.h"
static int * plcd=NULL;
static int lcd_fp=-1;
#define LCD_PATH "/dev/fb0" //文件路径
/*
	lcd屏幕初始化
*/
int lcd_Init(void)
{
	lcd_fp=open(LCD_PATH,O_RDWR);
	if(lcd_fp==-1)
	{
		perror("open failed:");
		return -1;
	}
	plcd=mmap(NULL,LCD_HEIGHT*LCD_WIDTH*4,PROT_WRITE|PROT_READ,MAP_SHARED,lcd_fp,0);
	if(plcd == MAP_FAILED)
	{
		perror("MMAP Failed");
		return -1;
	}
	return 0;
}

? ? ? ? 开发板是通过像素打点的形式显示图片,于是需要封装一个像素打点函数

/*
	像素打点函数
*/
void Lcd_Draw_Point(int x,int y,int color)
{
		*(plcd + LCD_WIDTH*y + x) = color;
}

????????然后通过系统IO(read)和标准IO(fread)读取bmp及jpg图片像素数据。其中jpg文件为压缩文件需先进行解压缩操作,通过write写入屏幕驱动里面。具体操作需要将模块封装成函数Display_Bmp(),以便调用。对JPEG图片的显示通过jpeglib库实现,具体函数已封装为Display_Jpg()。因本工程所使用的素材皆为jpg图片,故这里只放出jpg显示函数。

#include "jpg.h"

/***************************************
	跟JPG图片显示相关的功能模块(函数)
***************************************/

/*
	将jpgpath所指向的JPG图片显示到屏幕的(x0,y0)处
		成功显示返回0,失败返回-1	
*/
int Display_Jpg(int x,int y,const char *jpgpath)
{
	struct jpeg_decompress_struct dinfo;	//定义一个解压对象
	struct jpeg_error_mgr jerr;				//定义一个出错信息的对象

	dinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&dinfo);

	//用标准IO打开JPG图片
	FILE *infile = fopen(jpgpath,"r");
	if(infile == NULL)
	{
		perror("Fopen JPG Failed");
		return -1;
	}
	jpeg_stdio_src(&dinfo,infile);

	jpeg_read_header(&dinfo,TRUE);

	jpeg_start_decompress(&dinfo);

	unsigned char *buffer = malloc(dinfo.output_width * dinfo.output_components);
	unsigned char a = 0,r,g,b;
	unsigned int color;
	int i = 0;
	//output_scanline保存的是当前已经扫描了多少行,初始化为0
	while(dinfo.output_scanline < dinfo.output_height)
	{
		i = 0;
		//第一个参数表示解压对象
		//第二个参数表示保存解压后数据的二级指针
		//第三个参数表示读取多少行数据来进行解压
		jpeg_read_scanlines(&dinfo,&buffer,1);
		//每扫描一行output_scanline + 1

		int j = 0;
		for(j = 0;j < dinfo.output_width;j++)
		{
			if(dinfo.output_components == 4)
			{
				a = buffer[i++];
			}
			r = buffer[i++];
			g = buffer[i++];
			b = buffer[i++];
			color = (a << 24) | (r << 16) | (g << 8) | b;
			Lcd_Draw_Point(x+j,y+dinfo.output_scanline-1,color);
		}
	}

	jpeg_finish_decompress(&dinfo);

	jpeg_destroy_decompress(&dinfo);

	free(buffer);
	fclose(infile);
	
	return 0;
}

主系统显示效果

2.触摸屏模块

????????打开触摸屏的驱动文件 /dev/input/event0,然后调用read从触摸文件读取触摸信息,通过判断触摸坐标来确定触摸点位置,从而使能相关按键

#include "touch.h"
#include "main.h"
/***************************************
	跟触摸屏相关的一些功能函数
***************************************/

int Get_Touch(void)
{
	//打开触摸屏文件
	int fd_touch = open(TOUCH_PATH,O_RDWR);
	if(fd_touch == -1)
	{
		perror("open touch file failed:");
		return -1;
	}
	
	int ret;
	struct input_event ev;
	int Tx=0,Ty=0,Lx=0,Ly=0;
	int x = -1,y = -1,z=-1,i=1,j=3;
		while(1)
		{	
			ret = read(fd_touch,&ev,sizeof(ev));
			if(ret != sizeof(ev))
			{	
				continue;
			}
			if(ev.type == EV_ABS && ev.code == ABS_X)
			{
				//x轴的坐标输入事件
				x = ev.value;
			}
			else if(ev.type == EV_ABS && ev.code == ABS_Y)
			{
				//y轴的坐标输入事件
				y = ev.value;			
			}
			if(j!=0)
			{
				j--;
				continue;
			}
			if (i)
			{
				if(x >= 0 && y >= 0 && ev.value != 0)
				{
					//printf("Touch Point [ %d %d ]\n",x,y);
					Tx=x*800/1024;
					Ty=y*480/600;
					printf("-------------------------");
					printf("Touch Point [ %d %d ]\n",Tx,Ty);
					i--;
				}
			}
			else if(ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0)
			{
				//手指离开了屏幕
				//printf("Leave Point [ %d %d ]\n",x,y);
				Lx=x*800/1024;
				Ly=y*480/600;
				
				printf("-------------------------");
				printf("Leave Point [ %d %d ]\n",Lx,Ly);
				i=1;				
				j=3;
			}
			
			if(abs(Lx-Tx)<200 && abs(Ly-Ty)<200 && Tx>=200 && Tx<620 && Ty>=30 && Ty<450)//交互判断
			{
				panduan(Tx,Ty,Lx,Ly);
				Tx=0;
				Ty=0;
				Lx=0;
				Ly=0;
			}
			if(Tx>=650&&Ty>=300&&Ty<=360)//new game
			{
				map_interface();
			}
			if(Tx>=650&&Ty>=390&&Ty<=450)//quit game
			{
				//Display_Jpg(0,0,PATH_quitgame);
				printf("游戏结束\n");
				key();
			}
			
		}
	
	return 0;
}

3.串口通信

? ? ? ? 由于本项目中需要用到蓝牙模块与开发板通信从而操控响应相关功能按键,所以需要进行串口初始化。串口相关代码如下:

#include "Uart.h"
int Uart_Init(const char * uart_name)
{
	/*设置串口
	  波特率:9600
	  数据位:8
	  校验位:不要
	  停止位:1
	  数据流控制:无
	  */
	
	int   uart_fd= open(uart_name, O_RDWR);//打开串口1设备文件
	if (uart_fd == -1)
	{
		perror("open error:");
		return -1;
	}

	struct termios myserial;
	//清空结构体
	memset(&myserial, 0, sizeof (myserial));
	//O_RDWR               
	myserial.c_cflag |= (CLOCAL | CREAD);
	//设置控制模式状态,本地连接,接受使能
	//设置 数据位
	myserial.c_cflag &= ~CSIZE;   //清空数据位
	myserial.c_cflag &= ~CRTSCTS; //无硬件流控制
	myserial.c_cflag |= CS8;      //数据位:8

	myserial.c_cflag &= ~CSTOPB;//   //1位停止位
	myserial.c_cflag &= ~PARENB;  //不要校验

	cfsetospeed(&myserial, B9600);  //设置波特率,B9600是定义的宏
	cfsetispeed(&myserial, B9600);

	/* 刷新输出队列,清除正接受的数据 */
	tcflush(uart_fd, TCIFLUSH);

	/* 改变配置 */
	tcsetattr(uart_fd, TCSANOW, &myserial);
	return   uart_fd;
}

4.游戏模块(消消乐)

? ? ? ? 消消乐小游戏的设计核心

????????(1)游戏开始界面设计

? ? ? ? ?(2)随机游戏界面生成(二维数组)

#include "game.h"

/***************************************
	项目相关的主逻辑函数
***************************************/

int xxl[7][7];			//全局变量,地图数组
int xiao[7][7]={0};		//全局变量,地图标志数组
int count=0;			//全局变量,判断遍历时的相同个数
int direction;			//全局变量,用于记录方向
int fangxiang;			//全局变量,用于记录判断的方向
int score;				//全局变量,用于记录游戏得分


/*
	用来产生随机数,随机数的范围是[0,num-1]
*/

int Get_Random(int num)//生成随机数,形参用于控制随机数范围[0,num]
{
	
	int x=random()%num;
	return x;
}
int map_interface(void)//生成随机界面
{
	/*
	*/
	//用来设置随机数种子
	srandom(time(NULL));
	score=0;
	int i,j,k;
	char JPG_PATH[30];
	printf("游戏开始!\n");	
	for(i=0;i<7;i++)
	{
		for(j=0;j<7;j++)
		{
			xxl[i][j]=Get_Random(7);   //随机数组赋值
			k=xxl[i][j];
			switch (k)
			{
				case 0:strcpy(JPG_PATH,JPG_PATH0);
				break;
				case 1:strcpy(JPG_PATH,JPG_PATH1);
				break;
				case 2:strcpy(JPG_PATH,JPG_PATH2);
				break;
				case 3:strcpy(JPG_PATH,JPG_PATH3);
				break;
				case 4:strcpy(JPG_PATH,JPG_PATH4);
				break;
				case 5:strcpy(JPG_PATH,JPG_PATH5);
				break;
				case 6:strcpy(JPG_PATH,JPG_PATH6);
				break;
				default:return 0 ;
				break;
			}
			Display_Jpg(i*60+60+140,j*60+60-30,JPG_PATH);//显示游戏界面图片
		}
		Display_Jpg(650,300,PATH_newgame);//显示重新开始按钮
		Display_Jpg(650,390,PATH_quit);//显示游戏结束按钮
		Display_Jpg(630,30,SCORE_PATH);//显示分数框图
		Display_Jpg(740,45,PATH0);//初始化分数0
	}
	return 0;
}

? ? ? ? (3)通过触摸屏判断用户滑动方向实现消消乐元素交换

/*
	获取从触摸板获取的坐标
	换算成二维数组坐标以及用户滑动方向
*/
int panduan(int Tx,int Ty,int Lx,int Ly)
{
	int Ti,Tj,Li,Lj;
	Ti=(Tx-200)/60;			//获取二维数组坐标
	Tj=(Ty-30)/60;
	
	if(Lx-Tx>15)			//判断方向
	{
		 Li=Ti+1;
		 fangxiang='r';		//右
	}
	else if(Lx-Tx<-15)
	{
		 Li=Ti-1;
		 fangxiang='l';		//左
	}
	else
	{
		Li=Ti;
	}
	if(Ly-Ty>15)
	{
		 Lj=Tj+1;
		 fangxiang='d';		//下
	}
	else if(Ly-Ty<-15)
	{
		 Lj=Tj-1;
		 fangxiang='u';		//上
	}
	else
	{
		Lj=Tj;
	}
	
	if((xxl[Ti][Tj]==-1)||(xxl[Li][Lj]==-1)||(xxl[Ti][Tj]==xxl[Li][Lj]))//起始点与离开点对应数组元素不能相同,并且不能为被消元素
	{return 0;}
	
	
	
	if((Ti!=Li && Tj!=Lj)|| abs(Ti-Li)>1 || abs(Tj-Lj)>1 ||Li>6 ||Lj>6)//起始点与离开点不能是同一点
	{
		return 0;
	}
	else
	{
		map2(Ti,Tj,Li,Lj);
	}
	
}

? ? ? ? (4)交换后判断是否可消,可消则执行可消操作,否则执行交换元素复原

int map_updatax(void)
{
	int i,j,k;
	for(j=0;j<7;j++)
	{
		for(i=0;i<7;i++)
		{
			if(traverse_map(i,j,0,0)==0)//不能消
			{
				continue;
			}
			else//可消
			{
				map4();//标记
				usleep(250000);
				map3();//重显
				//usleep(100000);
				map_updata();//掉落更新
			}
		}
	}
}
int map_updata(void)//消了以后地图更新
{
	
	int i,j,flag=0;
	
	for(j=0;j<7;j++)
	{
		for(i=0;i<7;i++)
		{
			if((xxl[i][j]==-1)&&j!=0)//若该元素为被消除元素则与上一行进行互换
			{
				map_restore(i,j,i,j-1);
				flag=1;
			}
			if((xxl[i][j]==-1)&&j==0)//若该元素为顶层元素则随机产生新的图片
			{
				xxl[i][j]=Get_Random(7);//给随机数
				flag=1;
			}
		}
		
	}
	if(flag==0)//找不到被消除元素则结束递归
	{
		return 0;
	}
	map3();
	map_updata();//递归调用本身重复遍历是否还有被消除元素
	return 0;
}

?5.控制模块(用于总系统界面控制判定)

#include "Key.h"

int game(void)
{
	//LCD屏幕的初始化
	lcd_Init();
	//清屏
	Init_color(white);
	//获取BMP图片
	//Display_Bmp(0,0,BMP_PATH);
	//获取JPG图片
	Display_Jpg(0,0,JPG_PATHx);
	
	while(1)
	{
		if(Get_Touchx()==1)
		{
			break;
		}
	
	}
	//生成背景图片
	Display_Jpg(0,0,JPG_PATHb);
	//生成随机游戏界面
	map_interface();
	/*
		触摸信息相关函数
	*/
	Get_Touch();
	//LCD屏幕的解初始化
	Lcd_Uinit();
	return 0;
}

int key(void)
{
	Display_Jpg(0,0,PATH_system);
   
   while(1)
    {	
		switch (Get_Touchs())//选择进入不同模块
		{	
	    	case 2: //娱乐		
			game();
			break;
			case 1://灯光
			led();
			break;
			
			
			case 4://蓝牙
			bluetooth();
			break;
			default:return 0;
			break;
		}
	
    }
    return 0;
}
int bluetooth(void)
{	
	Display_Jpg(0,0,PATH_system);
	Display_Jpg(580,315,PATH_blutooth);

	printf("蓝牙模式!\n");
	unsigned char readbuf[256]={0};
	int uart1_fd = Uart_Init("/dev/ttySAC1");
	while(1)
	{
		int r = read(uart1_fd,readbuf,256);
		if(!strcmp(readbuf,"灯光"))//灯光模块
		{
			puts(readbuf);
			led_init();
			while(1)
			{
				read(uart1_fd,readbuf,256);
				if(strcmp(readbuf,"开灯"))
				{
					led_bluetooth(1);
				}
				else if(strcmp(readbuf,"关灯"))
				{
					led_bluetooth(0);
				}
				if(!strcmp(readbuf,"退出灯光"))
				{
					printf("退出灯光\n");
		
					bluetooth();
				}
			}
		}
		if(!strcmp(readbuf,"娱乐"))//娱乐模块
		{
			game();
		}
		if(!strcmp(readbuf,"退出蓝牙"))
		{
			key();
		}
	}
	close(uart1_fd);
	return 0;
}

五、效果图展示

??????

完整工程文件下载地址:https://download.csdn.net/download/weixin_56681901/21614333

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 09:30:35  更:2021-08-28 09:32:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 18:49:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计