粤嵌GEC6818-学习笔记2-屏幕相关及音频播放
这里写目录标题
- LCD屏幕
- 简介
- 操作:打开屏幕
- 映射
- 如何让plcd指向屏幕首地址!
- BMP图片的解析
- 把一张BMP格式的图片显示在我们的开发板上
- 触摸板的相关操作
- 练习:获取屏幕坐标
- 线程进程
- 练习:创建广告播放的一个线程
- 音频播放
- 播放的方式!!
- 相关
LCD屏幕
简介
- 屏幕的分辨率是:800480,即屏幕是由800480个像素点组成的。
- 像素点:可以组成颜色的点!
- 每个像素点占32bit,由A R G B组成,各占8各bit
像素点 | A(透明度) | R(red) | G(green) | B(blue) |
---|---|---|---|---|
color | 00 | ff | 00 | 00 |
unsigned int color = 0x00ff0000;
- 这种模式使得我们可以把颜色数量化 。
操作:打开屏幕
- 屏幕的路径:“/dev/fb0”
int lcd_fd;
lcd_fd = open("/dev/fb0",O_RDWR);
if(lcd_fd == -1)
{printf("open error\n");return -1;
}
映射
- 帧缓冲设备是linux为显存设备提供一个接口,把显存抽象后的一种设备!他允许上次应用程序在图像模式下直接对显示缓冲区进行读写!
int *plcd; //假设这个指针是指向lcd屏幕的首地址!*plcd = 0x00ff0000; //给第一个像素点写入红色
*(plcd+1) = 0x00ff0000 ; //这是给lcd屏幕第二个像素点写入红色for(int y = 0 ; y < 480 ; y++)
{for(int x = 0 ; x < 800 ; x++){*(plcd + y * 800 + x) = 0x00ff0000; // color}
}
//写一个画点的封装函数!
void Lcd_Draw_point(int x , int y , int color)
{if(x<800&&x>=0&&y<480&&y>=0){*(plcd + y * 800 + x) = color;}
}
如何让plcd指向屏幕首地址!
- mmap
NAMEmmap, munmap - map or unmap files or devices into memory映射 ,把屏幕的首地址,镜像给我们!!
SYNOPSIS#include <sys/mman.h>头文件void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);void *addr : NULL 它是由系统分配size_t length :映射的文件的大小 480*800*4int prot : 权限 PROT_READ : 可读PROT_WRITE : 可写PROT_EXEC : 可执行PROT_READ | PROT_WRITE | PROT_EXEC int flags : 属性 MAP_SHAREDint fd : 文件描述符off_t offset : 偏移量 , 0
返回值:
- 失败返回NULL
- 成功的话就返回该屏幕映射过来的首地址!
例子:
int *plcd = mmap(NULL , 480*800*4 , PROT_READ | PROT_WRITE | PROT_EXEC , MAP_SHARED , lcd_fd , 0);int munmap(void *addr, size_t length);void *addr : plcd 是我们映射lcd屏幕过来的首地址size_t length :480*800*4
BMP图片的解析
把一张BMP格式的图片显示在我们的开发板上
- 打开图片
int bmp_fd ;
bmp_fd = open("./1.bmp",O_RDWR);
if(bmp_fd == -1)
{printf("open bmp error\n");return -1;
}
- 图片的类型:bmp,jpg,png
- bmp 图片是一种最原始的,也是windows下面最常见一种图片,也是最基础的图片。它是没有经过任何算法处理的,或者说是没有经过任何算法压缩的,所以它bmp图片所占的内存是最大的!!!
- 没有 压缩 的图片 :意味着它保存每个像素点的值!
BITMAP头:0x00 2字节 保存BMDIB:0x12 4字节 表示是位图的宽度位图的宽度:每一行有多少个像素点!
int width;lseek(bmp_fd,0x12,SEEK_SET);int r = read(bmp_fd,&width,4);if(r == -1){printf("read error\n");return -1;}printf("width == %d\n", width);
width > 0 :它的像素点的保存顺序就是从左边到右边< 0 :则反之0x16 4字节 表示是位图的高度位图的高度:每一列有多少个像素点!high > 0< 00x1C 两个字节 表示是位图的色深short depth;depth == 24 //3个字节保存的东西为 R G B A:默认为0depth == 32 //四个字节保存的东西为 A R G B像素数组的大小:abs(width) * abs(high) * (depth/8)0x36 像素数组:保存每个像素点
触摸板的相关操作
在开发板上任意坐标显示一张任意分辨率的bmp图片
触摸屏的路径名: “/dev/input/event0”
int touch_fd = open("/dev/input/event0",O_RDONLY);if(touch_fd == -1){printf("open touch error\n");return -1;}
NOTE:
触摸板文件跟其他文件不同的是,它的内容吧,不是用数组保存,而是用一个结构体!在linux系统下面,所以的输入事件(鼠标,键盘,触摸板。。。)都用一个结构体来表示的
struct input_event{struct timeval time; //输入事件的时间_u16 type ; //事件的类型,如下:type == EV_KEY 表示这是一个按键事件type == EV_REL 表示这是一个鼠标事件type == EV_ABS 表示的是一个触摸板事件type == EV_SYN 事件的分割标志_u16 code; //要根据type的不同,它表示的含义也就不一样了type == EV_KEY 表示这是一个按键事件code 表示的是按键事件的键值 code == BTN_TOUCHtype == EV_REL 表示这是一个鼠标事件//这个暂时我们不讲!!因为我们用不到!type == EV_ABS 表示的是一个触摸板事件code 有几个值code == ABS_X 表示这是X轴的坐标code == ABS_Y 表示这是Y轴的坐标code == ABS_PRESSURE 表示这是给触摸板的压力_u16 value; //要根据type和code的不同,它表示的含义就不一样type == EV_KEY code == BTN_TOUCHvalue == 1 或者value == 0 表示按键按下/按键弹起type == EV_ABS code == ABS_X value == x轴坐标code == ABS_Y value == y轴坐标code == ABS_PRESSURE value == 压力值};
- NOTE:
应用程序,通过不断从输入设备文件,读取该结构体!
int xy_read()
{int x_read = -1;int y_read = -1;struct input_event ev;while(1){read();if(ev.type && ev.code){}}
}
练习:获取屏幕坐标
//获取坐标
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/input.h>
#include <unistd.h>
#include <string.h>
#define TOUCH_PATH "/dev/input/event0"
int touch_fd;
int xy_read()
{//1.打开触摸屏 touch_fd = open(TOUCH_PATH,O_RDONLY);//只读打开if(touch_fd<0){perror("open fail");return 0;}int x_read = -1;int y_read = -1;//定义一个结构体叫evstruct input_event ev;//一直读取触摸板信息while(1){//读取屏幕read(touch_fd, &ev, sizeof(struct input_event));//第三个参数evif(ev.type == EV_KEY && ev.code == BTN_TOUCH){if(ev.value == 1){printf("down\n");}else{printf("up\n");}}if(ev.type == EV_ABS) //触摸事件 {if(ev.code == ABS_X){x_read = ev.value; //x轴}if(ev.code == ABS_Y) //y轴{y_read = ev.value;}printf("(%d,%d)\n", x_read, y_read);} }
}int main()
{xy_read();close(touch_fd);
}
线程进程
我们的一个main就是一个进程
并发:同时进行两个或者两个以上的执行任务
线程就是我们主函数的一个分支,是比进程更加小的活动的单位,执行分支。
线程和进程都是我们平时所说的并发的一种方式!
指令它必须在函数的内部,线程的指令也会封装在函数的内部, 那么我们封装线程的指令函数叫做线程函数!!!线程函数的原型:
typedef void * (*start_routine_t)(void *)这样子的一个指针会指向我们的线程函数!!!那么线程函数是该长什么样子呢??参数:void *返回值:void *
- step1 :定义一个线程函数!!
void * display_adv(void *){while(1){//在你们的2048棋盘的旁边显示一个电子相册,用来播放小广告//显示第一个广告sleep(5);//显示第二个广告sleep(5);}}
- step2: 开辟这个分支
- 在linux中pthread的接口函数!
它可以创建一个线程:pthread_create
每一个线程都有自己的ID,用来唯一标识一个线程的,也就是每个线程都有一个ID身份证!!
id的类型:pthread_t ;
声明一个id: pthread_t id;
- 在linux中pthread的接口函数!
NAME
pthread_create - create a new thread创建一个新的线程
SYNOPSIS#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);pthread_t *thread : 指向你保存id号的那个空间!!!
const pthread_attr_t *attr : 表示线程的属性,一般为NULL,采用的是默认的属性
void *(*start_routine) (void *) : *start_routine : 指向它对应的线程函数
我们上面开创线程的目的就是为了人这个线程去执行线程函数!!
void * arg :其实它就是将要作为线程函数的实参传入!!!
Compile and link with -pthread.编译时加上-pthread
gcc xxx.c -o xxx -pthread
例子:
int main()
{pthread_t id;pthread_create(&id,NULL,&display_adv,NULL);while(1){show();}
}
练习:创建广告播放的一个线程
pthrad_t ad_th_num; // 定义一个线程号pthread_create(&ad_th_num,NULL,&ad,NULL);//线程任务函数 --- 广告void * ad(void * arg){while(1){bmp_show("");sleep(3);bmp_show("");sleep(3);}}
音频播放
- 命令:madplay
- 查看开发板是否已经安装了madplay
which madplay - 拷贝到/bin/
- 给权限
- 查看开发板是否已经安装了madplay
播放的方式!!
madplay的用法:madplay 路径
madplay ./mp3/1.mp3
* systemNAMEsystem - execute a shell commandSYNOPSIS#include <stdlib.h>int system(const char *command);const char *command : 是一个字符串,然后整个字符串就是我们要执行的那个命令!
char cmd[100];sprintf(cmd,"madplay ./mp3/1.mp3");sprintf(cmd,"madplay %s" , p);
相关
上一篇:
粤嵌GEC6818-学习笔记1-基础篇https://blog.csdn.net/weixin_45735391/article/details/125350683
下一篇:
粤嵌GEC6818-学习笔记3-相关项目https://blog.csdn.net/weixin_45735391/article/details/125820496
粤嵌GEC6818-学习笔记2-屏幕相关及音频播放相关推荐
- 基于粤嵌gec6818开发板嵌入式开发电子相册,音乐播放,视频播放,2048游戏
一.功能与要求 实现功能:本系统需要使用粤嵌的GEC-6818开发板设计一款娱乐影音系统,其中包括图片显示(相册).音乐播放.视频播放,游戏四个部分,在每个部分内部,具有操控各个部分的功能触摸按键.本 ...
- python语言怎么学-怎么学Python语言呢?粤嵌Python学习路线入门
Python的设计具有很强的可读性,相比其他语言经常使用英文关键字和一些标点符号,Python具有比其他语言更有特色的语法结构.随着大数据,人工智能时代的来临,Python已经成为有发展潜质的机器语. ...
- 【学习笔记】多项式相关算法
[学习笔记]多项式相关算法 手动博客搬家: 本文发表于20181125 13:19:28, 原地址https://blog.csdn.net/suncongbo/article/details/844 ...
- 吴恩达《机器学习》学习笔记十——神经网络相关(2)
吴恩达<机器学习>学习笔记十--神经网络相关(2) 一. 代价函数 二. 反向传播算法 三. 理解反向传播算法 四. 梯度检测 五. 随机初始化 1.全部初始化为0的问题 2.随机初始化的 ...
- 吴恩达《机器学习》学习笔记九——神经网络相关(1)
吴恩达<机器学习>学习笔记九--神经网络相关(1) 一. 非线性假设的问题 二. 神经网络相关知识 1.神经网络的大致历史 2.神经网络的表示 3.前向传播:向量化表示 三. 例子与直觉理 ...
- C语言实现电子音乐相册---粤嵌GEC6818嵌入式系统实训
C语言实现电子音乐相册---粤嵌GEC6818嵌入式系统实训 功能演示: 版本介绍 滑动式 点击放大式 完整版 至尊版 获取方式 功能演示: 演示视频: 滑动式 点击放大式 版本介绍 分为滑动式.点击 ...
- 模块化思想——粤嵌GEC6818读取图片宽度、高度、色深
推荐阅读:C语言实现2048小游戏-粤嵌GEC6818嵌入式系统实训 C语言实现电子音乐相册-粤嵌GEC6818嵌入式系统实训 模块化思想 交叉编译两个c文件的方法: 模块化思想: ... 只有一个唯 ...
- 粤嵌GEC6818开发板-入门感慨篇
第一次接触嵌入式开发,小脑袋是一篇空白,度娘各种资料,零零碎碎,似懂非懂,确实有点懵逼. 1.前期准备 粤嵌GEC6818开发板一套,USB转串口线一根(简称A线),网线一根(简称N线)(可选).用A ...
- 粤嵌gec6818开发板轮流显示颜色
粤嵌gec6818开发板轮流显示颜色 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> ...
最新文章
- 好程序员web前端分享javascript枚举算法
- 【数据挖掘笔记十三】数据挖掘的发展趋势和研究前沿
- mongoDB连接配置
- ucache灾备云报价_UCACHE灾备云功能
- BigPipe 大的页面分割成一个一个管道
- python marshal loads failed_在Python中marshal对象序列化的相关知识
- AJAX设置光标离开自动提交,Ajax自动提交和刷新页面
- Spark SQL将rdd转换为数据集-反射来推断Inferring the Schema Using Reflection
- python办公自动化案例-Python智能办公自动化实战课程
- MySQL→数据库、启动连接数据库、SQL→DDL数据定义语言及数据类型、DML数据操作语言、DQL数据查询语言、数据库约束→主键、唯一、非空、默认、外键、SQL、三大范式及一多关系、视图、内外连接
- cad抛物线lisp程序_数控车宏程序编程实用干货,全在这里了...
- Python计算机视觉编程pdf
- pca主成分分析_PCA主成分分析(中)
- gitbash PHP执行输出中文乱编解决方式
- eclipse ADT
- 千人虚拟社交体验,多人元宇宙场景真的可行么?
- deflate 压缩 java_Java和PHP配合:deflate(压缩)和inflate(解压)
- 经常被问到的有深度有内涵的数据结构面试题
- Chrome 设置黑色模式
- HCSA-03 Hillstone系统管理员分类、配置文件信息、版本升级、恢复出厂设置、许可证