1 2 Fork me on GitHub 6

Day4_File_IO

1.内存映射

通过write去操作屏幕,有明显的缺陷

  • 屏幕很慢(write的效率不高)
  • 连续调用write还需要配合使用lseek
  • 只是想操作屏幕一小部分,对整个fram buffer赋值

即有人提出fram buffer本身就是一块内存,在C语言中,我们知道一个内存的地址(指针)就可以通过指针来操作这块内存。

假设:
	int *plcd;//指向linux你和帧缓冲的首地址
	屏幕上第一个像素点在帧缓冲中的地址为plcd
	*plcd = 0xff00;//屏幕上的第一个像素点会显示成绿的
	第一行的第二个像素点在帧缓冲中的地址:
	plcd+1
	*(plcd+1) = 0xff00;
	...
	屏幕上坐标为x,y的像素点在帧缓冲中的地址
	plcd+800*y+x
	*(plcd+800*y+x) = 0xff00;
	===>封装成函数 任意的在屏幕上显示一个像素点
void Lcd_draw_point(int x,int y,int color,int *plcd)
{
    if(NULL == plcd)
    {
        printf("error:plcd == NULL\n");
        return ;
    }
    if(x>=0&&x<800&&y>=0&&y<480)
    {
   		*(plcd+800*y+x) = color;
	}
}

image-20220519164113344

LINUX操作系统提供了一个API函数:mmap
memory map 内存映射
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:要映射区域长度。800*480*4
        @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.
	   位定义0000  PROT_EXEC PROT_READ PROT_WRITE PROT_NONE
            	  1000      0100     0010  0001
                   0110  0100 | 0010
       PROT_READ |  PROT_WRITE  
         @flags:映射标志 映射方式 有如下两种情况
             MAP_SHARED:共享映射 你对映射区域的操作会立即反馈到文件或内核
		     MAP_PRIVATE:私有映射 你对映射区域的操作只对你可见
         @fd:
         @offset:偏移量 表示你想从文件的哪个位置开始映射
          返回值:
             成功:返回映射区域的首地址
             失败:返回MAP_FAILED 同时errno被设置
             			
       int munmap(void *addr, size_t length);

2.文件io

系统IO:由操作系统提供的,LINUX/UNIX、 WIN <---- - 标准IO:为了更好的能够方便移植,同一标准。printf scanf... 它调用的系统IO屏幕

1.文件描述符

file discriptor 唯一性 整数
所有已经打开的文件都是通过文件描述符来引用。
文件描述符是在LINUX下面,唯一标识一个已经打开的文
件。后续对这个文件的所有的操作都通过文件描述符。

2.文件的操作

man:manual 手册

LINUX会为每个库函数/命令提供一个帮助文档,而 man则是用来查询该帮助文档的。

man ls 查询ls这条指令的帮助文件(默认是第一页)

选项-f 帮助文档的目录,因为你要查询的命令可能在 不同的环境下是不同的东西。函数名或者命令。

man -f ls f

man 数字 要查询的东西 :查看指定的页数

image-20220523154208362

a.open/close

NAME
	open - open a file
SYNOPSIS
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
	int open(const char *pathname, int
flags);
    @pathname:路径名 可以是相对路径也可以是
    绝对路径
    @flags:打开标志,文件打开以后的权限,读和写
    O_RDONLY:open_read_only
    O_WRONLY
    O_RDWR
	三个标志任选其一
	返回值:
		成功返回文件描述符(>2) 代表了该文件0 1 2 标准输入 标准输出 标准出错
		失败返回-1,并且errno(错误码)被设置
            我 	槟榔
            1 	 买到了
            0 	 有内鬼 终止交易
           -1    被他吃完了
           -2    ...
	errno ---> perror 
	NAME
		perror - print a system error message
	SYNOPSIS
		#include <stdio.h>
		void perror(const char *s);
		@s:所指向的内容由用户进行输入
			比如:perror("open fail");
		open fail:success\n
NAME
	close - close a file descriptor
SYNOPSIS
    #include <unistd.h>
    int close(int fd);

参考代码

int fd = open("/LJ/1.txt",O_RDWR);
if(-1 == fd)
{
    perror("open fail");
    return -1;
}
//...
close(fd);

b.read/write

NAME
	read - read from a file descriptor
SYNOPSIS
    #include <unistd.h>
    ssize_t read(int fd, void *buf,size_t count);
	从文件中读取count个字节放到buf所指向的地方中去。
        @fd:
        @buf:
        @count:
	返回值:
		>0 成功读取到的字节数,文件偏移量(光标)随之增加
		=0 什么都没有读到 到达文件的末尾 文件结束了
		<0 出错 同时errno被设置
NAME
	write - write to a file descriptorSYNOPSIS
	#include <unistd.h>
	ssize_t write(int fd, const void*buf, size_t count);
	把buf所指向的空间中最多count个字节写到fd所代表的文件中去。
	返回值:
        >0 成功写入的字节数,文件偏移量(光标)随之增加
        =0 什么都没有写入
        <0 出错 同时errno被设置
ps:
    ssize_t size_t ???
    使用typedef来定义的新类型
    typedef unsigned int Uint_32 //定义了一个新类型,名为Uint_32 实际上就是//unsigned int

c.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);
    @fd
    @offset:要设置的偏移量
    @whence:定位方式
	SEEK_SET 基于文件的开头
		The file offset is set to offset bytes.
	新的光标位置=文件开头+offset(>0)
	SEEK_CUR 基于光标当前的位置
		The file offset is set to its current location plus offset bytes.
	新的光标位置=光标当前的位置+offset(可正可负)
	SEEK_END 基于文件的末尾
		The file offset is set to the size of the file plus offset bytes.
	新的光标位置=文件的末尾+offset(可正可负)
返回值:
    成功返回新的光标位置相对于文件开头的偏移量 单位:字节
    失败返回-1,并且errno被设置
    重定位光标在文件的开头
    lseek(fd,0,SEEK_SET);
    使用lseek求文件的大小

3.LCD屏幕

一、屏幕属性

液晶显示屏

分辨率:有多少行 多少列像素点。
1080p:1080* 1920
2K:1440* 2545
4K:...
6818开发板:480p 480*800=384000个像素点

像素点

piexl:显示某种颜色的点。 

在屏幕上显示图像,就是给每个像素点一个颜色。 

颜色:红色 蓝色 黑色... DC2(DREAM COLOR梦幻) 十 亿色

 三基色:红绿蓝 RGB red green blue 红的程度不一样,怎么来形容这种程度呢?量化:数量化 RGB设备 

红0~255  	绿  	蓝 

255 			0 		0 		耀世红 0XFF0000 

0 				255	 0 		原谅绿 0xFF00 

0 				0 		255 	天空蓝 0XFF 

透明度: 一个像素点看起来透明的问题。A(占一个字节 0~255)

ARGB

6818开发板屏幕就是ARGB(四个字节)

二、LINUX帧缓冲

中间层OS的作用:对上层应用层提供操作硬件的接口函数, 屏蔽硬件具体实现细节。让用户不必去关系硬件的实现。 

在内存中开辟一块缓冲区,用来保存屏幕上每个像素点的 颜色值,然后应用成序直接把要显示的图像的颜色值写入 到内存即可。 

这块缓冲区buffer至少多大:800* 480* 4 

帧缓冲设备是对图像硬件的一种抽象,它让上层应用不必 去关心具体的硬件实现细节,上层图形应用,只需要在帧 缓冲中填上合适的颜色值,然后帧缓冲的驱动按一定的刷 新频率去把颜色值在屏幕上正确的显示。 

以上就是帧缓冲的原理。

LINUX中设计哲学:LINUX一切皆文件。 
屏幕:/dev/fb0 

三、练习

/*****************************************************************************
    字符串A123aBCd&$$eNd
    把大写字母->小写
        小写->大写
        其他字符不变
    要求:需要封装成函数
*****************************************************************************/
#if 0
#include <stdio.h>

char  *String_change(char str[]); 

int main()
{
    char str[] = {"A123aBCd&$$eNd"};
    printf("%s\n",String_change(str));
    return 0;
}
char  *String_change(char str[])
{
    int i = 0;
    for(;str[i]!='\0';i++)
    {
        if(str[i] >= 97&&str[i] <= 122)
        {
            str[i] -= 32;
        }
        else if(str[i] >= 65&&str[i] <=90)
        {
            str[i] += 32;
        }
    }
    return str;
}
#endif
/*****************************************************************************
在开发板的屏幕显示德国国旗
*****************************************************************************/
#if 0
#include<stdio.h>
/*头文件*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*宏定义*/
#define FILE_PATH "/dev/fb0"
int main(int argc,char **argv)
{
	//1.打开帧缓冲
	int fd = open("/dev/fb0",O_RDWR);
    if(-1 == fd)
	{
		perror("open fail");
        //print a system error message
		return -1;
	}
    /*
    int open(const char *pathname, int
    flags);
    @pathname:路径名 可以是相对路径也可以是
    绝对路径
    @flags:打开标志,文件打开以后的权限,读和
    写
    O_RDONLY : open_read_only
    O_WRONLY
    O_RDWR
    三个标志任选其一
    返回值:
    成功返回文件描述符(>2) 代表了该文件
    0 1 2 标准输入 标准输出 标准出错
    失败返回-1,并且errno(错误码)被设
    置
    */
	//2.写入颜色值
	int color[480][800];
	int i,j;
	for(j=0;j<480;j++)
	{
	    for(i=0;i<800;i++)
	    {
            id(j<=160)
	            color[j][i]=0x000000;
            else if(j<=320)
                color[j][i]=0xff0000;
            else 
                color[j][i]=0xffff00;
		}
	}
	int ret = write(fd,color,800*480*4);
    if(ret < 0)
	{
		perror("write fail");
		return -1;
	}
    /*
    ssize_t read(int fd, void *buf,
    size_t count);
    从文件中读取count个字节放到buf所指向的地方中
    去。
    @fd: 
    @buf: 
    @count: 
    返回值:
    >0 成功读取到的字节数,文件偏移量(光标)
    随之增加
    =0 什么都没有读到 到达文件的末尾 文件结束
    了
    <0 出错 同时errno被设置
    */
	//3.关闭文件
	close(fd);
}
#endif
/*****************************************************************************
使用lseek求文件的大小(单位字节)
    NAME   lseek - reposition read/write file offset
       即重定位光标
    off_t lseek(int fd, off_t offset,int whence);
    @fd
    @offset:要设置的偏移量
    @whence:定位方式
    SEEK_SET 基于文件的开头
        The file offset is set to offset bytes.
        新的光标位置=文件开头+offset(>0)
    SEEK_CUR 基于光标当前的位置
        The file offset is set to its current location plus offset bytes.
        新的光标位置=光标当前的位置+offset(可正可负)
    SEEK_END 基于文件的末尾
        The file offset is set to the size of the file plus offset bytes.
        新的光标位置=文件的末尾+offset(可正可负)
    返回值:
        成功返回新的光标位置相对于文件开头的偏移量
        单位:字节
        失败返回-1,并且errno被设置
        重定位光标在文件的开头
    lseek(fd,0,SEEK_SET);
*****************************************************************************/
#if 1
 #include<stdio.h>
/*头文件*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*宏定义*/
#define FILE_PATH "../ceshi.txt"
int main(int argc,char **argv)
{
    char str[1000] = "今天真好看!!";
    int i=0;
    /*
    打开文件:open(文件路径 O_RDONLY/O_WRONLY/O_RDWR)
    返回值:文件描述符(代表该文件)/-1.
    */
	int fd = open(FILE_PATH,O_RDWR);
    if(-1 == fd)
	{
		perror("open fail");
        //print a system error message
		return -1;
	}
    /*
    写入:write(文件描述符<-待放数据 ,内存大小)
     返回值:    >0 成功读取到的字节数,文件偏移量(光标)随之增加
                =0 什么都没有读到 到达文件的末尾 文件结束
                <0 出错 同时errno被设置
    */
    int length=lseek(fd,14,SEEK_SET);
    int ret = write(fd,str,1000);
    if(ret < 0)
	{
		perror("write fail");
		return -1;
	}
    /*将光标移回开头*/
    length=lseek(fd,0,SEEK_SET);
    /*从最后开始,0偏移,返回偏移量*/
    int red=read(fd,str,1000);
    if(red <= 0)
	{
		perror("read fail");
		return -1;
	}
    for(i=0;i<1000;i++)
        printf("%c",str[i]);
    length=lseek(fd,0,SEEK_END);
    printf("%d",length);
    close(fd);
}
#endif

RGB颜色查询对照表

4.homework

/********************************************************************
作业
1.在屏幕的x y(矩形的左上角)处显示一个颜色为color
高h宽为w的矩形
封装成函数
2.在屏幕上显示一个圆
封装成函数
拓展:显示一个太极图案
********************************************************************/
#if 0
/*头文件*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>

/*宏定义*/
#define FILE_PATH "/dev/fb0"

/*函数声明*/
int *Init_LCD(int *fd);
void Uninit_LCD(int fd,int *plcd);
void Lcd_draw_point(int x,int y,int color,int *plcd);
void Lcd_draw_matrx(int x,int y,int h,int w,int color,int *plcd );

void Lcd_draw_circle(int x,int y,int r,int color,int *plcd );
void Lcd_draw_leftcircle(int x,int y,int r,int color,int *plcd );
void Lcd_draw_rightcircle(int x,int y,int r,int color,int *plcd );

void Lcd_draw_taiji(int x,int y,int r,int *plcd);

int main(int argc,char **argv)
{
	int fd=-1;
	int* plcd = Init_LCD(&fd);
	Lcd_draw_matrx(0,0,880,480,0xff0000,plcd);//清屏
	//Lcd_draw_circle(440,240,200,0xff0000,plcd);
	Lcd_draw_taiji(440,240,200,plcd);
	Uninit_LCD(fd,plcd);
}

/*
	Init_LCD:初始化显示屏
	参数为空
	返回值 int*
		成功 返回映射区域的首地址
		失败 返回NULL
*/
int *Init_LCD(int *fd)
{
	//1.打开帧缓冲
	*fd = open("/dev/fb0",O_RDWR);
	if(-1 == *fd)
	{

		perror("open fail");
		return NULL;
	}
	//2.映射
	int *plcd = mmap(NULL,800*480*4
			,PROT_READ |  PROT_WRITE,
			MAP_SHARED,*fd,0);
	if(MAP_FAILED == plcd)
	{
		perror("mmap fail");
		return NULL;
	}
	return plcd;
}

/*
	Uninit_LCD:解初始化屏幕
	@fd:帧缓冲的文件描述符
	@plcd:
	返回值:无
*/
void Uninit_LCD(int fd,int *plcd)
{
	//1.解映射
	munmap(plcd,800*480*4);
	//2.关闭帧缓冲
	close(fd);
}

void Lcd_draw_point(int x,int y,int color,int *plcd)
{
    if(NULL == plcd)
    {
        printf("error:plcd == NULL\n");
        return ;
    }
    if(x>=0&&x<800&&y>=0&&y<480)
    {
   		*(plcd+800*y+x) = color;
	}
}

void Lcd_draw_matrx(int x,int y,int h,int w,int color,int *plcd)
{
	int i,j;
	if((x+w)>=0||(x+w)<=880||(y+h)>=0||(y+h)<=880)
		for(j=x;j<x+w;j++)
		{
			for(i=y;i<y+h;i++)
			{
				Lcd_draw_point(i,j,color,plcd);
			}
		}
}

void Lcd_draw_circle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}
void Lcd_draw_leftcircle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r&&i<x)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}
void Lcd_draw_rightcircle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r&&i>=x)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}

void Lcd_draw_taiji(int x,int y,int r,int* plcd)
{
	Lcd_draw_leftcircle(x,y,r,0x000000,plcd);
	Lcd_draw_rightcircle(x,y,r,0xffffff,plcd);
	Lcd_draw_circle(x,y-(r/2),r/2,0xffffff,plcd);
	Lcd_draw_circle(x,y+(r/2),r/2,0x000000,plcd);
	Lcd_draw_circle(x,y-(r/2),r/4,0x000000,plcd );
	Lcd_draw_circle(x,y+(r/2),r/4,0xffffff,plcd );
}
#endif
/*******************************************************************************
碰壁转弯直线代码
*******************************************************************************/
#if 0
/*头文件*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>

/*宏定义*/
#define FILE_PATH "/dev/fb0"

/*函数声明*/
int *Init_LCD(int *fd);
void Uninit_LCD(int fd,int *plcd);
void Lcd_draw_point(int x,int y,int color,int *plcd);
void Lcd_draw_matrx(int x,int y,int h,int w,int color,int *plcd );

void Lcd_draw_circle(int x,int y,int r,int color,int *plcd );
void Lcd_draw_leftcircle(int x,int y,int r,int color,int *plcd );
void Lcd_draw_rightcircle(int x,int y,int r,int color,int *plcd );

void Lcd_draw_taiji(int x,int y,int r,int *plcd);

int main(int argc,char **argv)
{
	int fd=-1;
	int* plcd = Init_LCD(&fd);
	Lcd_draw_matrx(0,0,880,480,0xff0000,plcd);//清屏
	//Lcd_draw_circle(440,240,200,0xff0000,plcd);
	Lcd_draw_taiji(440,240,5,plcd);
	Uninit_LCD(fd,plcd);
}

/*
	Init_LCD:初始化显示屏
	参数为空
	返回值 int*
		成功 返回映射区域的首地址
		失败 返回NULL
*/
int *Init_LCD(int *fd)
{
	//1.打开帧缓冲
	*fd = open("/dev/fb0",O_RDWR);
	if(-1 == *fd)
	{

		perror("open fail");
		return NULL;
	}
	//2.映射
	int *plcd = mmap(NULL,800*480*4
			,PROT_READ |  PROT_WRITE,
			MAP_SHARED,*fd,0);
	if(MAP_FAILED == plcd)
	{
		perror("mmap fail");
		return NULL;
	}
	return plcd;
}

/*
	Uninit_LCD:解初始化屏幕
	@fd:帧缓冲的文件描述符
	@plcd:
	返回值:无
*/
void Uninit_LCD(int fd,int *plcd)
{
	//1.解映射
	munmap(plcd,800*480*4);
	//2.关闭帧缓冲
	close(fd);
}

void Lcd_draw_point(int x,int y,int color,int *plcd)
{
    if(NULL == plcd)
    {
        printf("error:plcd == NULL\n");
        return ;
    }
    if(x>=0&&x<800&&y>=0&&y<480)
    {
   		*(plcd+800*y+x) = color;
	}
}

void Lcd_draw_matrx(int x,int y,int h,int w,int color,int *plcd)
{
	int i,j;
	if((x+w)>=0||(x+w)<=880||(y+h)>=0||(y+h)<=880)
		for(j=x;j<x+w;j++)
		{
			for(i=y;i<y+h;i++)
			{
				Lcd_draw_point(i,j,color,plcd);
			}
		}
}

void Lcd_draw_circle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}
void Lcd_draw_leftcircle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r&&i<x)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}
void Lcd_draw_rightcircle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r&&i>=x)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}

void Lcd_draw_taiji(int x,int y,int r,int* plcd)
{
	//上圆心
	int i0=x;
	int j0=y-r/2;
	//下圆心
	int i2=x;
	int j2=y+r/2;
	int flog=0;
	int flog1=0;
	while(1)
	{
		if(0==flog)
		{
			j0--;
			Lcd_draw_circle(i0,j0,r/2,0xffffff,plcd);
			Lcd_draw_circle(i0,j0,r/4,0x000000,plcd );
			//sleep(0.5);
			if(j0==1)flog=1;
		}
		if(1==flog)
		{
			j0++;
			Lcd_draw_circle(i0,j0,r/2,0xffffff,plcd);
			Lcd_draw_circle(i0,j0,r/4,0x000000,plcd );
			//sleep(0.5);
			if(j0==480)flog=0;
		}
		if(0==flog1)
		{
			i0++;
			Lcd_draw_circle(i0,j0,r/2,0xffffff,plcd);
			Lcd_draw_circle(i0,j0,r/4,0x000000,plcd );
			//sleep(0.5);
			if(i0==800)flog1=1;
		}
		if(1==flog1)
		{
			i0--;
			Lcd_draw_circle(i0,j0,r/2,0xffffff,plcd);
			Lcd_draw_circle(i0,j0,r/4,0x000000,plcd );
			//sleep(0.5);
			if(i0==1)flog1=0;
		}
	}
}
#endif
/********************************************************************
 * 转动太极图案代码
 * 
********************************************************************/
#if 1
/*头文件*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>

/*宏定义*/
#define FILE_PATH "/dev/fb0"

/*函数声明*/
int *Init_LCD(int *fd);
void Uninit_LCD(int fd,int *plcd);
void Lcd_draw_point(int x,int y,int color,int *plcd);
void Lcd_draw_matrx(int x,int y,int h,int w,int color,int *plcd );

void Lcd_draw_circle(int x,int y,int r,int color,int *plcd );
void Lcd_draw_leftcircle(int x,int y,int r,int color,int *plcd );
void Lcd_draw_rightcircle(int x,int y,int r,int color,int *plcd );

void Lcd_draw_taiji(int x,int y,int r,int *plcd);

int main(int argc,char **argv)
{
	int fd=-1;
	int* plcd = Init_LCD(&fd);
	Lcd_draw_matrx(0,0,880,480,0xff0000,plcd);//清屏
	//Lcd_draw_circle(440,240,200,0xff0000,plcd);
	Lcd_draw_taiji(400,240,200,plcd);
	Uninit_LCD(fd,plcd);
}

/*
	Init_LCD:初始化显示屏
	参数为空
	返回值 int*
		成功 返回映射区域的首地址
		失败 返回NULL
*/
int *Init_LCD(int *fd)
{
	//1.打开帧缓冲
	*fd = open("/dev/fb0",O_RDWR);
	if(-1 == *fd)
	{

		perror("open fail");
		return NULL;
	}
	//2.映射
	int *plcd = mmap(NULL,800*480*4
			,PROT_READ |  PROT_WRITE,
			MAP_SHARED,*fd,0);
	if(MAP_FAILED == plcd)
	{
		perror("mmap fail");
		return NULL;
	}
	return plcd;
}

/*
	Uninit_LCD:解初始化屏幕
	@fd:帧缓冲的文件描述符
	@plcd:
	返回值:无
*/
void Uninit_LCD(int fd,int *plcd)
{
	//1.解映射
	munmap(plcd,800*480*4);
	//2.关闭帧缓冲
	close(fd);
}

void Lcd_draw_point(int x,int y,int color,int *plcd)
{
    if(NULL == plcd)
    {
        printf("error:plcd == NULL\n");
        return ;
    }
    if(x>=0&&x<800&&y>=0&&y<480)
    {
   		*(plcd+800*y+x) = color;
	}
}

void Lcd_draw_matrx(int x,int y,int h,int w,int color,int *plcd)
{
	int i,j;
	if((x+w)>=0||(x+w)<=880||(y+h)>=0||(y+h)<=880)
		for(j=x;j<x+w;j++)
		{
			for(i=y;i<y+h;i++)
			{
				Lcd_draw_point(i,j,color,plcd);
			}
		}
}

void Lcd_draw_circle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}
void Lcd_draw_leftcircle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r&&i<x)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}
void Lcd_draw_rightcircle(int x,int y,int r,int color,int *plcd )
{
	int i,j;
	for(j=0;j<480;j++)
		{
			for(i=0;i<880;i++)
			{
				if((x-i)*(x-i)+(y-j)*(y-j)<r*r&&i>=x)
					Lcd_draw_point(i,j,color,plcd);
			}
		}
}

void Lcd_draw_taiji(int x,int y,int r,int* plcd)
{
	int i=0,j=0;
	int m=i+10,n=j+10;
	int time=500;
	//上圆心
	int i0=x;
	int j0=y-r/2;
	//下圆心
	int i2=x;
	int j2=y+r/2;
	int addx[20]={400,372,340,320,304,300,304,320,340,373,400,428,460,480,496,500,496,480,460,428};
	int addy[20]={140,144,160,180,212,240,268,300,320,336,340,336,320,300,268,240,212,180,160,144};
	//画两个半圆
	Lcd_draw_leftcircle(x,y,r,0x000000,plcd);//黑
	Lcd_draw_rightcircle(x,y,r,0xffffff,plcd);//白
	//画两个大圆
	Lcd_draw_circle(i0,j0,r/2,0xffffff,plcd);
	Lcd_draw_circle(i2,j2,r/2,0x000000,plcd);
	//画两个小圆
	Lcd_draw_circle(i0,j0,r/4,0x000000,plcd );
	Lcd_draw_circle(i2,j2,r/4,0xffffff,plcd );
	while(1)
	{
		//画两个大圆
		Lcd_draw_circle(addx[i],addy[j],r/2,0xffffff,plcd);
		Lcd_draw_circle(addx[m],addy[n],r/2,0x000000,plcd);
		//sleep(0.25);
		//画两个小圆
		Lcd_draw_circle(addx[i],addy[j],r/4,0x000000,plcd );
		Lcd_draw_circle(addx[m],addy[n],r/4,0xffffff,plcd );
		i++;
		j++;
		m++;
		n++;
		sleep(0.5);
		if(20==i)i=0;
		if(20==j)j=0;
		if(20==m)m=0;
		if(20==n)n=0;
	}	

}
#endif
/*
//用这个程序求出解的数组:
#include<stdio.h>
int main()
{
	int i, j;
	//int str[10000][10000];
	for (j = 140; j <= 340;j++)
	{
		for (i = 300; i <= 500; i++)
		{
			if (207600 + i * i + j * j == 800 * i + 480 * j)
			{
				printf("有解:%d,%d",i,j);
				printf("\n");
				
			}
		}
	}
	return 0;
}
有解:400,140
有解:372,144
有解:428,144
有解:340,160
有解:460,160
有解:320,180
有解:480,180
有解:304,212
有解:496,212
有解:300,240
有解:500,240
有解:304,268
有解:496,268
有解:320,300
有解:480,300
有解:340,320
有解:460,320
有解:372,336
有解:428,336
有解:400,340
即:
//上圆逆时针转到下圆:0-9
400,140
372,144
340,160
320,180
304,212
300,240
304,268
320,300
340,320
372,336
//下圆逆时针转到上圆:10-19
400,340
428,336
460,320
480,300
496,268
500,240
496,212
480,180
460,160
428,144
*/

posted @   JianFeng丶  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示