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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> S5PV210开发之1.0.14------LCD显示器 -> 正文阅读

[嵌入式]S5PV210开发之1.0.14------LCD显示器

目录

1. 什么是LCD

  1. LCD:液晶显示器、面板,不会主动发光,可以通过不同电信号让液晶分子进行选择性的透光,此时在液晶面板前面看到的就是各种各样不同的颜色,LCD面板的比较对象是TN IPS VA屏!
  2. LED:主动发光、背光、我们平时所说的“LED屏”,全称LED-backlit LCD,看见后面那个大大的LCD了吗?翻译成中文是LED背光液晶显示器。我们所说的LED也是指的他的背光
  3. OLED,Organic Light-Emitting Diode,中文全称有机发光二极管,是一种全新的显示技术,可弯曲,OLED屏幕为自发光屏幕,无需背光照明,与LCD屏幕有着本质区别。

2. LCD接口技术

  1. 采用TTL接口。
  2. SoC的LCD控制器硬件接口是TTL电平的,LCD这边硬件接口也是TTL电平的
  3. TTL电平的缺陷就是不能传递太远,如果LCD屏幕和主板控制器太远,就不能直接TTL连接,转换方式:主机SoC(TTL) ->VGA-> LCD屏幕(TTL)

在这里插入图片描述

3. RGB接口详解

  1. VD[23:0]:24根数据线,并行
  2. HSYNC:水平同步信号
  3. VSYNC:垂直同步信号:时序信号线,为了让LCD能够正常显示给的控制信号
  4. VCLK(像素时钟):LCD工作时需要主板控制器给LCD模组一个工作时钟信号,就是VCLK。
  5. VDEN:数据有效标志:时序信号,和HSYNC、VSYNC结合使用。
  6. LEND:行结束标志,不是必须的,时序信号,非必须,譬如X210接口就没有。
    在这里插入图片描述

4. LCD显示图像相关概念

  1. 像素pixel:是图像中最基本的元素、图像被操作的最小单位、可以是黑白(控制亮度)、可以是单色(控制亮、灭)、也可以是彩色
  2. 扫描:图像是一个像素一个像素扫描生成的,只是肉眼识别不出
  3. 驱动器:将控制器的数字信号转换成模拟信号发给LCD显示器、面板需要一定的模拟电信号来控制液晶分子
  4. 控制器:按时序发出数字信号、SoC会从内存中拿像素数据给LCD控制器并最终传给LCD驱动器。
  5. 显存:内存中的一块区域、先和LCD控制器建立映射、然后在显存中写入像素数据,然后就不需要关心LCD控制器、驱动器、LCD显示器,以后CPU就只关心显存了,因为我只要把要显示的图像的像素数据丢到显存中,硬件就会自动响应。
  6. 像素间距(pitch),连续2个像素的像素中心的距离。
  7. 分辨率:整个屏幕的横向和纵向的像素个数就叫分辨率,譬如X210开发板用的屏幕是800×480,分辨率不等于清晰度、
  8. 像素深度:一个像素在计算机中由多少个字节数据来描述,一般来说像素深度有这么几种:1位、8位、16位、24位、32位

5. LCD的六个主要时序参数

  1. LCD图像显示单位:帧,
  2. 帧内数据:一帧图像其实就是多个像素组成的矩阵。
  3. 帧外数据:整个视频由很多个帧构成,最终播放视频时逐个播放各个图像帧即可。
  4. 显示一帧图像其实是一个一个像素点显示的过程

6个主要时序参数:

HSPW 水平同步信号脉宽、HBPD 水平同步信号前肩、HFPD 水平同步信号后肩

VSPW 垂直同步信号脉宽、VBPD 垂直同步信号前肩、VFPD 垂直同步信号后肩、

  1. 前三个H开头的信号为一组横向的时序信号、HSPW告诉驱动器要发信息了,HBPD、HFPD调整时间,纵向V开头的信号同理。一行总共包含4部分:HSPW+HBPD+有效行信息+HFPD。
  2. 一帧图像其实就是一列,一列图像由多个行组成,每行都是上面讲的这个时序。
  3. 一帧图像的通信过程是这样的:整个帧图像信号分为4部分:VSPW+VBPD+帧有效信号+VFPD。VSPW是帧同步信号宽度,用来告诉驱动器一帧图像要开始了;VBPD和VFPD分别是垂直同步信号前后肩。

在这里插入图片描述
这些参数都是LCD本身的、与LCD控制器无关、这些参数大小来自LCD厂家提供的示例代码。

在这里插入图片描述
补充:H开头的三个单位都是DCLK(像素时钟),V开头的三个单位是TH。这样设置的好处是我们改变了像素时钟的设置时,不用改变这里的时序参数。

6. 颜色在计算机中的表示

  1. 自然光颜色连续、计算机颜色离散,当离散点足够多、颜色就足够丰富。
  2. 像素深度bpp与颜色丰富性有直接关系。
  3. 像素深度解析:

1位:0/1只能控制单色的亮灭

8位:2^8有256种颜色,灰度显示。没有彩色,我们把纯白到纯黑分别对应255到0,中间的数值对应不同的灰。

16位:用16个二进制位表示颜色,此时能表示65536种颜色。这时候就可以彩色显示了,一般是RGB565的颜色分布(用5位二进制表示红色、用6位二进制表示绿色、用5位二进制表示蓝色),失真严重。

24位:用24个二进制位来表示颜色,此时能表示16777216种颜色。这种表示方式和16位色原理是一样的,只是RGB三种颜色各自的精度都更高了(RGB各8位),叫RGB888。

32位:总共用32位二进制来表示颜色,其中24位表示红绿蓝三元色(还是RGB888分布),剩下8位表示透明度。这种显色方式就叫ARGB(A是阿尔法,表示透明度),现在PC机中一般都用ARGB表示颜色。

7. S5PV210的LCD控制器

  1. 数据手册:
    在这里插入图片描述
    时钟:AHB
    外部接口选择:RGB

  2. 虚拟屏幕:在这里插入图片描述
    开发板支持5个虚拟屏幕、每个虚拟屏幕对应信息保留在显存中

  3. 虚拟显示:
    作用:需要显示的图片的分辨率大于屏幕支持的分辨率,先将整个大图片的像素信息以全部存放在显存中,然后让LCD去对应其中的一部分区域作为有效的显示区域,这个就叫虚拟显示
    编程时,通过改变屏幕左上角的位置、来改变显示的图片、不需要额外写内存操作

在这里插入图片描述

8. 编程实战

LCD初始化代码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include "main.h"

#define GPF0CON			(*(volatile unsigned long *)0xE0200120)
#define GPF1CON			(*(volatile unsigned long *)0xE0200140)
#define GPF2CON			(*(volatile unsigned long *)0xE0200160)
#define GPF3CON			(*(volatile unsigned long *)0xE0200180)

#define GPD0CON			(*(volatile unsigned long *)0xE02000A0)
#define GPD0DAT			(*(volatile unsigned long *)0xE02000A4)

#define CLK_SRC1		(*(volatile unsigned long *)0xe0100204)
#define CLK_DIV1		(*(volatile unsigned long *)0xe0100304)
#define DISPLAY_CONTROL	(*(volatile unsigned long *)0xe0107008)

#define VIDCON0			(*(volatile unsigned long *)0xF8000000)
#define VIDCON1			(*(volatile unsigned long *)0xF8000004)
#define VIDTCON2		(*(volatile unsigned long *)0xF8000018)
#define WINCON0 		(*(volatile unsigned long *)0xF8000020)
#define WINCON2 		(*(volatile unsigned long *)0xF8000028)
#define SHADOWCON 		(*(volatile unsigned long *)0xF8000034)
#define VIDOSD0A 		(*(volatile unsigned long *)0xF8000040)
#define VIDOSD0B 		(*(volatile unsigned long *)0xF8000044)
#define VIDOSD0C 		(*(volatile unsigned long *)0xF8000048)

#define VIDW00ADD0B0 	(*(volatile unsigned long *)0xF80000A0)
#define VIDW00ADD1B0 	(*(volatile unsigned long *)0xF80000D0)

#define VIDTCON0 		(*(volatile unsigned long *)0xF8000010)
#define VIDTCON1 		(*(volatile unsigned long *)0xF8000014)

#define HSPW 			(40)				// 1~40 DCLK
#define HBPD			(10 - 1)			// 46
#define HFPD 			(240 - 1)			// 16 210 354
#define VSPW			(20)				// 1~20 DCLK
#define VBPD 			(10 - 1)			// 23
#define VFPD 			(30 - 1)			// 7 22 147

// FB地址
#define FB_ADDR			(0x23000000)
#define ROW				(480)
#define COL				(800)
#define HOZVAL			(COL-1)
#define LINEVAL			(ROW-1)

#define XSIZE			COL
#define YSIZE			ROW


// 初始化LCD
void lcd_init(void)
{
	// 配置引脚用于LCD功能,LCD控制器连接的引脚要配置好工作模式、因为引脚复用,凡是有引脚的都要设置GPIO的工作模式。GPF0-GPF3都是如此
	
	GPF0CON = 0x22222222;
	GPF1CON = 0x22222222;
	GPF2CON = 0x22222222;
	GPF3CON = 0x22222222;

	// 打开背光	GPD0_0(PWMTOUT0)
	GPD0CON &= ~(0xf<<0);
	GPD0CON |= (1<<0);	// 输出模式
	GPD0DAT &= ~(1<<0);	// output 0 to enable backlight
将GPDODAT寄存器的bit[0]0,就是GPDO_0输出低电平

	// 10: RGB=FIMD I80=FIMD ITU=FIMD
	DISPLAY_CONTROL = 2<<0;

	// bit[26~28]:使用RGB接口 写100
	// bit[18]:RGB 并行 写0
	// bit[2]:选择时钟源为HCLK_DSYS=166MHz 写0
	VIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );

	// bit[1]:使能lcd控制器
	// bit[0]:当前帧结束后使能lcd控制器
	VIDCON0 |= ( (1<<0)|(1<<1) );

	// bit[6]:选择需要分频
	// bit[6~13]:分频系数为5,即VCLK(像素时钟) = 166M/(4+1) = 33M
	VIDCON0 |= 4<<6 | 1<<4;


	// H43-HSD043I9W1.pdf(p13) 时序图:VSYNC和HSYNC都是低脉冲
	// s5pv210芯片手册(p1207) 时序图:VSYNC和HSYNC都是高脉冲有		效,所以需要反转
	VIDCON1 |= 1<<5 | 1<<6;

//以上的VIDCON1设置控制器内部的一些时钟、分频、接口类型RGB等等

	// 设置时序 横+竖
	VIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;
	VIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;
	// 设置长宽(物理屏幕)
	VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);
//以上的VIDTCONn设置一些和时序、长宽、这类设计到具体的数据。 

	// 设置window0,只使用虚拟屏幕0
	// bit[0]:使能
	// bit[2~5]:24bpp(RGB888)
	WINCON0 |= 1<<0;
	WINCON0 &= ~(0xf << 2);
	WINCON0 |= (0xB<<2) | (1<<15);

	#define LeftTopX     0
	#define LeftTopY     0
	#define RightBotX   799
	#define RightBotY   479

	// 设置window0的上下左右
	// 设置的是window0这个虚拟屏幕的所需要的显存空间的大小
	VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);
	VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);

	//设置的是需要显出来的大小
	VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);


	// 设置fb的地址,帧缓存地址寄存器、就是一帧图片数据所需要写入的内存中的显存的地址,初始化要指定好地址
	VIDW00ADD0B0 = FB_ADDR;
	VIDW00ADD1B0 = (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);
	//一行的像素个数*4(采用RGB888,一个像素3字节但是4字节对齐)

	// 使能channel 0传输数据
	SHADOWCON = 0x1;
}

在这里插入图片描述

demo1:用一种颜色填充屏幕

RGB,全1为白,全0为黑
#define BLUE	0x0000FF 
#define RED		0xFF0000
#define GREEN	0x00FF00
#define WHITE	0xFFFFFF


// 在像素点(x, y)处填充为color颜色
static inline void lcd_draw_pixel(u32 x, u32 y, u32 color)
{
	*(pfb + COL * y + x) = color;
}


// 把整个屏幕全部填充成一个颜色color
static void lcd_draw_background(u32 color)
{
	u32 i, j;
	
	for (j=0; j<ROW; j++)
	{
		for (i=0; i<COL; i++)
		{
			lcd_draw_pixel(i, j, color);
		}
	}
}

static void delay(void)
{
	volatile u32 i, j;
	for (i=0; i<4000; i++)
		for (j=0; j<1000; j++);
}

void lcd_test(void)
{
	lcd_init();
	

// 测试绘制背景色,成功
	while (1)
	{
		lcd_draw_background(RED);
		delay();
		
		lcd_draw_background(GREEN);
		delay();
		
		lcd_draw_background(BLUE);
		delay();
	}

}

demo2:画横线、竖线

// 绘制横线,起始坐标为(x1, y)到(x2, y),颜色是color
static void lcd_draw_hline(u32 x1, u32 x2, u32 y, u32 color)
{
	u32 x;
	
	for (x = x1; x<x2; x++)
	{
		lcd_draw_pixel(x, y, color);
	}
}

// 绘制竖线,起始坐标为(x, y1)到(x, y2),颜色是color
static void lcd_draw_vline(u32 x, u32 y1, u32 y2, u32 color)
{
	u32 y;
	
	for (y = y1; y<y2; y++)
	{
		lcd_draw_pixel(x, y, color);
	}
}

在这里插入图片描述

demo3:写字符、字符串

// 写字
// 写字的左上角坐标(x, y),字的颜色是color,字的字模信息存储在data中
static void show_8_16(unsigned int x, unsigned int y, unsigned int color, unsigned char *data)  
{  
// count记录当前正在绘制的像素的次序
    int i, j, count = 0;  
	  
    for (j=y; j<(y+16); j++)  
    {  
        for (i=x; i<(x+8); i++)  
        {  
            if (i<XSIZE && j<YSIZE)  
            {  
			// 在坐标(i, j)这个像素处判断是0还是1,如果是1写color;如果是0直接跳过
			data是想要写的字符以数组方式存储的字符模
            	if (data[count/8] & (1<<(count%8)))   
					lcd_draw_pixel(i, j, color);
            }  
            count++;  
        }  
    }  
} 


// 写字符串
// 字符串起始坐标左上角为(x, y),字符串文字颜色是color,字符串内容为str
void draw_ascii_ok(unsigned int x, unsigned int y, unsigned int color, unsigned char *str)
{
	int i;  
	unsigned char *ch;
    for (i=0; str[i]!='\0'; i++)  
    {  
		ch = (unsigned char *)ascii_8_16[(unsigned char)str[i]-0x20];
        show_8_16(x, y, color, ch); 
		
        x += 8;
		if (x >= XSIZE)
		{
			x -= XSIZE;			// 回车
			y += 16;			// 换行
		}
    }  
}

demo4:画图

// 画800×480的图,图像数据(颜色数据)存储在pData所指向的数组中

void lcd_draw_picture(const unsigned char *pData)
{
	u32 x, y, color, p = 0;
	
	for (y=0; y<480; y++)
	{
		for (x=0; x<800; x++)
		{
			// 在这里将坐标点(x, y)的那个像素填充上相应的颜色值即可
			color = (pData[p+0] << 0) | (pData[p+1] << 8) | (pData[p+2] << 16);
//RGB888
			lcd_draw_pixel(x, y, color);
			p += 3;
		}
	}
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 14:15:39  更:2021-09-27 14:18:27 
 
开发: 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/26 3:20:28-

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