IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FPGA 25 RGB888(兼容RGB565) 屏幕驱动设计 -> 正文阅读

[嵌入式]FPGA 25 RGB888(兼容RGB565) 屏幕驱动设计

在这里插入图片描述

FPGA 25 RGB888(兼容RGB565) 屏幕驱动设计

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XxtUOmuy-1628878116223)(img/blog_img/fpga/image-20210809211148995.png)]

主要功能 :设计了RGB88 的通用驱动模块

实现(设计)流程:根据RGB888 屏幕的工作原理以及数据传输协议方式,编写输出信号的发送,进而将我们要显示的图像显示到屏幕上。

实验目的 : 直接使用fpga芯片设计RGB88 的驱动,而不是使用屏幕驱芯片来驱动。对于一般的单片机来说,要达到较好的显示效果,必定会占用大量的cpu资源,而fpga 的并行能力则很好的解决了这个问题,由于模块和模块之间的互不影响,所以使用fpga驱动 rgb屏幕的效果方面会比较好.

实验现象 : 通过内部设计一个屏幕驱动显示模块,实现屏幕2*4=8 区域颜色显示的效果

屏幕基础知识:

常用屏幕接口:

1、8080屏幕 (在 51 单片机上,使用最广泛的显示设备就是 1602、 12864 字符点阵 )

2、彩色液晶屏(内部带有显示缓存存储器,这样只要把待显示的内容写入到显存,使用 STM32 的 FSMC 总线,将液晶显示屏映射为一块存储区,直接使用 FSMC 总线对该存储区进行读写 )

3、RGB屏幕(WindowsCE、 Linux 等等。而且它们都能驱动很多的大屏幕 ,屏幕本身不含显存,需要驱动器能够带有显存,并按照 RGB 时序准确的将显存中的数据送到屏幕上显示,而一般的单片机STM32 由于工作速度、总线带宽、存储容量有限,很难支持如此高的数据刷新速率 。)

RGB 基本知识了解:

? 常用的 4.3/5 寸显示屏都是以模组的形式提供的,各大厂家生产的模组,其接口引脚顺序都是兼容的,而且接口时序也都是标准 的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ujAh1W96-1628878116226)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525143133542.png)]

AT043TN24 模组的接口编号即功能描述如表 5.5.1 所示 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-obBTNqXa-1628878116228)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525145903628.png)]

原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-at1RfYbL-1628878116230)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525145614432.png)]

接口功能定义

注: 背光要求供电【VLED+ VLED-】)电压为 18.6V 到 21V,电流为 36mA 到 44mA 之间。因此需要额外的升压电路 。

? 该屏幕的颜色数据支持 24 位输入,即每种颜色(RGB)有 8 位表示。由于在一般的数字系统中常常使用 16 位色(RGB565)进行图像显示,并且为了节约 FPGA引脚,本实验中,只选取了 24 位颜色数据中的一部分数据,将其精简为 16 位。为了保证精简数据后,图像颜色能够不失真,因此分别选取 R、 G、 B 数据线的高 5、 6、 5 位,组成新的
16 位数据线。此外,开发的驱动也可以很好的兼容RGB565屏幕,可以实现一个模块,两种屏幕的共同实验问题。 RGB 数据的格式如表 27.2 所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-psza3flW-1628878116231)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525150431990.png)]

常见数据颜色:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jCQ4rpLR-1628878116232)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525150549593.png)]

2、RGB 接口 TFT 屏扫描方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hBkVjy8v-1628878116233)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525150801764.png)]

VGA原理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z3Q42uD7-1628878116234)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525151612817.png)]

液晶显示器原理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZnqJQrz-1628878116235)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152425551.png)]

VGA 和液晶屏驱动相同点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xhC2PD4R-1628878116235)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152445297.png)]

3、RGB 接口 TFT 屏时序分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5iugKlar-1628878116236)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152636439.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kI4YBOiL-1628878116236)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152718299.png)]

实现行和场的方式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zu2uKS2l-1628878116237)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152814618.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GZ7i0jMc-1628878116238)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152937555.png)]

实现方式:模块内使用两个计数器分别进行、场计数, 然后根据计数器的计数值确定像素数据内容和行、场同步信号的电平状态 。

模块接口设计 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pKDaR00c-1628878116239)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525163722322.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvolKB38-1628878116240)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525163739580.png)]

//TFT 行、场扫描时序参数表
parameter   TFT_HS_end=10'd40,
            hdat_begin=10'd42,
            hdat_end=10'd522,
            hpixel_end=10'd524,
            TFT_VS_end=10'd9,
            vdat_begin=10'd11,
            vdat_end=10'd283,
            vline_end=10'd285;

行扫描计数器即每个像素时钟自加 1,一旦加满到 524(刚好 525 个时钟周期),计数器清零并重新计数,该部分代码可如下设计:

reg [9:0] hcount_r; //TFT 行扫描计数器
//行扫描计数器
always@(posedge Clk9M or negedge Rst_n)
    if(!Rst_n) //复位时,让行扫描计数器清零
        hcount_r<=10'd0;
else if(hcount_r== hpixel_end) //当一行数据扫完后,再次清零行扫描计数器
	hcount_r<=10'd0;
else //0~524 之间,每个像素时钟时行扫描计数器自加 1
	hcount_r<=hcount_r+10'd1;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AE4Z7VMx-1628878116240)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525165507460.png)]

(很重要!!!)注 :只有每次一行扫描完成(即:行扫描计数器(hcount_r) == 最终的像素点hpixel_end的时候),场扫描计数器vcount_r才会开始变化(清零 或者 +1)

reg [9:0] vcount_r; //TFT 场扫描计数器
//场扫描计数器
always@(posedge Clk9M or negedge Rst_n)
if(!Rst_n) //复位时让场计数器清零
    vcount_r<=10'd0;
else if(hcount_r== hpixel_end) begin //每次一行扫描完成,场扫描计数器信号才会开始变化(清零 或者 +1)
    if(vcount_r== vline_end) //每次一场扫描结束,清零计数器
        vcount_r<=10'd0;
    else
        vcount_r<=vcount_r+10'd1;//场计数器在 0~285,满足条件,自加 1
    end
else //不满足行扫描结束条件器件,让场扫描计数器保持不变
	vcount_r<=vcount_r;

行同步信号和场同步信号控制设计(设计接两个信号和屏幕计数器的高低电平的设置):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IQR1jvdY-1628878116241)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525170333767.png)]

assign TFT_HS = (hcount_r>TFT_HS_end)?1'b1:1'b0;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZkqWd58F-1628878116241)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525170425425.png)]

assign TFT_VS = (vcount_r>TFT_VS_end)?1'b1:1'b0;

个人表述(屏幕工作流程描述):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hauOySoA-1628878116242)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525152937555.png)]

对于一帧完整的图片(480*272 的图片)来说,我们每次接收显示,要执行以下流程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PGMlMkAs-1628878116242)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525171524909.png)]

? step1: 先发送一个行同步信号序列(525个时钟周期组成一个行同步信号序列),在 0-41的时钟周期下,给行同步信号引脚 【HS,发送低电平】,41-43时钟周期下,HS 引脚发送【高电平信号】,43-523时钟周期下,HS发送【高电平】,523-525时钟周期下,HS发送【高电平】。这就是一个完整的行时序实现。

? step2: 场扫描的实现,首先,我们要确定或者知道的是,在一帧的图片传输的过程中,只有1个场扫描序列(相对于行信号序列的 272行扫描序列),并且,我们也可以看到,对于一个输入的信号,只有每一个行信号序列的最后一个时钟周期(clk = 525)时,我们才会+1个场信号时钟周期,其余时间保持信号不变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s5sIRahK-1628878116243)(E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210525172401229.png)]

所以,显然可知,场信号的1个时钟周期是 == 525个行信号时钟周期。我们在【代码中】也可以看到,只有我们的行信号时钟计数器计数了525个时钟周期以后,我们才产生了给场时钟信号【计数器】+1。这就是一帧完整的时钟信号的变化。

数据(图像/图片)输出状态设计 :

首先我们要指导在整个一帧的图片中,只有中间时序的图像显示区域,我们输入的数据才是有效的,其余地方的数据都是无效的,所以,根据时序的情况,我们根据时序的变化来确定什么时候,我们的输入是可直接输出到屏幕,而其他的时刻,我们是不应该输入数据的,或者说让我们的输入数据无效.

//数据、同步信号输出
assign dat_act=((hcount_r>= hdat_begin)&&(hcount_r< hdat_end))
&&((vcount_r>= vdat_begin)&&(vcount_r< vdat_end));

数据选择:

利用二选一多路器实现消隐强制输出 0,代码如下所示。其中, TFT_RGB 是输出到 VGA接口上的数据,而 data_in 则是其他模块传递过来的正确的图像数据。dat_act =1 时,表示我们现在的数据可以直接输入到屏幕,反之我们输出的信号位16‘h0000.

assign TFT_RGB=(dat_act==1)?data_in:16'h0000;

行列扫描位置输出设计 (等价理解为 图片的 X轴 和 Y轴坐标)

这样的话我们可以通过: hcount ,hcount (X, Y)给信号控制模块,让信号控制模块输出在该点的图像数据

assign hcount = hcount_r- hdat_begin;
assign hcount = vcount_r- vdat_begin;

时钟及使能控制设计

assign TFT_CLK = Clk9M;
assign TFT_DE = dat_act;
assign TFT_PWM = Rst_n;

仿真及板级验证 :

module TFT_LCD
(
	Clk9M,
	Rst_n,
	Data_in,
	
	vcount,
	hcount,
	TFT_RGB,
	TFT_VS,
	TFT_HS,
	TFT_CLK,
	TFT_DE,
	TFT_PWM
);

	input Clk9M ;
	input Rst_n ;
	input [15:0]Data_in;  // RGB 每个像素点的待显示的数据

	output [9:0]vcount ;	//行扫描地址(X 轴坐标)
	output [9:0]hcount ;	//场扫描地址(Y 轴坐标)
	
	output [15:0]TFT_RGB	;	//三原色数据输出 RGB565
	output TFT_VS 	;	// 场同步输出信号
	output TFT_HS 	;	// 行同步输出信号
	output TFT_CLK	;	// TFT像素时钟
	output TFT_DE 	;	// 背光使能
	output TFT_PWM	;	// 背光控制

//TFT 行、场扫描时序参数表
parameter   TFT_HS_end=10'd40, //行消隐时间数
            hdat_begin=10'd42,
            hdat_end=10'd522,
            hpixel_end=10'd524,

            TFT_VS_end=10'd9, //场消隐时间数
            vdat_begin=10'd11,
            vdat_end=10'd283,
            vline_end=10'd285;

reg [9:0] hcount_r; //TFT 行扫描计数器

wire dat_act;         //有效显示标定

//行扫描计数器
always@(posedge Clk9M or negedge Rst_n)
    if(!Rst_n) //复位时,让行扫描计数器清零
        hcount_r<=10'd0;
else if(hcount_r== hpixel_end) //当一行数据扫完后,再次清零行扫描计数器
	hcount_r<=10'd0;
else //0~524 之间,每个像素时钟时行扫描计数器自加 1
	hcount_r<=hcount_r+10'd1;

reg [9:0] vcount_r; //TFT 场扫描计数器
//场扫描计数器
always@(posedge Clk9M or negedge Rst_n)
if(!Rst_n) //复位时,让行扫描计数器清零
	vcount_r<=10'd0;
else if(hcount_r== hpixel_end) begin  //每次一行扫描完成
	if(vcount_r == vline_end)
		vcount_r<=10'd0;
	else
		vcount_r <= vcount_r + 1'd1;
	end
else //0~524 之间,每个像素时钟时行扫描计数器自加 1
	vcount_r <= vcount_r;


//行同步信号和场同步输出信号控制设计:
assign  TFT_HS = (hcount_r > TFT_HS_end)? 1'b1:1'b0 ;
assign  TFT_VS = (vcount_r > TFT_VS_end)? 1'b1:1'b0 ;

//像素点数据输出选择
// dat_act : 2选1 数据选择器,场消隐和行消隐信号在图像显示区,设置为1,选中1通道,否则选中0通道

assign dat_act=((hcount_r>= hdat_begin)&&(hcount_r< hdat_end))
&&((vcount_r>= vdat_begin)&&(vcount_r< vdat_end));

// TFT_RGB 数据输出: 由 dac_act 信号来选择
assign TFT_RGB = (dat_act)?Data_in:16'h0000;


// X// 实际TFT屏幕 X ,Y 轴坐标输出
//output [9:0]vcount ;	//行扫描地址(y 轴坐标)
//output [9:0]hcount ;	//场扫描地址(x 轴坐标)
assign vcount=(dat_act)?(vcount_r-vdat_begin):10'd0; //  y轴
assign hcount=(dat_act)?(hcount_r-hdat_begin):10'd0; //  x轴 ,Y 轴坐标输出

// TFT_CLK 时钟信号 ,这个是完成和外部TFT_LCD模块 通信的时钟
assign TFT_CLK = Clk9M;

//	output TFT_DE 	;	// 背光使能
// TFT_DE 直接与 dat_act 信号相连,即在有效显示区域时使能 LED 屏幕
assign TFT_DE = dat_act ;

//	output TFT_PWM	;	// 背光控制
//  TFT_PWM则直接与复位输入相连,即当复位结束后便一直开启背光
assign TFT_PWM = Rst_n;

endmodule


test_bench 文件:

`timescale 1ns/1ps
`define clk_period 120

module TFT_LCD_tb ;

	reg Clk9M ;
	reg Rst_n ;
	reg [15:0]Data_in;  // RGB 每个像素点的待显示的数据

	wire [9:0]vcount ;	//行扫描地址(X 轴坐标)
	wire [9:0]hcount ;	//场扫描地址(Y 轴坐标)
	
	wire [15:0]TFT_RGB	;	//三原色数据输出 RGB565
	wire TFT_VS 	;	// 场同步输出信号
	wire TFT_HS 	;	// 行同步输出信号
	wire TFT_CLK	;	// TFT像素时钟
	wire TFT_DE 	;	// 背光使能
	wire TFT_PWM	;	// 背光控制

	reg [7:0]v_cnt = 0; //扫描帧数统计计数器
	
 TFT_LCD TFT_LCD_01
	(
		.Clk9M(Clk9M),
		.Rst_n(Rst_n),
		.Data_in(Data_in),
		
		.vcount(vcount),
		.hcount(hcount),
		.TFT_RGB(TFT_RGB),
		.TFT_VS(TFT_VS),
		.TFT_HS(TFT_HS),
		.TFT_CLK(TFT_CLK),
		.TFT_DE(TFT_DE),
		.TFT_PWM(TFT_PWM)
	);

	
initial Clk9M = 0;
always #(`clk_period/2) Clk9M = ~Clk9M;

initial begin
	Rst_n = 1'b0;
	Data_in = 16'd0;
	#(`clk_period*200 + 1);
	Rst_n = 1'b1;
	Data_in = 16'h1010;
end
	
	
	always@(posedge TFT_VS)   //统计总扫描帧数 TFT_VS:上升沿到来时,即代表一帧图像开始
	v_cnt = v_cnt + 1'b1;
	
initial 
	begin
		wait(v_cnt == 3);  //等待扫描2帧后结束仿真
		$stop;
	end
	


endmodule	

	

top 顶层显示设计文件:

module TFT_CTRL_test(
	Clk, 	//50MHZ时钟
	Rst_n,
    
	TFT_RGB,//TFT数据输出
	TFT_HS,	//TFT行同步信号
	TFT_VS,	//TFT场同步信号
	TFT_CLK,
	TFT_DE,
	TFT_PWM
);

	input Clk;
	input  Rst_n;
	output [15:0]TFT_RGB;
	output TFT_HS;
	output TFT_VS;
	output TFT_CLK;
	output TFT_DE;
	output TFT_PWM;
	
	reg [15:0]disp_data;
	wire [9:0]hcount;
	wire [9:0]vcount;
	wire Clk33M;



TFT_pll TFT_pll_01 (
	.inclk0(Clk),
	.c0(Clk33M)
	);

	
	
TFT_LCD TFT_LCD_01
	(
		.Clk33M(Clk33M),
		.Rst_n(Rst_n),
		.Data_in(disp_data),
		
		.vcount(vcount),
		.hcount(hcount),
		.TFT_RGB(TFT_RGB),
		.TFT_VS(TFT_VS),
		.TFT_HS(TFT_HS),
		.TFT_CLK(TFT_CLK),
		.TFT_DE(TFT_DE),
		.TFT_PWM(TFT_PWM)
	);


//定义颜色编码
localparam 
	//BLACK		= 16'h0000, //黑色
	BLACK		= 16'h4000, //棕色
	BLUE		= 16'h001F, //蓝色
	RED			= 16'hF800, //红色
	PURPPLE		= 16'hF81F, //紫色
	GREEN		= 16'h07E0, //绿色
	CYAN		= 16'h07FF, //青色
	YELLOW		= 16'hFFE0, //黄色
	WHITE		= 16'hFFFF; //白色
	
//定义每个像素块的默认显示颜色值
localparam 
	R0_C0 = BLACK,	//第0行0列像素块
	R0_C1 = BLUE,	//第0行1列像素块
	R1_C0 = RED,	//第1行0列像素块
	R1_C1 = PURPPLE,//第1行1列像素块
	R2_C0 = GREEN,	//第2行0列像素块
	R2_C1 = CYAN,	//第2行1列像素块
	R3_C0 = YELLOW,	//第3行0列像素块
	R3_C1 = WHITE;	//第3行1列像素块

	wire R0_act = vcount >= 0 && vcount < 120;	//正在扫描第0行
	wire R1_act = vcount >= 120 && vcount < 240;//正在扫描第1行
	wire R2_act = vcount >= 240 && vcount < 360;//正在扫描第2行
	wire R3_act = vcount >= 360 && vcount < 480;//正在扫描第3行
	
	wire C0_act = hcount >= 0 && hcount < 400; //正在扫描第0列
	wire C1_act = hcount >= 400 && hcount < 800;//正在扫描第1列 
	
	wire R0_C0_act = R0_act & C0_act;	//第0行0列像素块处于被扫描中标志信号
	wire R0_C1_act = R0_act & C1_act;	//第0行1列像素块处于被扫描中标志信号
	wire R1_C0_act = R1_act & C0_act;	//第1行0列像素块处于被扫描中标志信号
	wire R1_C1_act = R1_act & C1_act;	//第1行1列像素块处于被扫描中标志信号
	wire R2_C0_act = R2_act & C0_act;	//第2行0列像素块处于被扫描中标志信号
	wire R2_C1_act = R2_act & C1_act;	//第2行1列像素块处于被扫描中标志信号
	wire R3_C0_act = R3_act & C0_act;	//第3行0列像素块处于被扫描中标志信号
	wire R3_C1_act = R3_act & C1_act;	//第3行1列像素块处于被扫描中标志信号
	
	always@(*)
		case({R3_C1_act,R3_C0_act,R2_C1_act,R2_C0_act,
				R1_C1_act,R1_C0_act,R0_C1_act,R0_C0_act})
			8'b0000_0001:disp_data = R0_C0;
			8'b0000_0010:disp_data = R0_C1;
			8'b0000_0100:disp_data = R1_C0;
			8'b0000_1000:disp_data = R1_C1;
			8'b0001_0000:disp_data = R2_C0;
			8'b0010_0000:disp_data = R2_C1;
			8'b0100_0000:disp_data = R3_C0;
			8'b1000_0000:disp_data = R3_C1;
			default:disp_data = R0_C0;
		endcase
	
endmodule


  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:45:24  更:2021-08-15 15:47:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:39:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码