这个程序实现了一个实现简易的相册,使用6818开发板的液晶屏和触摸屏,可以显示多张BMP格式的图片,并支持通过触摸屏的操作切换图片。
程序的主要功能和流程如下:
打开液晶屏设备文件,并将液晶屏映射到内存:通过打开/dev/fb0
设备文件,并使用mmap
函数将液晶屏映射到内存,以便后续在屏幕上显示图片。
打开触摸屏设备文件:通过打开/dev/input/event0
设备文件,实现对触摸屏输入事件的捕获和处理。
获取图片路径名字:通过get_bmpname
函数获取指定目录下的所有BMP格式图片的路径名字,并存储在数组bmppath
中。
显示第一张图片:程序默认显示第一张图片,使用show_bmp
函数将图片显示在液晶屏上。
循环监听触摸事件:进入无限循环,程序不断监听触摸屏的输入事件。根据触摸坐标判断用户点击了屏幕的哪个区域。
切换图片:根据触摸坐标的位置,如果用户点击了右上角区域,则切换到上一张图片;如果点击了右下角区域,则切换到下一张图片。通过更新bmppath
数组的索引 i
来实现图片的切换,并调用show_bmp
函数将新的图片显示在液晶屏上。
主函数代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LCDDEV "/dev/fb0"
#define PATH_SIZE 1024
#define PHOTO_SIZE 100
#define TOUCH_DEV "/dev/input/event0" // 触摸屏设备文件路径
void get_xy(int touch_fd,int *x,int *y)
{
struct input_event buf;
*x = -1;
*y = -1;
while (1)
{
// 读取触摸事件
int ret = read(touch_fd, &buf, sizeof(buf));
if (ret == -1){
perror("read fail");
exit(errno);
}
// 判断事件类型是否是触摸事件
if (buf.type == EV_ABS)
{
// 根据事件类型设置对应的坐标值
if (buf.code == ABS_X){
*x = (buf.value * 800) / 1024;
}
if (buf.code == ABS_Y){
*y = (buf.value * 800) / 1024;
}
}
if (!(*x > 0 && *x < 800 && *y > 0 && *y < 480)){
continue;
}
if(*x>-1 && *y>-1){
break; // 得到坐标后退出
}
}
}
// 从目录中读取BMP类型图片路径名字
void get_bmpname(char *dir, char *bmppath[])
{
char *cur_path = calloc(PATH_SIZE, sizeof(char)); //程序执行的位置
char *dst_path = calloc(PATH_SIZE, sizeof(char)); //指定要读取文件的路径
if( !(cur_path && dst_path) )
{
perror("calloc fail");
exit(errno);
}
// 保留程序执行的位置
getcwd(cur_path, PATH_SIZE);
// 获取指定目录的绝对路径
chdir(dir);
getcwd(dst_path, PATH_SIZE);
// 1.打开目录文件
DIR *dp = opendir(dir);
if ( dp == NULL )
{
perror("opendir fail");
exit(errno);
}
// 2. 读取目录项
int i = 0;
struct dirent *ep = NULL;
while(1)
{
ep = readdir(dp);
if ( ep == NULL && errno == 0 ) //成功读完所有的目录项
{
break;
}
else if( ep == NULL ) //进入到这个判断,说明errno值已被改变,出现某种错误
{
perror("readdir fail");
}
if ( strstr(ep->d_name, ".bmp") )
{
if(bmppath[i] == NULL)
bmppath[i] = calloc(PATH_SIZE, sizeof(char));
else
bzero(bmppath[i], PATH_SIZE);
snprintf(bmppath[i], PATH_SIZE, "%s/%s", dst_path, ep->d_name);
i++;
}
else
{
continue;
}
}
// 继续向后检索,是否为NULL,不为空这次读取的图片资源没有上次多
// 应该把多余申请的资源释放掉
for(; bmppath[i] != NULL; i++)
{
free(bmppath[i]);
bmppath[i] = NULL;
}
// 关闭目录
closedir(dp);
}
int main(int argc, char *argv[])
{
int x,y;
// 打开液晶屏设备
int lcd_fd = open(LCDDEV, O_RDWR);
if(lcd_fd == -1)
{
perror("open lcd fail");
exit(errno);
}
// 给液晶屏文件映射一块内存
int *fb = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
if(fb == MAP_FAILED)
{
perror("mmap fail");
exit(errno);
}
// 打开触摸屏
int touch_fd = open(TOUCH_DEV, O_RDONLY);
if (touch_fd < 0){
perror("打开触摸屏失败");
exit(errno);
}
// 获取指定目录的图片路径名字
char *bmppath[PHOTO_SIZE] = {NULL};
int i = 0;
get_bmpname("./", bmppath);
for (i=0; bmppath[i] != NULL; i++) //获取读到多少张图片路径
/* empty */;
//默认显示第一张图片
show_bmp(bmppath[0], fb, 0, 0);
while(1)
{
get_xy(touch_fd, &x, &y);
if(x>400 && x<800 && y>0 && y<240){ //右上角的那块区域
{
--i;
if (i < 0){
i = 5;
}
show_bmp(bmppath[i], fb, 0, 0);
}
}
else if(x>400 && x<800 && y>240 && y<480){ //右下角的那块区域
++i;
if (i > 5) {
i = 0; // 如果i小于0,跳转至6
}
show_bmp(bmppath[i], fb, 0, 0);
}
}
// 关闭触摸屏
close(touch_fd);
// 关闭液晶屏
munmap(fb, 800*480*4);
close(lcd_fd);
return 0;
}
全部的文件打包放这了。
模拟相册https://download.csdn.net/download/qq_64928278/88136955?spm=1001.2014.3001.5501
更多C语言和Linux系统相关文章,关注专栏:
手撕C语言
玩转linux
一键三连喔
~