嵌入式学习-uboot-lesson14-LCD相关

2024-05-27 09:48

本文主要是介绍嵌入式学习-uboot-lesson14-LCD相关,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于LCD的相关知识在这里就不再说了,下面就直接开始对LCD进行编程分析。

一、硬件结构

这里写图片描述

这里写图片描述
根据上面两幅图可以得知,
1.LCD的VD[0:23]一共24个引脚,接在GPI[0:15],GPJ[0:7] 这24个IO口上,
2.GPJ[8:11]分别接LCD的:
GPJ8—-HSYNC:行(水平方向)同步信号
GPJ9—-VSYNC:场(垂直方向)同步信号
GPJ10—VDEN:video data enable 视频输入使能端
GPJ11—VCLK :像素之间时钟信号

因此需要对这些引脚进行配置,使之满足我们的需求。

二、编程流程

根据第一步,我们首先需要做的工作是:

1).配置引脚

同时,我们还需要对LCD的时序进行配置

2).设置LCD时序值

同时,还需要对在内存中专门开辟出来的framebuffer,进行初始化

3).帧缓存初始化

这里写图片描述

这里写图片描述
第二步和第三步的全部过程在上面两幅图中全部标了出来,下面我们只需根据上面的步骤进行编程即可

三、编程实现

1).配置引脚

这里写图片描述

这里写图片描述
根据上图需要将GPI寄存器的所有引脚配置为0b10模式
即:

#define GPICON           (*((volatile unsigned long*)0x7F008100)) //端口I 配置寄存器 GPICON = 0xaaaaaaaa;    //16个引脚都配置为0b10

这里写图片描述
这里写图片描述
根据上面两幅图,可知需要将GPJ[0:15] 和GPJ[16:23]都设置为ob10
即:

#define GPJCON           (*((volatile unsigned long*)0x7F008120)) //端口J 配置寄存器 
GPJCON = 0xaaaaaa;

2).设置LCD时序值和帧缓存初始化

1.MIFPCON 的第三位SEL_BYPASS为0(正常模式)

根据前面的步骤流程图可知,需要将其第三位设为0即可
这里写图片描述

#define MOFPCON          (*((volatile unsigned long*)0x7410800C)) //调制解调器接口控制寄存器
MOFPCON = 0<<3;

2.SPCON的LCD_SEL[1:0]位设置为01,表示使用 RGB I/F 类型

根据上面的步骤流程图,需要将SPCON的[1:0]位设置为0b01即可
这里写图片描述

这里写图片描述

#define SPCON            (*((volatile unsigned long*)0x7F0081A0)) //特殊端口控制寄存器   SPCON  &= ~(0x3);SPCON  |= 0x01;

3.VIDCON0:配置视频输出格式和显示使能/禁止

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

#define VIDCON0          (*((volatile unsigned long*)0x77100000)) //视频控制0 寄存器 
VIDCON0 &= ~((0x3<<26)| (0x3<<17) | (0x1<<16) | (0x3<<2)|(0<<5));

其中时钟源选择HCLK为133MHZ
VCLK=视频时钟源/(CLKVAL+1) 其中。根据4.3寸屏的手册,VCLK的典型值为9MHZ,经过计算,得CLKVAL大约等于14

这里写图片描述

这里写图片描述
这里写图片描述

VIDCON0 |= ((14<<6) | (1<<4)|(3<<0));

4VIDCON1 RGB控制信号

根据时序图,在VCLK的下降沿得到数据
这里写图片描述

这里写图片描述

这里写图片描述

#define VIDCON1          (*((volatile unsigned long*)0x77100004)) //视频控制1 寄存器VIDCON1 &= ~(1<<7);   VIDCON1 |= ((1<<6) | (1<<5));  

5VIDTCONx视频时序控制寄存器

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述
根据上面的几幅图,可以得出时序图:

5.1 VSPW

vspw+1=tvp=10 vspw=9

#define VSPW      9
5.2 VBPD

vbpd+1=tvb=2 vbpd=1

#define VBPD      1
5.3 LINEVAL

一共有272行,272-1=271

#define LINEVAL   272-1
5.4 VFPD

vfpd+1=tvf=2 vfpd=1

#define VFPD      1
5.5 HSPW

hspw+1=thp=41 hspw=40

#define HSPW      40
5.6 HBPD

hbpd+1=thb=2 hbpd=1

#define HBPD      1
5.7 HOZVAL

480-1=479

#define HOZVAL    480-1
5.8 HFPD

hfpd+1=thf=2 hfpd=1

#define HFPD      1

综合上面,即:

#define VSPW      9
#define VBPD      1
#define LINEVAL   272-1
#define VFPD      1
#define HSPW      40
#define HBPD      1
#define HOZVAL    480-1
#define HFPD      1#define VIDTCON0         (*((volatile unsigned long*)0x77100010)) //视频时序控制0寄存器
#define VIDTCON1         (*((volatile unsigned long*)0x77100014)) //视频时序控制1寄存器
#define VIDTCON2         (*((volatile unsigned long*)0x77100018)) //视频时序控制2寄存器VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0);VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0);VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

6WINCON0 窗口0控制寄存器

这里写图片描述

这里写图片描述

#define WINCON0          (*((volatile unsigned long*)0x77100020)) //窗口0 控制寄存器   WINCON0 &= ~(0xf << 2);WINCON0 |= (0xb<<2);WINCON0 = (1<<16)|(0xb<<2)|(1<<0);

7

这里写图片描述

这里写图片描述
VIDOSD0A:窗口 0 位置控制 A 寄存器
左上角X,Y坐标
VIDOSD0B:窗口 0 位置控制 B 寄存器
右下角XY坐标
VIDOSD0C:窗口 0 位置控制 C 寄存器
行数列数(1个像素24位,但是占据32位,即4个字节)
同时,单位为word 所以为272*480

#define VIDOSD0A         (*((volatile unsigned long*)0x77100040)) //视频窗口0 的位置控制寄存器
#define VIDOSD0B         (*((volatile unsigned long*)0x77100044)) //视频窗口0 的位置控制寄存器
#define VIDOSD0C         (*((volatile unsigned long*)0x77100048)) //视频窗口0 的位置控制寄存器
#define LeftTopX 0
#define LeftTopY 0
#define RightBotX 479
#define RigntBotY 271   
VIDOSD0A = (LeftTopX<<11) |(LeftTopY<<0);VIDOSD0B = (RightBotX<<11)|(RigntBotY<<0);VIDOSD0C = (LINEVAL+1)*(HOZVAL+1);

8

这里写图片描述

VIDW00ADD0B0 窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0
存放FRAME_BUFFER的基地址
VIDW00ADD0B1 窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1
VBASEL=VBASEU+(PAGEWIDTH+OFFSIZE)*(LINEVAL+1)=0+(480*4+0)*272
OFFSIZE:偏移值 从0开始

#define FRAME_BUFFER   0x54000000
#define VIDW00ADD0B0     (*((volatile unsigned long*)0x771000A0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0
#define VIDW00ADD1B0     (*((volatile unsigned long*)0x771000D0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1
VIDW00ADD0B0 = FRAME_BUFFER;
VIDW00ADD1B0 = (FRAME_BUFFER+((HOZVAL+1)*4+0)*(LINEVAL+1))&(0xffffff);  

通过以上步骤即可实现了LCD的初始化,下面将对其进行测试,观察是否出现正确的图像。

四、测试

这次主要的测试是通过在显示屏上显示一副图片来完成的,
在显示图片之前,需要先将屏幕清一下(可不做)

void lcd_clear()
{int x,y,color;for(x=0;x<272;x++)for(y=0;y<480;y++)point(x,y,0xFFFfff);        //WIN0MAP = (1<<24)|(color&0xffffff);
}

然后可以在屏幕上进行划线,或者将某个区域填充为纯色,具体代码如下

        //划横线 -> 描第201行,第y列for(y=100;y<380;y++)point(210,y,0xFF0000);  

随后,便可以将图片显示在LCD上

//x0,y0,x(高度),y(宽度) 272*480
Paint_Bmp(0,0,272,480,bmp);void Paint_Bmp(U16 x0,U16 y0,U16 x,U16 y,const unsigned char gImage_bmp[])
{int i, j;unsigned char *p = (unsigned char *)gImage_bmp;int blue, green, red;int color;// 图片大小200x200像素for (i = x0 ; i < x0 +x; i++)for (j = y0; j < y0 + y; j++){blue  = *p++;green = *p++;red   = *p++;// D[23:16] = Red data, D[15:8] = Green data,D[7:0] = Blue datacolor = (red << 16)| (green << 8)|( blue << 0); point(i, j, color);}
}

贴上图片:
稍后

贴上主要代码:

/********************************************
*file name: lcd.c
*author   : stone
*date     : 2016.7.11
*function : lcd的初始化及测试
*********************************************/#define GPICON           (*((volatile unsigned long*)0x7F008100)) //端口I 配置寄存器 
#define GPJCON           (*((volatile unsigned long*)0x7F008120)) //端口J 配置寄存器 
#define MOFPCON          (*((volatile unsigned long*)0x7410800C)) //调制解调器接口控制寄存器
#define SPCON            (*((volatile unsigned long*)0x7F0081A0)) //特殊端口控制寄存器
#define VIDCON0          (*((volatile unsigned long*)0x77100000)) //视频控制0寄存器 
#define VIDCON1          (*((volatile unsigned long*)0x77100004)) //视频控制1寄存器
#define VIDTCON0         (*((volatile unsigned long*)0x77100010)) //视频时序控制0寄存器
#define VIDTCON1         (*((volatile unsigned long*)0x77100014)) //视频时序控制1寄存器
#define VIDTCON2         (*((volatile unsigned long*)0x77100018)) //视频时序控制2寄存器
#define WINCON0          (*((volatile unsigned long*)0x77100020)) //窗口0 控制寄存器
#define VIDOSD0A         (*((volatile unsigned long*)0x77100040)) //视频窗口0 的位置控制寄存器
#define VIDOSD0B         (*((volatile unsigned long*)0x77100044)) //视频窗口0 的位置控制寄存器
#define VIDOSD0C         (*((volatile unsigned long*)0x77100048)) //视频窗口0 的位置控制寄存器
#define VIDW00ADD0B0     (*((volatile unsigned long*)0x771000A0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0
#define VIDW00ADD1B0     (*((volatile unsigned long*)0x771000D0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1#define WIN0MAP     (*((volatile unsigned long*)0x77100180))#define VSPW      9
#define VBPD      1
#define LINEVAL   272-1
#define VFPD      1
#define HSPW      40
#define HBPD      1
#define HOZVAL    480-1
#define HFPD      1#define LeftTopX 0
#define LeftTopY 0
#define RightBotX 479
#define RigntBotY 271#define FRAME_BUFFER   0x54000000
extern unsigned char bmp[391680];
typedef unsigned short U16;void lcd_port_init()
{GPICON = 0xaaaaaaaa;  //16个引脚都配置为0b10GPJCON = 0xaaaaaa;  
}void lcd_config_init()
{MOFPCON = 0<<3;SPCON  &= ~(0x3);SPCON  |= 0x01;VIDCON0 &= ~((0x3<<26)| (0x3<<17) | (0x1<<16) | (0x3<<2)|(0<<5));VIDCON0 |= ((14<<6) | (1<<4)|(3<<0));VIDCON1 &= ~(1<<7);   VIDCON1 |= ((1<<6) | (1<<5));  VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0);VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0);VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);WINCON0 &= ~(0xf << 2);WINCON0 |= (0xb<<2);WINCON0 = (1<<16)|(0xb<<2)|(1<<0);VIDOSD0A = (LeftTopX<<11) |(LeftTopY<<0);VIDOSD0B = (RightBotX<<11)|(RigntBotY<<0);VIDOSD0C = (LINEVAL+1)*(HOZVAL+1);  VIDW00ADD0B0 = FRAME_BUFFER;VIDW00ADD1B0 = (FRAME_BUFFER+((HOZVAL+1)*4+0)*(LINEVAL+1))&(0xffffff);  
}void point(int row, int col, int color)
{unsigned long *point = (unsigned long*)FRAME_BUFFER;*(point + row*480 + col) = color;
}void lcd_clear()
{int x,y,color;for(x=0;x<272;x++)for(y=0;y<480;y++)point(x,y,0xFFFfff);        //WIN0MAP = (1<<24)|(color&0xffffff);}
void Paint_Bmp(U16 x0,U16 y0,U16 x,U16 y,const unsigned char gImage_bmp[])
{int i, j;unsigned char *p = (unsigned char *)gImage_bmp;int blue, green, red;int color;// 图片大小200x200像素for (i = x0 ; i < x0 +x; i++)for (j = y0; j < y0 + y; j++){blue  = *p++;green = *p++;red   = *p++;// D[23:16] = Red data, D[15:8] = Green data,D[7:0] = Blue datacolor = (red << 16)| (green << 8)|( blue << 0); point(i, j, color);}
}/*void Paint_txt(U16 x0,U16 y0,U16 x,U16 y,const unsigned char gImage_bmp[])
{int i, j;unsigned char *p = (unsigned char *)gImage_bmp;int blue, green, red;int color;// 图片大小200x200像素for (i = x0 ; i < x0 +x; i++)for (j = y0; j < y0 + y; j++){//blue  = *p++;//green = *p++;//red   = *p++;// D[23:16] = Red data, D[15:8] = Green data,D[7:0] = Blue data//color = (red << 16)| (green << 8)|( blue << 0); color = *p;point(i, j, color);}
}*/void lcd_init()
{lcd_port_init();lcd_config_init();  
}void lcd_test()
{int y;lcd_clear();//划横线 -> 描第150行,第y列for(y=100;y<380;y++)point(210,y,0xFF0000);  //x0,y0,x(高度),y(宽度) 272*480Paint_Bmp(0,0,272,480,bmp);//Paint_txt(0,0,224,56,zi);}

菜鸟一枚,如有错误,多多指教。。。

这篇关于嵌入式学习-uboot-lesson14-LCD相关的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1007129

相关文章

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设