<p>第6天笔记</p>
讯享网
GEC6818图⽚显⽰
如何将资源拷⻉⾄GEC6818
将⽂件拷⻉⾄U盘
将U盘插⼊GEC6818对应的USB接⼝
在开发板(SecureCRT)执⾏命令,检测U盘
如果是NTFS格式的U盘,就需要⼿动挂载,挂载命令如下:
使⽤cp命令,将udisk下的⽂件或者⽂件夹拷⻉到开发版,(因为udisk只是将u盘和开发板建⽴了映射,⽂
件依然是在u盘)
ARM开发板图⽚显⽰原理
回顾:
- 之前我们是做过⼀个练习,把a.txt⽂件⾥⾯的数据,通过⽂件IO的⽅式,复制到了b.txt。
- 之前也实现了在LCD屏幕绘制颜⾊。
首先需要准备一张800∗480的图片,用作测试。
第1步:打开fb0⽂件(只写⽅式),打开图⽚⽂件(读写⽅式),函数open()
第2步:将图⽚⽂件⾥⾯的像素点读取出来,放到缓冲区(800∗480∗3),函数read()
第3步:将缓冲区⾥⾯的像素点,写进fb0⽂件⾥,函数write()
第4步:关闭所有打开的⽂件,函数close()
/*
> File Name: demo01.c
> Author: fpf
> Description: 向LCD屏幕写入图片(原始,对数据不做任何处理)
> Created Time: 2024年10月12日 星期六 10时32分50秒
/
#include <stdio.h>
// 文件IO操作相关的四个库文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
// 打开LCD屏幕(写进去)
int lcd = open(“/dev/fb0”,O_RDWR);
// 打开BMP图片(读出来)
分析:
- 图⽚只占了屏幕的四分之三,剩余四分之⼀是未完成填充的。
- 图⽚在LCD屏幕上的颜⾊颜⾊显⽰失真。
- 图⽚在LCD屏幕上的显⽰是倒的。
整体的结论是:图⽚显⽰不OK
int bmp = open(“https://blog.csdn.net/2403_/article/details/picture/home_bg.bmp",O_RDWR);
// 创建缓冲区,
int buf[800 * 480];
// 存放读取到的图片数据
int ret = read(bmp,buf,800 * 480 * 3); // BMP图片 1像素 = 3字节(GBR)
// 将缓冲区的图片数据写入到LCD屏
ret = write(lcd,buf,800 * 480 * 4); // LCD屏幕 1像素 = 4字节(ARGB)
// 关闭BMP图片
close(bmp);
// 关闭LCD屏幕
close(lcd);
return 0;
}
1. 只显示四分之三的问题
分析:
RGB:是由RGB三种色值构成,也就是1像素=3字节,也就是800*480的图片拥有的字节数为:
LCD:是由ARGB四种色值构成,也就是1像素=4字节,也就是800*480的屏幕拥有的字节数为:
也就是RGB只能占满LCD屏幕的四分之三。
800 * 480 * 3 = 字节
800 * 480 * 4 = 字节
// 将一个BMP图片的像素点,对齐一个LCD屏幕的像素点
// 做法是再定义一个数组,来进行像素点的改造
int argb[800 * 480]; // 1个argb 对应一个lcd屏幕的像素点
char rgb[800 * 480 *3]; // 三个rgb 组成一个BMP图片的像素点
2. 图片色调问题
解决方法:
注意:
- LCD:像素点中字节排列顺序:ARGB
- BMP:像素点中字节排列顺序:(A)GBR
处理BMP:
A补充的,位置不做调整
B位置不动
G向左移动⼀个字节,也就是8位 G << 8
R向左移动⼆个字节,也就是16位 R << 16
3. 图片上下颠倒的问题
总结:
- 原本BMP第⼀⾏的像素点,需要刷到LCD最后⼀⾏
- 原本BMP左上⻆的像素点刷到LCD左下⻆,BMP右上⻆的像素点刷到LCD右下⻆。
小贴士:
BMP图⽚的像素点的存放特点:
- 以BGR的形式进⾏存储
- 从下⽹上,从左往右存储
修正后的代码:
// LCD屏幕显示BMP图片
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
// 入口函数
int main(int argc, char const *argv[])
{
// 创建一个缓冲区,存储从BMP文件中读取到的原始的图像信息(BGR,24位),这里面的图片数据已
经去掉了54个字节的信息域
char bmp_buf[800 * 480 * 3];
// 创建一个缓冲区,存放BMP从24位转换位32位的数据
int lcd_buf[800 * 480];
// 创建一个缓冲区,存放翻转后的BMP数据
int show_buf[800 * 480];
// 打开LCD屏幕
int lcd = open(”/dev/fb0“, O_RDWR);
// 判断屏幕是否打开成功
if (lcd == -1)
{
printf(”LCD屏幕打开失败! “);
return -1;
}
// 打开本地BMP图片
int bmp = open(”https://blog.csdn.net/2403_/article/details/picture/home_bg.bmp", O_RDWR);
// 判断BMP是否打开成功
if (bmp == -1)
{
printf(“BMP图片打开失败! ”);
return -1;
}
// 因为BMP图片的前54个字节是信息域,不是RGB,所以我们要跳过,从BMP的第55个字节开始读取
// 从BMP文件的开头位置偏移54个字节,这样我们读取到就是BGR数据
lseek(bmp, 54, SEEK_SET);
// 从BMP文件中读取图像数据
// 这里为什么是:800 * 480 * 3 因为我们现在读的是BMP图片,BMP是由GBR构成,每一种色值就是
一个字节,那么就是3个字节
int ret = read(bmp, bmp_buf, 800 * 480 * 3);
if (ret == -1)
{
printf(“BMP图片读取失败! ”);
return -1;
}
// 关闭BMP
close(bmp);
// 将24位的BMP转换位32位
// 定义循环变量
int i; // 通过i获取到每一个像素
int j; // 通过j获取到每一个像素对应的字节
for (i = 0, j = 0; i < 800 * 480; i++, j += 3)
{
// BMP是由ABGR构成
// LCD是由ARGB构成
// BMP B << 0
// BMP G << 8
// BMP R << 16
lcd_buf[i] = (bmp_buf[j] << 0) | (bmp_buf[j + 1] << 8) | (bmp_buf[j + 2] <<
16);
}
// 翻转图片
// 原因:开发板中本身存储的图片的倒的,我们显示的时候,需要水平翻转180°
// 解决:将BMP的第一行写到LCD屏幕的最后一行,将BMP的第二行写到LCD屏幕的倒数第二行,以此类
推,直到写完
// 定义循环变量
int x; // 控制列
int y; // 控制行
// 第一层循环,获取每一行
for (y = 0; y < 480; y++)
{
// 第二层循环,获取每一列
for (x = 0; x < 800; x++)
{
// 翻转
// 翻转的公式:800 * (479 - y) + x
show_buf[800 * (479 - y) + x] = lcd_buf[800 * y + x];
}
}
// 将最终处理后的BMP写入到LCD
ret = write(lcd, show_buf, 800 * 480 * 4);
if (ret == -1)
{
printf(“LCD屏幕数据写入失败! ”);
return -1;
}
图⽚显⽰优化:噪点分析与解决⽅法
- 现象:LCD使⽤write函数直接写⼊像素点出现噪点,等待⼀会后能完全消失。
- 问题分析:由于系统调⽤需要花费时间。⽤write函数写的时候,需要内核去调⽤写函数,⽽内核调⽤需要⼀定的时间,但是开发板的执⾏速度⽐较快,所以,在调⽤的过程中已经显⽰上去了,但是整个调度过程中,数据有⼀部分还在内核中,没有显⽰出来,形成了堵塞)。
- 解决办法:给LCD申请⼀⽚显存
- ⽅法:使⽤mmap函数采⽤内存映射的⽅式来为LCD映射⼀块特殊的内存作为LCD的显存。通俗来讲,就是在运⾏内存⾥映射⼀块空间。这块空间与fb0相关联起来。之后你直接对这块空间进⾏像素点的印刷,fb0也就会有相应的像素点刷到LCD上;
- 内存映射和解除内存映射
// 关闭lcd
close(lcd);
return 0;
}
mmap函数
说明:
映射
库引⽤:
#include <sys/mman.h>
函数原型:
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
主要参数:
addr->映射内存的起始地址,NULL(表⽰由内核⾃动寻找符合要求的内存地址)
length-> 映射内存的⼤⼩
prot->映射内存的操作权限(与open的权限⼀致)
PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.
flags->映射内存更新⽅式
MAP_SHARED共享,更新已有的内存
MAP_PRIVATE私有,创建新的内存并更新
fd->需要映射的⽂件描述符
offset->映射内存的偏移量
返回值:成功返回映射内存的基地址 失败返回MAP_FAILED和错误码
举例:
munmap函数
int *fd_map = NULL;
fd_map = mmap(NULL,8004804,PROT_READ | PROT_WRITE,MAP_SHARED,fd_lcd,0);
if(fd_map == NULL)
{
perror(“mmap”);
return -1;
}
说明:
解除映射
函数原型:
int munmap(void ∗𝑎𝑑𝑑𝑟, size_t length);
主要参数:
参数1:映射内存的起始地址
参数2:解除映射的内存的⼤⼩
返回值:
成功:0,失败:-1
举例:
如何使用mmap函数
munmap(fd_map,800 * 480 * 4);
// LCD屏幕显示BMP图片
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
// 内存映射相关库
#include <sys/mman.h>
#include <string.h>
// 入口函数
int main(int argc, char const *argv[])
{
// 创建一个缓冲区,存储从BMP文件中读取到的原始的图像信息(BGR,24位),这里面的图片数据已
经去掉了54个字节的信息域
char bmp_buf[800 * 480 * 3];
// 创建一个缓冲区,存放BMP从24位转换位32位的数据
int lcd_buf[800 * 480];
// 清空缓冲区
bzero(bmp_buf,sizeof(bmp_buf));
bzero(lcd_buf,sizeof(lcd_buf));
// 打开LCD屏幕
int lcd = open(“/dev/fb0”, O_RDWR);
// 判断屏幕是否打开成功
if (lcd == -1)
{
printf(“LCD屏幕打开失败! ”);
return -1;
}
// 打开本地BMP图片
int bmp = open(“https://blog.csdn.net/2403_/article/details/picture/bg01.bmp", O_RDWR);
// 判断BMP是否打开成功
if (bmp == -1)
{
printf(”BMP图片打开失败! “);
return -1;
}
// 因为BMP图片的前54个字节是信息域,不是RGB,所以我们要跳过,从BMP的第55个字节开始读取
// 从BMP文件的开头位置偏移54个字节,这样我们读取到就是BGR数据
lseek(bmp, 54, SEEK_SET);
// 从BMP文件中读取图像数据
// 这里为什么是:800 * 480 * 3 因为我们现在读的是BMP图片,BMP是由GBR构成,每一种色值就是
一个字节,那么就是3个字节
int ret = read(bmp, bmp_buf, 800 * 480 * 3);
if (ret == -1)
{
printf(”BMP图片读取失败! “);
return -1;
}
// 关闭BMP
close(bmp);
// 内存映射,将一块内存和fb0进行映射
int *fd_mmap = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd,
0);
// 将24位的BMP转换位32位
// 定义循环变量
int i; // 通过i获取到每一个像素
int j; // 通过j获取到每一个像素对应的字节
for (i = 0, j = 0; i < 800 * 480; i++, j += 3)
{
// BMP是由ABGR构成
// LCD是由ARGB构成
// BMP B << 0
// BMP G << 8
准备”64*64“的按钮图片
免费图标下载:
阿⾥巴巴⽮量图标库:iconfont-阿里巴巴矢量图标库
将这个图片烧写进开发板对应的位置(picture)。
// BMP R << 16
lcd_buf[i] = (bmp_buf[j] << 0) | (bmp_buf[j + 1] << 8) | (bmp_buf[j + 2] <<
16);
}
// 翻转图片
// 原因:开发板中本身存储的图片的倒的,我们显示的时候,需要水平翻转180°
// 解决:将BMP的第一行写到LCD屏幕的最后一行,将BMP的第二行写到LCD屏幕的倒数第二行,以此类
推,直到写完
// 定义循环变量
int x; // 控制列
int y; // 控制行
// 第一层循环,获取每一行
for (y = 0; y < 480; y++)
{
// 第二层循环,获取每一列
for (x = 0; x < 800; x++)
{
// 翻转
// 翻转的公式:800 * (479 - y) + x
*(fd_mmap + 800 * (479 - y) + x) = lcd_buf[800 * y + x];
}
}
// 解除内容映射
munmap(fd_mmap, 800 * 480 * 4); // 解除屏幕映射的字节数,所以 * 4
// 关闭lcd
close(lcd);
return 0;
}
在”show_bmp.h“添加函数声明
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
// 自定义MBP头信息
struct bmp_header
{
uint16_t type;
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offbits;
}attribute((packed));
// 自定义BMP数据信息
struct bmp_info
{
uint32_t size;
uint32_t width;
uint32_t height;
uint16_t planes;
uint16_t bitcount;
uint32_t compression;
uint32_t size_image;
uint32_t x_pel;
uint32_t y_pel;
uint32_t clr_used;
uint32_t clr_Important;
}attribute((packed));
// 存储lcd屏幕
static int lcd;
// 映射指针
static int lcd_buf;
在“show_bmp.c”,添加相关函数
static int lcd_init();
/
* 功能:LCD屏幕任意位置任意大小的图片绘制
* 形参:
* char picture:要显示图片的名字,包括路径
int x 图片左上角这一点居于lcd屏幕的X坐标
int y 图片左上角这一点居于lcd屏幕的Y坐标
/
extern int showbmp(const char* picture,int x,int y);
#include ”show_bmp.h“
/*
初始化LCD屏幕
*/
static int lcd_init()
{
// 打开lcd屏幕
lcd = open(”/dev/fb0“, O_RDWR);
// 判断打开是否失败
if (lcd == -1)
{
perror(”LCD屏幕打开失败!“);
return -1;
}
// 映射屏幕
lcd_buf = (int *)mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd,
0);
// 判断是否映射失败
if (lcd_buf == MAP_FAILED)
{
perror(”内存映射失败!“);
return -1;
}
}
/
功能:LCD屏幕任意位置任意大小的图片绘制
- 形参:
* char picture:要显示图片的名字,包括路径
int x 图片左上角这一点居于lcd屏幕的X坐标
int y 图片左上角这一点居于lcd屏幕的Y坐标
/
int showbmp(const char *picture, int x, int y)
{
// 映射屏幕
lcd_init();
if (lcd_buf == MAP_FAILED)
{
perror(”mmap failed“);
exit(0);
}
// 1. 打开图片
int bmpfd = open(picture, O_RDONLY);
if (bmpfd == -1)
{
perror(”open bmp“);
munmap(lcd_buf, 800 * 480 * 4);
return -1;
}
// 2. 读取图片的信息,
struct bmp_header header = {0};
read(bmpfd, &header, sizeof(header));
struct bmp_info info = {0};
read(bmpfd, &info, sizeof(info));
// 3.读取图片的实际色彩数据
int rgb_size = header.size - header.offbits;
char *rgb = calloc(1, rgb_size);
char *pimg = rgb;
read(bmpfd, rgb, rgb_size);
int pad = (4 - (info.width * 3) % 4) % 4; // 计算每一行的无效字节数
rgb += (info.width * 3 + pad) * (info.height - 1); // 让rgb指向最末行的起始位置
lcd_buf += (x + 800 * y);
int i, j;
for (j = 0; j < info.height; j++)
{
for (i = 0; i < info.width; i++)
{
int lcd_offset = (i + 800 * j);
int rgb_offset = 3 * i - (info.width * 3 + pad) * j;
memcpy(lcd_buf + lcd_offset, rgb + rgb_offset, 3);
}
}
close(bmpfd);
free(pimg);
带有main函数的“main_show_bmp.c”内容
编译
// 关闭lcd
close(lcd);
// 解除映射
munmap(lcd_buf, 800 * 480 * 4);
return 0;
}
// 引入 show_bmp.h
#include ”show_bmp.h“
int main(int argc, char const *argv[])
{
showbmp(”https://blog.csdn.net/2403_/article/details/picture/home_bg.bmp", 0, 0); // 背景图
showbmp(“https://blog.csdn.net/2403_/article/details/picture/mp3_off.bmp", 463, 395); // 音频播放
showbmp(”https://blog.csdn.net/2403_/article/details/picture/mp4_off.bmp", 547, 395); // 视频播放
showbmp(“https://blog.csdn.net/2403_/article/details/picture/photo_off.bmp", 631, 395); // 电子相册
showbmp(”https://blog.csdn.net/2403_/article/details/picture/piano_off.bmp", 715, 395); // 小钢琴
return 0;
}
arm-linux-gcc show_bmp.c main_show_bmp.c -o home
执行结果
GEC6818触摸屏
触作摸屏操作
对于触摸屏而言,该设备会产生三种数据:
X轴坐标值
Y轴坐标值
P压⼒值
理论上来说,从手指放上屏幕开始,到滑动一段距离,离开屏幕结束,会产生如下所示的一系列数据:
有如下地方需要注意:
在刚开始的第⼀个坐标值和最后⼀个坐标值中,都连带会读到压⼒值P
P1是⼿指刚落下时,产⽣压⼒值⼤于0的数据
P2是⼿指离开时,产⽣压⼒值等于0的数据
(X Y P1) SYN (X Y) SYN (X Y) SYN (X Y) … … (X Y) SYN (X Y P2)
应⽤层并不能保证能严格交替读取 (X,Y) 坐标值,它们会由于异步等原因出现断续,⽐如 (X X X X Y)
若⼿指滑动的⽅向刚好垂直与坐标轴,会导致其中⼀个维度的坐标值不变,那么也可能会导致只出现⼀个
维度坐标值的情形,例如:
这种情况下需要借助系统⾃动产⽣的 SYN 事件来整理出成对的坐标值。
触摸屏相关函数代码
不同坐标系值的获取
大家使用GEC6818开发版的时候,需要注意的是,本次实训使用的板子拥有两套坐标系:
⿊⾊底纹板⼦(紧贴屏幕的底板颜⾊为⿊⾊)
坐标系采⽤1024∗600,由于板⼦的分辨率是800∗480,所以需要对获取到的坐标进⾏转换,转换关系如
下:
获取的坐标值获取的坐标值获取的坐标值:
获取的 坐标值
获取的坐标值获取的坐标值获取的坐标值:
获取的 坐标值
蓝⾊底纹板⼦(紧贴屏幕的底板颜⾊为蓝⾊)
坐标系采⽤800∗480,由于板⼦的分辨率是800∗480,所以不需要对获取到的坐标进⾏转换,直接获取即可。
触摸屏滑屏实现
图⽰:
… (X) SYN (X) SYN (X Y) SYN (Y) … … (X Y) SYN …
思路:
滑屏功能是在屏幕上的⼀个点移动到另外⼀个点,计算出之间的距离,当此距离达到⼀定的程度,则判断
为滑动。 如果没有超过⼀定的距离,则归类为单击屏幕。
// 触摸屏划屏函数
#include <stdio.h> // usr/include/stdio.h
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/输入子系统头文件/
#include <linux/input.h> // usr/include/linux/input.h
int main(int argc,char argv)
{
/打开触摸屏/
int fd;
fd = open(“/dev/input/event0”,O_RDWR);
if(fd < 0)
{
perror(“open ts fail”);
return -1;
}
/操作触摸屏/
// 定义一个存储触摸屏信息的结构体
struct input_event ts;
int x1=0,y1=0; // 按下去的坐标值
int x2=0,y2=0; // 松手后的坐标值
while(1)// 循环读取数据
{
/抓取按下去的坐标值/
while(1)
{
// 在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
read(fd,&ts,sizeof(struct input_event));
if(ts.type == EV_ABS && ts.code==ABS_X) // x轴的坐标值
{
// x1 = ts.value; // 蓝色底纹触摸屏的坐标值
x1 = ts.value * 800 / 1024; // 黑色底纹触摸屏的坐标值
printf(“x=%d ”,x1);
}
if(ts.type == EV_ABS && ts.code==ABS_Y) // y轴的坐标值
{
// y1 = ts.value; // 蓝色底纹触摸屏的坐标值
y1 = ts.value * 480 / 600; // 黑色底纹触摸屏的坐标值
printf(“y=%d ”,y1);
}
// 当按下去的那一刻,跳出循环;只抓取按下去的坐标值
if(ts.type == EV_KEY && ts.code==BTN_TOUCH && ts.value == 1)//
{
printf(“按下去:x1=%d y1=%d ”,x1,y1);
break;
}
}
/抓取松手后的坐标值/
while(1)
{
// 在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
read(fd,&ts,sizeof(struct input_event));
if(ts.type == EV_ABS && ts.code==ABS_X) // x轴的坐标值
{
// x2 = ts.value; // 蓝色底纹触摸屏的坐标值
x2 = ts.value * 800 / 1024; // 黑色底纹触摸屏的坐标值
printf(“x=%d ”,x2);
}
if(ts.type == EV_ABS && ts.code==ABS_Y) // y轴的坐标值
{
// y2 = ts.value; // 蓝色底纹触摸屏的坐标值
y2 = ts.value * 480 / 600; // 黑色底纹触摸屏的坐标值
printf(“y=%d ”,y2);
}
// 当按下去的那一刻,跳出循环,只抓取松手后的坐标值
if(ts.type == EV_KEY && ts.code==BTN_TOUCH && ts.value == 0)
{
printf(“松手:x2=%d y2=%d ”,x2,y2);
break;
}
}
// 用来做方向判定,阈值(50)由自己设置
if(x2-x1 > 50) // 50差值决定你滑动的灵敏度
printf(“right ”);
触摸屏点击实现
if(x2-x1 < -50)
printf(“left ”);
if(y2-y1 > 50)
printf(“down ”);
if(y2-y1 < -50)
printf(“up ”);
}
/关闭触摸屏/
close(fd);
return 0;
}
// 触摸屏单击函数
#include <stdio.h> // usr/include/stdio.h
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/输入子系统头文件/
#include <linux/input.h> // 位于usr/include/linux/input.h
int main(int argc,char argv)
{
/打开触摸屏/
int fd;
fd = open(“/dev/input/event0”,O_RDWR);
if(fd < 0)
{
perror(“open ts fail”);
return -1;
}
// 操作触摸屏
// 定义一个存储触摸屏信息的结构体
struct input_event ts;
int x1=0,y1=0; // 点击的坐标值
// 读取触摸屏的设备文件
while(1)
{
// 在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
read(fd,&ts,sizeof(struct input_event));
if(ts.type == EV_ABS && ts.code==ABS_X) // x轴的坐标值
给图⽚事件绑定和回弹处理
在main_show_bmp.c中新增触摸屏代码,并给按钮绑定点击事件
main_show_bmp.c
{
// x1 = ts.value; // 蓝色底纹触摸屏的坐标值
x1 = ts.value * 800 /1024; // 黑色底纹触摸屏的坐标值
printf(“x=%d ”,x1);
}
if(ts.type == EV_ABS && ts.code==ABS_Y) // y轴的坐标值
{
// y1 = ts.value; // 蓝色底纹触摸屏的坐标值
y1 = ts.value * 480 / 600; // 黑色底纹触摸屏的坐标值
printf(“y=%d ”,y1);
}
}
// 关闭触摸屏
close(fd);
return 0;
}
// 引入 show_bmp.h
#include “show_bmp.h”
/输入子系统头文件/
#include <linux/input.h> // 位于usr/include/linux/input.h
/
* 初始化图片显示
*/
void init_bmp()
{
// 显示图片
showbmp(“https://blog.csdn.net/2403_/article/details/picture/home_bg.bmp", 0, 0); // 背景图
showbmp(”https://blog.csdn.net/2403_/article/details/picture/mp3_off.bmp", 463, 395); // 音频播放
showbmp(“https://blog.csdn.net/2403_/article/details/picture/mp4_off.bmp", 547, 395); // 视频播放
showbmp(”https://blog.csdn.net/2403_/article/details/picture/photo_off.bmp", 631, 395); // 电子相册
showbmp(“https://blog.csdn.net/2403_/article/details/picture/piano_off.bmp", 715, 395); // 小钢琴
}
/*
初始化触摸屏
*/
int init_ts()
{
/打开触摸屏/
int fd;
fd = open(”/dev/input/event0“, O_RDWR);
if (fd < 0)
{
perror(”open ts fail“);
return -1;
}
/操作触摸屏/
// 定义一个存储触摸屏信息的结构体
struct input_event ts;
int x1 = 0, y1 = 0; // 点击的坐标值
long stime;
// 读取触摸屏的设备文件
while (1)
{
// 在这个地方read这条语句是阻塞(根本原因此处的fd带有阻塞属性)
read(fd, &ts, sizeof(struct input_event));
if (ts.type == EV_ABS && ts.code == ABS_X) // x轴的坐标值
{
// x1 = ts.value; // 蓝色底纹触摸屏的坐标值
x1 = ts.value * 800 / 1024; // 黑色底纹触摸屏的坐标值
// printf(”x=%d “, x1);
}
if (ts.type == EV_ABS && ts.code == ABS_Y) // y轴的坐标值
{
// y1 = ts.value; // 蓝色底纹触摸屏的坐标值
y1 = ts.value * 480 / 600; // 黑色底纹触摸屏的坐标值
// printf(”y=%d “, y1);
}
// 点击事件
stime = ; // 按键回弹时间
if (ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 1)
{
// printf(”按下去:x1=%d y1=%d “, x1, y1);
if (x1 < 463 + 64 && x1 > 463 && y1 < 395 + 64 && y1 > 395)
{
printf(”音频播放! “);
// 点击后图片切换
showbmp(”https://blog.csdn.net/2403_/article/details/picture/mp3_on.bmp", 463, 395); // 音频播放
// 回复按键
usleep(stime);
showbmp(“https://blog.csdn.net/2403_/article/details/picture/mp3_off.bmp", 463, 395); // 音频播放
}
else if (x1 < 547 + 64 && x1 > 547 && y1 < 395 + 64 && y1 > 395)
{
printf(”视频播放! “);
// 点击后图片切换
showbmp(”https://blog.csdn.net/2403_/article/details/picture/mp4_on.bmp", 547, 395); // 音频播放
// 回复按键
usleep(stime);
showbmp(“https://blog.csdn.net/2403_/article/details/picture/mp4_off.bmp", 547, 395); // 音频播放
}
else if (x1 < 631 + 64 && x1 > 631 && y1 < 395 + 64 && y1 > 395)
{
printf(”电子相册! “);
// 点击后图片切换
showbmp(”https://blog.csdn.net/2403_/article/details/picture/photo_on.bmp", 631, 395); // 电子相册
// 回复按键
usleep(stime);
showbmp(“https://blog.csdn.net/2403_/article/details/picture/photo_off.bmp", 631, 395); // 电子相册
}
else if (x1 < 715 + 64 && x1 > 715 && y1 < 395 + 64 && y1 > 395)
{
printf(”小钢琴! “);
// 点击后图片切换
showbmp(”https://blog.csdn.net/2403_/article/details/picture/piano_on.bmp", 715, 395); // 小钢琴
// 回复按键
usleep(stime);
showbmp(“https://blog.csdn.net/2403_/article/details/picture/piano_off.bmp", 715, 395); // 小钢琴
}
}
}
/关闭触摸屏/
close(fd);
return 0;
}
int main(int argc, char const *argv[])
{
init_bmp();
init_ts();
return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/190322.html