lcd屏幕的显示原理
我们常说开发板的屏幕是800*480的
单位是什么? 像素点!
屏幕一行有800个像素点
一列有480个像素点。
像素点? 显示颜色的点
怎么让像素点显示自己想要的颜色?
OS规定: 一个 像素点由4个字节的大小来表示
这四个字节分别是什么呢?
A : 透明度 一般为0
R : Red 红色
G : Green 绿色
B : Blue 蓝色
RGB : 光的三基色
把这三种颜色 按照不同的比例混合
是不是就可以得到任何的颜色
A R G B 各占一个字节的大小
无符号一个字节(8bit)能表示的范围是多少?
0000 0000 1111 1111 1 0000 0000 - 1
0 ~ 255
也即是说:
假设我给A = 0 R =0 G = 0 B = 255
那么像素点应该显示最蓝色
如果要显示最红?
A = 0 R = 255 G = 0 B = 0
我们把这种用数字的范围来表示颜色的深浅的操作叫做颜色的量化
16进制 的一位 表示2进制的4位
假设我现在要用16进制表示最红
0x 0 255 0 0
0x A R G B
0x 00 ff 00 00
此时 也就是说 如果我想要给一个像素点上最红
那么我只需要将0X00ff0000写到像素点对应的控制点去
现在的问题是怎么写?
1. 写到哪里?
开发板有一个专门的屏幕文件 写到该文件里面就行
“/dev/fb0”
2. 怎么写?
linux的一句设计哲学
everything is file in linux
所有事物都是 文件 在linux下。
那么这意味着 我只需要学会操作文件的方法 我就可以操作linux下的一切。
第一步打开文件 open
linux手册
man 页数 要查的函数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
函数功能: 打开一个指定文件
头文件:如上
参数列表:
pathname:path:路径 name 名字
路径名 带路径的文件的名字
例子:
我要打开屏幕文件
/dev/fb0
flags:标志 决定你对打开文件的权限
o_RDONLY :只读
o_WRONLY:只写
o_RDWR:可读可写
返回值:
成功返回文件描述符(大于2的正整数)失败返回-1
打开屏幕文件代码:
int fd;
fd=open("/dev/fb0",O_RDWR);
if(fd==-1)
{
perror("失败");//perror会把错误原因告诉你(英文)
return -1;
}
第二步 :读文件内容 read 写文件 write
#include <unistd.h>
int write(int fd, const void *buf, int count);
函数功能: 往文件写入内容
头文件:如上
参数列表:
fd:文件描述符 open函数的返回值
表示一个打开的文件
buf:指向一段空间 这段空间用来保存你要写入的数据
count:表示你要写入多少字节数据
返回值:
成功返回实际写入的字节数 失败返回-1
int write(int fd, const void *buf, int count);
第三步:关闭文件 close
close(fd);
close只有一个参数 就是那个已经打开的文件的文件描述符
实现:
在开发板屏幕上显示粉色
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include <unistd.h>
int main()
{
int i=0;
int j=0;
int color[480][800]={0};
int fd=open("/dev/fb0", O_RDWR);
if(fd==-1)
{
perror("open error\n");
return -1;
}
for(i=0;i<480;i++)
{
for(j=0;j<800;j++)
{
color[i][j]=0x00ffc0cb;
}
}
write(fd,color,800*480*4);
close(fd);
}
在开发板屏幕上显示德国国旗
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/fb0",O_RDWR);
if(fd == -1){
perror("open error\n");
return -1;
}
int buf[480][800];
for(int i=0; i<480; i++)
{
for(int j=0; j<800; j++)
{
if(i<=160)
{
buf[i][j] = 0x00000000;
}
else if(i>160 && i<=320){
buf[i][j] = 0x00ff0000;
}
else
{
buf[i][j] = 0x00FFD700;
}
}
}
int d = write(fd,buf,800*480*4);
if(d == -1)
{
perror("open error\n");
return -1;
}
close(fd);
}
在开发板屏幕上显示圆
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/fb0",O_RDWR);
if(fd == -1)
{
perror("open error\n");
return -1;
}
int buf[480][800];
for(int i=0; i<480; i++)
{
for(int j=0; j<800; j++)
{
if(0.8*(i-240)*(i-240)+(j-400)*(j-400) <= 150*150)
{
buf[i][j] = 0x00000000;
}
else
{
buf[i][j] = 0x00FFD700;
}
}
}
int d = write(fd,buf,800*480*4);
if(d == -1)
{
perror("open error\n");
return -1;
}
close(fd);
}
在开发板上显示太极图
思路:两个左右黑白的半圆合成一个大圆,然后在同一条直径上画上下两个直径为大圆一半的圆,再在两个圆中画两个小圆
//画圆
void draw_round(int x,int y,int r,int color)
{
for(int i=0;i<480;i++)
{
for(int j=0;j<800;j++)
{
if((i-y)*(i-y)+(j-x)*(j-x) <=r*r)
{
*(addr +i*800 +j)=color;
}
}
}
}
//画左半圆
static void draw_Halfround_L(int x,int y,int r,int color)
{
for(int i=0;i<480;i++)
{
for(int j=0;j<800;j++)
{
if((i-y)*(i-y)+(j-x)*(j-x) <=r*r && j<=x)
{
*(addr +i*800 +j)=color;
}
}
}
}
//画右半圆
static void draw_Halfround_R(int x,int y,int r,int color)
{
for(int i=0;i<480;i++)
{
for(int j=0;j<800;j++)
{
if((i-y)*(i-y)+(j-x)*(j-x) <=r*r && j>=x)
{
*(addr +i*800 +j)=color;
}
}
}
}
static void draw_Halfround_T(int x,int y,int r,int color)
{
for(int i=0;i<480;i++)
{
for(int j=0;j<800;j++)
{
if((i-y)*(i-y)+(j-x)*(j-x) <=r*r && i<=y)
{
*(addr +i*800 +j)=color;
}
}
}
}
//太极图
void draw_TaiJi(int x,int y,int r)
{
//背景
draw_bmp("./TaiJi.bmp",0,0);
//大圆
draw_Halfround_L(x,y,r,0x00000000);
draw_Halfround_R(x,y,r,0x00FFFFFF);
draw_round(400,140,100,0x00FFFFFF); //上圆
draw_round(400,340,100,0x00000000); //下圆
draw_round(400,140,20,0x00000000); //上小圆
draw_round(400,340,20,0x00FFFFFF); //下小圆
}