目录
这是我制作了象棋游戏这个项目后,自己花了几个小时重新写的一个类,仅供参考。
一、效果演示
1.清屏
2.等待获取坐标
3.指定位置映射了一个棋子
4.抠取原底图并指定位置让它覆盖棋子,实现复原效果
5.进度条是动态的,这里以图片代替
二、代码
1.Lcd.cpp
#include "Lcd.h"
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 数据的初始化 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 无 *
*******************************************************/
Lcd::Lcd(void)
{
//变量初始化
w = 0;
h = 0;
pix = 0;
fd = 0;
touch_screen_fd = 0;
one_x = 0;
one_y = 0;
tow_x = 0;
tow_y = 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 打开lcd屏幕 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::open_lcd(void)
{
//打开lcd设备
this->fd = open("/dev/fb0", O_RDWR);
if (this->fd < 0)
{
return -1;
}
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 关闭lcd屏幕 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::close_lcd(void)
{
//关闭lcd设备
int fd_close = close(this->fd);
if (fd_close < 0)
{
return -1;
}
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 申请lcd屏幕映射 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::apply_for(void)
{
//获取lcd参数
struct fb_var_screeninfo vinfo;
int ret = ioctl(this->fd, FBIOGET_VSCREENINFO, &vinfo);
w = vinfo.xres;
h = vinfo.yres;
pix = vinfo.bits_per_pixel / 8;
//映射
int ssize = w * h * pix;
mptr = (unsigned int*)mmap(NULL, ssize, PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, 0);
if (mptr == MAP_FAILED)
{
return -1;
}
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 销毁lcd屏幕映射 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 无 *
*******************************************************/
void Lcd::destruction_apply_for(void)
{
if (mptr != MAP_FAILED)
{
int ssize = w * h * pix;
munmap(mptr, ssize);
}
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 清屏 *
*------------------------------------------------------*
* 参 数: *
* color 要显示的颜色 *
* 返回值: *
* 无 *
*******************************************************/
void Lcd::clear(unsigned int color)
{
for (int i = 0; i < w * h; i++)
{
mptr[i] = color;
}
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 在lcd上显示800*480的图片 *
*------------------------------------------------------*
* 参 数: *
* pathname 图片的存放路径 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::show_bmp(const char* pathname)
{
int width, high; //图片亮度与高度
int i, j, x, y;
// 读取BMP格式头,获取图片信息
struct bitmap_header header;
struct bitmap_info info;
struct rgb_quad quad;
//打开图片,获取图片描述符
int bmp_fd = open(pathname, O_RDONLY);
if (bmp_fd == -1)
{
return -1;
}
// 第一、二个结构体是必有信息
read(bmp_fd, &header, sizeof(header));
read(bmp_fd, &info, sizeof(info));
//获取打开图片的大小
width = info.width;
high = info.height;
if (width > 800 || high > 480)
{
close(bmp_fd);
return -1;
}
//变长数组
unsigned char bmpbuff[width * high * 3];
unsigned int buff[width * high];
unsigned int tmpbuff[width * high];
read(bmp_fd, bmpbuff, sizeof(bmpbuff));
//图片像素点移动
for (i = 0; i < width * high; i++)
{
buff[i] = bmpbuff[3 * i + 0] | bmpbuff[3 * i + 1] << 8 | bmpbuff[3 * i + 2] << 16;
}
//图片像素点倒置
for (y = 0; y < high; y++)
{
for (x = 0; x < width; x++)
{
tmpbuff[(high - 1 - y) * width + x] = buff[y * width + x];
}
}
//图片像素显示
for (y = 0; y < high; y++)
{
for (x = 0; x < width; x++)
{
//遇到白色就跳过,不绘画,可将0xffffff修改成不需要的颜色
/*if (tmpbuff[y * width + x] == 0x00ffffff)
{
continue;
}*/
*(mptr + (y* 800) + x) = tmpbuff[y * width + x];
}
}
//关闭LCD文件
close(bmp_fd);
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 在lcd上显示指定起点位置的图片 *
*------------------------------------------------------*
* 参 数: *
* pathname 图片的存放路径 *
* start_x 绘画起点的x轴 *
* start_y 绘画起点的y轴 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::specified_show_bmp(const char* pathname, int start_x, int start_y)
{
int width, high; //图片亮度与高度
int i, j, x, y;
// 读取BMP格式头,获取图片信息
struct bitmap_header header;
struct bitmap_info info;
struct rgb_quad quad;
//打开图片,获取图片描述符
int bmp_fd = open(pathname, O_RDONLY);
if (bmp_fd == -1)
{
return -1;
}
// 第一、二个结构体是必有信息
read(bmp_fd, &header, sizeof(header));
read(bmp_fd, &info, sizeof(info));
//获取打开图片的大小
width = info.width;
high = info.height;
if (start_x + width > 800 || start_y + high > 480)
{
close(bmp_fd);
return -1;
}
//变长数组
unsigned char bmpbuff[width * high * 3];
unsigned int buff[width * high];
unsigned int tmpbuff[width * high];
read(bmp_fd, bmpbuff, sizeof(bmpbuff));
//图片像素点移动
for (i = 0; i < width * high; i++)
{
buff[i] = bmpbuff[3 * i + 0] | bmpbuff[3 * i + 1] << 8 | bmpbuff[3 * i + 2] << 16;
}
//图片像素点倒置
for (y = 0; y < high; y++)
{
for (x = 0; x < width; x++)
{
tmpbuff[(high - 1 - y) * width + x] = buff[y * width + x];
}
}
//图片像素显示
for (y = 0; y < high; y++)
{
for (x = 0; x < width; x++)
{
//遇到白色就跳过,不绘画,可将0xffffff修改成不需要的颜色
/*if (tmpbuff[y * width + x] == 0x00ffffff)
{
continue;
}*/
*(mptr + ((start_y + y) * 800)+ start_x + x) = tmpbuff[y * width + x];
}
}
//关闭LCD文件
close(bmp_fd);
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 扣取指定区域像素并在lcd上指定起点显示 *
*------------------------------------------------------*
* 参 数: *
* pathname 图片的存放路径 *
* hui_x 指定扣取起点的x轴 *
* hui_y 指定扣取起点的y轴 *
* hui_w 扣取的宽度 *
* hui_h 扣取的高度 *
* start_x 绘画起点的x轴 *
* start_y 绘画起点的y轴 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::specified_cutout_show_bmp(const char* pathname,int hui_x,int hui_y, int hui_w,int hui_h,int start_x,int start_y)
{
int width, high; //图片亮度与高度
int i, j, x, y;
// 读取BMP格式头,获取图片信息
struct bitmap_header header;
struct bitmap_info info;
struct rgb_quad quad;
//打开图片,获取图片描述符
int bmp_fd = open(pathname, O_RDONLY);
if (bmp_fd == -1)
{
return -1;
}
// 第一、二个结构体是必有信息
read(bmp_fd, &header, sizeof(header));
read(bmp_fd, &info, sizeof(info));
//获取打开图片的大小
width = info.width;
high = info.height;
if (width > 800 || high > 480)
{
close(bmp_fd);
return -1;
}
//变长数组
unsigned char bmpbuff[width * high * 3];
unsigned int buff[width * high];
unsigned int tmpbuff[width * high];
read(bmp_fd, bmpbuff, sizeof(bmpbuff));
//图片像素点移动
for (i = 0; i < width * high; i++)
{
buff[i] = bmpbuff[3 * i + 0] | bmpbuff[3 * i + 1] << 8 | bmpbuff[3 * i + 2] << 16;
}
//图片像素点倒置
for (y = 0; y < high; y++)
{
for (x = 0; x < width; x++)
{
tmpbuff[(high - 1 - y) * width + x] = buff[y * width + x];
}
}
//图片像素显示
for (y = 0; y < hui_h; y++)
{
for (x = 0; x < hui_w; x++)
{
//遇到白色就跳过,不绘画,可将0xffffff修改成不需要的颜色
/*if (tmpbuff[(hui_y + y) * 800 + hui_x + x] == 0x00ffffff)
{
continue;
}*/
*(mptr + (start_y+ y) * 800 + start_x+ x) = tmpbuff[(hui_y + y) * 800 + hui_x + x];
}
}
//关闭LCD文件
close(bmp_fd);
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 打开触摸屏并获取点击和松开的坐标 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::open_touch_screen(void)
{
//定义一个结构体变量
struct input_event ts;
//打开触摸屏
touch_screen_fd = open("/dev/input/event0", O_RDWR);
if (touch_screen_fd < 0)
{
return -1;
}
//清空
memset(&ts, 0, sizeof(struct input_event));
while (1)
{
//读取触摸屏
read(touch_screen_fd, &ts, sizeof(struct input_event));
//决断是否为相对坐标类型
if (ts.type == EV_ABS && ts.code == ABS_X)
{
tow_x = ts.value;
}
//决断是否为相对坐标类型
if (ts.type == EV_ABS && ts.code == ABS_Y)
{
tow_y = ts.value;
}
//表示手指按下
if (ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 1)
{
//记录起点坐标
one_x = tow_x;
one_y = tow_y;
}
//表示手指松开
if (ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)
{
//坐标换算 起点坐标
one_x = one_x * (800.0 / 1024.0);
one_y = one_y * (480.0 / 600.0);
//坐标换算 结束坐标
tow_x = tow_x * (800.0 / 1024.0);
tow_y = tow_y * (480.0 / 600.0);
return 0;
}
}
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 关闭触摸屏 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 成功:0 失败:-1 *
*******************************************************/
int Lcd::close_touch_screen(void)
{
int close_touch_screen_fd = close(touch_screen_fd);
if (close_touch_screen_fd < 0)
{
return -1;
}
return 0;
}
/*******************************************************
* 函数介绍 *
*------------------------------------------------------*
* 功能: 进度条 *
*------------------------------------------------------*
* 参 数: *
* 无 *
* 返回值: *
* 无 *
*******************************************************/
void Lcd::progress_bar(void)
{
int x, y;
for (y = 450; y < 465; y++)
{
for (x = 50; x < 750; x++)
{
mptr[y * 800 + x] = 0x007f7f7f;
}
}
for (x = 50; x < 750; x++)
{
for (y = 450; y < 465; y++)
{
mptr[y * 800 + x] = 0x003300FF;
}
usleep(300);
}
}
2.Lcd.h
#pragma once
#include <cstring>
#include <iostream>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/input.h>
using namespace std;
// BMP格式头规范
struct bitmap_header
{
int16_t type;
int32_t size; // 图像文件大小
int16_t reserved1;
int16_t reserved2;
int32_t offbits; // bmp图像数据偏移量
}__attribute__((packed));
struct bitmap_info
{
int32_t size; // 本结构大小
int32_t width; // 图像宽
int32_t height; // 图像高
int16_t planes;
int16_t bit_count; // 色深
int32_t compression;
int32_t size_img; // bmp数据大小,必须是4的整数倍
int32_t X_pel;
int32_t Y_pel;
int32_t clrused;
int32_t clrImportant;
}__attribute__((packed));
struct rgb_quad
{
int8_t blue;
int8_t green;
int8_t red;
int8_t reserved;
}__attribute__((packed));
class Lcd
{
public:
//存放触摸屏坐标
int one_x, one_y, tow_x, tow_y;
//数据初始
Lcd();
//打开lcd
int open_lcd(void);
//申请映射
int apply_for(void);
//关闭lcd
int close_lcd(void);
//销毁映射
void destruction_apply_for(void);
//清屏
void clear(unsigned int color);
//打开触摸屏
int open_touch_screen(void);
//关闭触摸屏
int close_touch_screen(void);
//进度条
void progress_bar(void);
//映射800*480图片
int show_bmp(const char* pathname);
//指定位置映射图片
int specified_show_bmp(const char* pathname, int start_x, int start_y);
//指定位置映射指定扣取的图片
int specified_cutout_show_bmp(const char* pathname, int hui_x, int hui_y, int hui_w, int hui_h, int start_x, int start_y);
~Lcd(){ }
private:
//私有变量
int fd, touch_screen_fd, h, w, pix;
unsigned int* mptr;
};
3.main.cpp
#include "Lcd.h"
int main(void)
{
//定义类变量
Lcd lcd;
//打开lcd和映射
lcd.open_lcd();
lcd.apply_for();
//清屏
lcd.clear(0xEB3324);
sleep(2);
//打开触摸屏并获取坐标
lcd.open_touch_screen();
cout << "按下的坐标:" << lcd.one_x << " " << lcd.one_y << endl;
cout << "松开的坐标:" << lcd.tow_x << " " << lcd.tow_y << endl;
//映射800*480图片
lcd.show_bmp("/root/C++/photo/jiemian.bmp");
sleep(2);
//指定位置映射图片
lcd.specified_show_bmp("/root/C++/photo/10.bmp", 100, 100);
sleep(2);
//指定位置映射指定扣取的图片
lcd.specified_cutout_show_bmp("/root/C++/photo/jiemian.bmp", 100,100,48,48,100, 100);
sleep(2);
//进度条
lcd.show_bmp("/root/C++/photo/jiazai0.bmp");
lcd.progress_bar();
//关闭lcd
lcd.close_lcd();
//销毁映射
lcd.destruction_apply_for();
//关闭触摸屏
lcd.close_touch_screen();
while (1);
return 0;
}
三、开发板的介绍
GEC6818 开发平台,核心板采用 10 层板工艺设计,确保稳定可靠,可以批量用于平板电脑,车机,学 习机,POS 机,游戏机,行业监控等多种领域。该平台搭载三星 Cortex-A53 系列高性能八核处理器 S5P6818, 最高主频高达 1.4GHz,可应用于嵌入式 Linux 和 Android 等操作系统的驱动、应用开发。开发板留有丰富 的外设,支持千兆以太网、板载 LVDS 接口、MIPI 接口、USB 接口等。
GEC6818 开发平台采用的是三星 64 位八核 Cortex-A53 架构的 S5P6818 芯片,下面是芯片主要参数:
型号 | S5P6818 |
上市时间 | 2014 年 |
工艺制程 | 28nm |
CPU 主频 | 1.4G+ |
封装尺寸 | 0.65mm 引脚间距,17*17mm2 513-FCBGA 封装 |
CPU 架构 | Cortex-A53 八核 |
缓存容量 | 32KB*4 I/D 缓存 1MB 二级缓存 |
DDR3 接口 | 单通道 32 位数据总线 高达800MHz 工作频率 |
多媒体解码 | H.263,H.264,MPEG1,MPEG2 MEG4,VC1,VP8,Theora,AVS RV8/9/10,MJPEG(几乎全格式) |
多媒体编码 | H.263,H.264 MPEG4,MJPEG |
显示接口 | RGB,MIPI,LVDS |
最大显示分辨率 | 2048*1280 |
以太网接口 | 集成千兆以太网控制器 |
GPIO 电平 | 3.3V |
ADC | 8 路 12 bit 0~1.8V |
USB 接口 | 1 路 HOST 1 路 HSIC 1 路 OTG |
芯片 ID | 支持 128BIT 唯一 ID 号 |
- 常用接口说明
1.电源接口
开发平台总电源接口为 CN1,对应的电源适配器的输出电压为直流5V。
2.调试串口
开发平台默认使用 UART0 作为调试串口,UART0 为标准 DB9 接口。你可以通过附带的交叉串口线和 PC 进行通讯。
3.USB-OTG接口
该接口用于程序烧写,同步等。它还能通过 OTG 线实现 HOST 的功能。
4.以太网接口
开发平台支持千兆有线以太网接口,板载RTL8211E
5.音频接口
一个 3.5mm 音频输入接口(红色),一个 3.5mm 输出接口(绿色),可直接接耳机,用于音频的播放和录制。
6.LCD接口
开发平台底板默认留有一个 40PIN 的 LCD 接口(底板背部位置),通过软排线将 RGB 相关信号连接 到 LCD 控制板上,进而控制 LCD 和显示。