点亮你的LCD!(linux原子哥)

文章详细解释了RGBLCD的两种驱动模式DEHV,以及关键信号如HSYNC、VSYNC和PCLK的作用。通过比喻说明了HBP、HFP、VBP和VFP的概念,并介绍了LCDIF接口的重要寄存器配置,包括LCDIF_CTRL、LCDIF_CTRL1等,用于设置分辨率和同步信号。此外,还讨论了内联函数在代码优化中的作用。

首先是RGB接口

RGBLCD一般有两种驱动模式:DE HV 分别对应DE线与HSYNC线

解释一下:DE-DATA ENABLE数据使能 VSYNC-Vertical Synchronization垂直同步

HSYNC-Horizontal Synchronization水平同步 PCLK-Pixel CLK像素时钟

下面是很重要的一个功能示意图

我们将这个区域看成一个草坪,我们需要去做修理的任务,那么我们就得从左上角开始修剪,我们从左上角开始向右出发修建草坪,一直修剪到最右边的白色边框结束,那么在LCD扫描的技术里,我们需要返回到第二行最左边,那这个时候我们就要把除草机关掉,然后等我们回到第二行最左边才能打开,这就是黑边的作用。

(加粗!)我想到你把上面这张平面图卷起来,让最右边和最左边重合,这样,就像是地球一样,你在世界地图上从上海出发一路向右,最后绕了一圈到了西藏,从西藏到上海的时候就是黑边所在地方,这就是HBP与HFP:Horizontal Back Porch与Horizontal Front Porch,但是注意了这两个是Back在前面,Front在后面,为啥呢,应该是因为它的前后区分是通过信号产生的时间。

第一行HSYNC信号产生后初始化的时间是HBP,同步信号后肩,

第二行HSYNC信号产生前等待该信号产生的时间是HFP,同步信号前肩,

同理,引出参数VFP以及VBP。

酱紫的话我们就可以看得懂下面这张时序图了

则显示一行总时间是:HSPW + HBP + HOZVAL + HFP

同理,上图是帧同步信号,我个人认为是垂直的。

总的显示时间是 T = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)

那么我们显示一帧图像需要时钟数这样计算:

接着我们操作寄存器CCM_PLL_VIDEO对时钟频率进行设置

接下来我们重点阅读 eLCDIF接口的几个重要寄存器

1、LCDIF_CTRL的寄存器配置

2、寄存器LCDIF_CTRL1,只用到 BYTE_PACKING_FORMAT(bit19:16),此位用来决定在 32 位的数据中哪些字节的数据有效,默认值为 0XF,也就是所有的字节有效,当为 0 的话表示所有的字节都无效。如果显示的数据是24 位(ARGB 格式,但是 A 通道不传输)的话就设置此位为 0X7。

3、寄存器 LCDIF_TRANSFER_COUNT,控制分辨率大小

我使用的是4.3寸电容屏,分辨率800*480,那么V_COUNT 480,H_COUNT 800。

4、寄存器LCDIF_VDCTRL0,VSYNC和DOTCLK模式控制寄存器0

5、寄存器LCDIF_VDCTRL1,VSYNC和DOTCLK模式控制寄存器1,用来设置VSYNC的总周期:屏幕高度+VSPW+VBP+VFP。

6、寄存器LCDIF_VDCTRL2,VSYNC和DOTCLK模式控制寄存器2,高16位用来设置HSYNC信号宽度,即HSPW;低十六位用来设置HSYNC的总周期:屏幕宽度+HSPW+HBP+HFP。

7、寄存器LCDIF_VDCTRL3

8、寄存器LCDIF_CDCTRL4

9、寄存器 LCDIF_CUR_BUF 和 LCDIF_NEXT_BUF

在了解寄存器配置之后我们阅读代码,我挑选我个人感觉重要的代码着重进行解释

LCD的控制参数结构体

内联函数inline:(173条消息) 内联函数 —— C 中关键字 inline 用法解析_zqixiao_09的博客-优快云博客_c inline

我理解的是,内联函数类似于:你在学校上课,你的电脑在宿舍,但是你不能带电脑去学校,所以每当你在学校要用电脑的时候,你就得回宿舍去查,然后无论多少次你都要一次一次回去查,那你就累死了。

内联函数就相当于,你已经把宿舍连着电脑一起扛到教学楼旁边,这样你每次就不用回去了,但是因为这样你的教学楼膨胀了,变大了。

函数调用的本质其实是为了方便,为了减少代码的冗余,举个例子

void num_add()
{
    a++;b++;c++;d++;
}

void main()
{
    for()
    num_add();
}

这是正常的函数调用,但是在for中每次重复运行就要回去调用,那加入了inline修饰函数之后就相当于以下的效果

inline void num_add()
{
    a++;b++;c++;d++;
}

void main()
{
    for()
    a++;b++;c++;d++; 
}

就是inline仅仅是相当于帮你程序员减少了主函数里面的代码量(看起来),但是在实际运行起来,对于程序而言代码量增加了。好处是:栈空间就是指放置程式的局部数据也就是函数内数据的内存空间,在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足所造成的程式出错的问题,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。

划重点:在该程序中我们需要更改Makefile,在此处添加

CC := $(CROSS_COMPILE)gcc -fgnu89-inline

这个函数就是填充颜色函数,原理很简单,我们先找到要填充的点的地址,根据它在LCD屏幕上的位置来判断它是在哪里,接着用:显存首地址+像素大小*(LCD的长*纵坐标+横坐标)找到这个点在内存里的位置。

### 正点原子 3.5寸 LCD 屏幕点亮教程及代码实现 正点原子的开发板支持多种尺寸和类型的 LCD 显示屏,其中 3.5 寸 LCD点亮过程需要初始化硬件接口、配置液晶显示控制器(如 ILI9341),并完成基本的显示功能设置。以下是点亮 3.5 寸 LCD 屏幕的教程及示例代码。 #### 初始化硬件接口 在点亮 LCD 屏幕之前,需要对相关硬件接口进行初始化,包括延时函数、串口通信以及 LED 接口等。这些初始化操作确保了开发板与 LCD 模块之间的正常通信[^2]。 ```c void delay_init(void); void uart_init(u32 bound); void LED_Init(void); ``` 调用上述函数可以完成必要的硬件初始化工作。 #### 配置液晶显示控制器 正点原子的 3.5 寸 LCD 模块通常使用 ILI9341 控制器。该控制器支持多种总线模式,开发板默认配置为 8080 并口方式[^3]。以下是对 LCD 控制器的初始化代码: ```c void LCD_Init(void) { // 硬件复位 LCD_Reset(); // 写入初始化命令 LCD_WriteReg(0xEF, 0x03); LCD_WriteReg(0xEF, 0x83); LCD_WriteReg(0xEB, 0x16); // 设置屏幕方向 LCD_SetDirection(LCD_DIR_LANDSCAPE); // 打开显示 LCD_WriteReg(0x29, 0x00); } ``` 以上代码实现了对 ILI9341 控制器的基本配置,包括硬件复位、写入初始化命令以及设置屏幕方向等。 #### 显示颜色填充 在完成 LCD 初始化后,可以通过颜色填充来验证屏幕是否正常点亮。以下代码展示了如何清屏并填充指定颜色: ```c void LCD_Clear(u16 Color) { u16 i, j; LCD_SetWindows(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1); // 设置窗口大小 for(i = 0; i < LCD_HEIGHT; i++) { for(j = 0; j < LCD_WIDTH; j++) { LCD_DrawPoint(Color); // 绘制单个像素点 } } } ``` 通过调用 `LCD_Clear` 函数,可以将整个屏幕填充为指定的颜色,
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值