目录
一、系统IO(文件IO)
open:打开一个文件
colse: 关闭文件
read: 读取文件信息
概念与用法
联系:读取一个文件大小
write: 向文件中写入
概念与用法
练习:读出来的数据,写入到另一个文件
二、开发板屏幕
6818屏幕介绍
概念与用法
lseek:定位光标的位置 光标定位的位置 +/- 偏移量
概念与用法
mmap:建设一个映射关系
概念与用法
练习:屏幕单刷、循环刷颜色,画矩形,三角形,圆形
正文
一、系统IO(文件IO)
open:打开一个文件
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
pathname:文件名 //路径
flags:文件打开的标志,代表了我们对文件的权限
O_RDONLY, //只读
O_WRONLY, //只写
O_RDWR //可读可写
返回值:成功返回一个新的文件描述符
文件描述符:程序运行过程中,打开文件的序号,操作文件,就是通过操作文件描述符(这个描述符很重要,我们对文件所有操作都是通过这个描述符定位再执行的 )
系统默认会打开三个文件:标准输入,标准输出,标准出错
失败返回-1,同时error被设置(perror())
打开一个文件的代码如下
int fd = open("hello.c",O_RDONLY); //开启描述符为fd的文件 if(-1 == fd) { perror("open error"); return -1; }
colse: 关闭文件
NAME
close - close a file descriptor
SYNOPSIS
#include <unistd.h>
int close(int fd); //关闭描述符为fd的文件
fd: 文件描述符
read: 读取文件信息
概念与用法
NAME
read - read from a file descriptor
SYNOPSIS
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
fd: 文件描述符,我们要读取的那个文件
buf:将读取的信息放在哪里
count:读取多少字节的信息(一次性读取多少字节)
返回值:成功返回读取到的字节数,如果返回0,说明文件已经读完了
失败返回-1 ,同时error被设置
char buf[1024] = {0}; //定义一个数组,将每次读取的数据存入其中 read(fd,buf,1024); //将描述符为fd的文件信息读到buf数组里,每次读取1024个字节
联系:读取一个文件大小
#include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #include <unistd.h> int read_wen() { int fd = open("99.c",O_RDONLY); //开启99.c文件 if(-1 == fd) { perror("open error"); return -1; } char buf[1024] = {0}; int num = 0,r; do { r = read(fd,buf,1024); //读取99.c文件 if(r == -1) { perror("read error"); return -2; } num += r; //将每次读取到的字节数存入num if(r != 0) printf("%s\n",buf); }while (r>0); //循环读取文件信息,直到某一次读取信息为0 printf("num = %d\n",num); close(fd); //关闭99.c文件 return 0; }
write: 向文件中写入
概念与用法
NAME
write - write to a file descriptor
SYNOPSIS
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
fd:文件描述符,写入的文件
buf:要写入的东西
count:写入的大小
返回值:成功返回写入的字节数,(0 表示没有写进去)
失败返回-1,同时error被设置
练习:读出来的数据,写入到另一个文件
int write_wen() { int fd1 = open("read.c",O_RDONLY); //开启要读取信息的文件 int fd2 = open("1.txt",O_WRONLY); //开启要写入信息的文件 if(-1 == fd1 || -1 == fd2) { perror("open error"); return -1; } int num = 0,r; do { char buf[1024] = {0}; r = read(fd1,buf,1024); //读取文件信息到buf里 //write(fd2,buf,1024); if(r == -1) { perror("read error"); return -2; } num += r; if(r != 0) //判断文件信息是否读完,否就执行写入程序 { printf("%s\n",buf); int w = write(fd2,buf,r); //将刚刚读取到信息的部分数组里的信息写入到fd2 if(-1 == w) { perror("write error"); return -3; } } }while (r>0); printf("num = %d\n",num); close(fd1); close(fd2); return 0; }
二、开发板屏幕
6818屏幕介绍
概念与用法
开发板的屏幕由像素点组成,480 * 800像素点
像素点由一个32位(4个字节)的数据来描述的
为了方便描述,我们将32位分为四组, a(透明度), r(红) ,g(绿), b(蓝)
描述一个红色
a r g b
0000 0000 1111 1111 0000 0000 0000 0000
0x00ff0000 或 0xff0000
描述一个白色
0000 0000 1111 1111 1111 1111 1111 1111
0xffffff
描述一个黑色
0x0
开发板屏幕属于帧缓存设备,他也是一个文件(/dev/fb0)
open()
write()写颜色
close()
800 * 480 * 4
关闭配置
vi /etc/profile
按i进入编辑模式
注释掉 cd /IOT(如果目录在这里就不要注释)
./iot
用#
保存退出
按esc结束编辑模式
输入:wq 保存退出
lseek:定位光标的位置 光标定位的位置 +/- 偏移量
概念与用法
问题:如果是已经将屏幕用一个颜色刷过一遍后,再换一种颜色刷是无法改变屏幕颜色的,因为刷过一遍后,光标会停留再最后的像素点那,再刷一遍只会往下刷,所以要回复光标
NAME
lseek - reposition read/write file offset
SYNOPSIS
#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence);
从光标所在位置开始偏移offset
fd:文件描述符,写入的文件
offset:偏移量 可正可负
whence:光标所在位置
SEEK_SET //文件头
The file offset is set to offset bytes.
SEEK_CUR //基于当前位置
The file offset is set to its current location plus offset
bytes.
SEEK_END //文件尾
The file offset is set to the size of the file plus offset
bytes.
返回值:成功返回光标所在位置(离文件头的位置)
失败返回-1,同时error被设置
mmap:建设一个映射关系
概念与用法
问题:用文件IO形式刷新屏幕,效率过低,需要一种更高效率的方式
NAME
mmap, 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);
addr:映射区的首地址,一般由系统分配,填NULL
length:映射区的长度
prot:映射区的权限,
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. //无权限
PROT_READ | PROT_WRITE //可读可写
flags:数据共享的标志
MAP_SHARED
公有的,共享
MAP_PRIVATE 私有的
fd:文件描述符,写入的文件
offset:偏移量 映射区哪个位置开始,一般给 0
返回值:成功返回映射区的首地址,
失败返回MAP_FAILED,同时error被设置
munmap:解映射
int munmap(void *addr, size_t length);
addr:映射区的首地址
length:映射区的长度
练习:屏幕单刷、循环刷颜色,画矩形,三角形,圆形
#include "lcd.h" unsigned int *plcd = NULL; int Display(int color,int x,int y) { if(x >= 0 && x <= 800 && y >= 0 && y <= 480) //全屏幕遍历 { *(plcd + y * 800 + x) = color; //y代表第几行,一行800像素,y*800代表这个像素点上面Y行的像素点个数 //x代表第几列,Y*800再加上x后,就定位到了这个像素点 //然后将color颜色赋值给这个像素点,完成这个像素点的颜色改变 } } int Lcd_Init() { int fd = open("/dev/fb0",O_RDWR); if(-1 == fd) { perror("open error"); return -1; } plcd = mmap(NULL,800 * 480 * 4,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); } void Dis_wh() { for(int i = 0;i < 480;i++) { for(int j = 0;j < 800;j++) { Display(0xffff, j, i); //将每个点都赋值0xffff这个颜色,实现颜色刷满全屏 } } } //画矩形 void Dis_qu() { for(int i = 100;i < 400;i++) { for(int j = 100;j < 600;j++) { Display(0xff5577, j, i); } } } //画圆 void Dis_yuan() { for(int i = 0;i < 480;i++) { for(int j = 0;j < 800;j++) { if((j - 400) * (j - 400) + (i - 240) * (i - 240) <= 10000) { Display(0xffff, j, i); } else { Display(0xff2467, j, i); } } } } //(y - y0)/(y2 - y0) = (x - x0)/(x2 - x0) //(350,350) (275,425) (350, 500) //(y - 300)/-100 = (x - 100)/100 y = - x + 400 //(y - 100)/100 = (x - 300)/-100 y = -x + 400 //画三角 void Dis_jiao() { for(int y = 0;y < 480;y++) { for(int x = 0;x < 800;x++) { if( x >= 100 && y <= 300 && y >= 100 && y <= -x + 400 && y >= x) { Display(0xff2467, x, y); } } } }