RGBLCD显示实验————复习到这

2023-10-27

LCD 液晶屏是常用到的外设,通过LCD 可以显示绚丽的图形、界面等,提高人机交互的效率。I.MX6U 提供了一个eLCDIF 接口用于连接RGB 接口的液晶屏。本章我们就学习如何驱动RGB 接口液晶屏,并且在屏幕上显示字符。

LCD 和eLCDIF 简介

LCD 简介

LCD 全称是Liquid Crystal Display,也就是液晶显示器,是现在最常用到的显示器,手机、电脑、各种人机交互设备等基本都用到了LCD,最常见就是手机和电脑显示器了。由于笔者不是LCD 从业人员,对于LCD 的具体原理不了解,百度百科对于LCD 的原理解释如下:

LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置TFT(薄膜晶体管),上基板玻璃上设置彩色滤光片,通过TFT 上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。

我们现在要在I.MX6U-ALPHA 开发板上使用LCD,所以不需要去研究LCD 的具体实现原理,我们只需要从使用的角度去关注LCD 的几个重要点:

1、分辨率
提起LCD 显示器,我们都会听到720P、1080P、2K 或4K 这样的字眼,这个就是LCD 显示器分辨率。LCD 显示器都是由一个一个的像素点组成,像素点就类似一个灯(在OLED 显示器中,像素点就是一个小灯),这个小灯是RGB 灯,也就是由R(红色)、G(绿色)和B(蓝色)这三种颜色组成的,而RGB 就是光的三原色。1080P 的意思就是一个LCD 屏幕上的像素数量是1920*1080 个,也就是这个屏幕一列1080 个像素点,一共1920 列,如图24.1.1.1 所示:
在这里插入图片描述

在图24.1.1.1 就是1080P 显示器的像素示意图,X 轴就是LCD 显示器的横轴,Y 轴就是显示器的竖轴。图中的小方块就是像素点,一共有19201080=2073600 个像素点。左上角的A 点是第一个像素点,右下角的C 点就是最后一个像素点。2K 就是25601440 个像素点,4K 是3840*2160 个像素点。很明显,在LCD 尺寸不变的情况下,分辨率越高越清晰。同样的,分辨率不变的情况下,LCD 尺寸越小越清晰。比如我们常用的24 寸显示器基本都是1080P 的,而我们现在使用的5 寸的手机基本也是1080P 的,但是手机显示细腻程度就要比24 寸的显示器要好很多!

由此可见,LCD 显示器的分辨率是一个很重要的参数,但是并不是分辨率越高的LCD 就越好。衡量一款LCD 的好坏,分辨率只是其中的一个参数,还有色彩还原程度、色彩偏离、亮度、可视角度、屏幕刷新率等其他参数。

2、像素格式
上面讲了,一个像素点就相当于一个RGB 小灯,通过控制R、G、B 这三种颜色的亮度就可以显示出各种各样的色彩。那该如何控制R、G、B 这三种颜色的显示亮度呢?一般一个R、G、B 这三部分分别使用8bit 的数据,那么一个像素点就是8bit*3=24bit,也就是说一个像素点3 个字节,这种像素格式称为RGB888。如果再加入8bit 的Alpha(透明)通道的话一个像素点就是32bit,也就是4 个字节,这种像素格式称为ARGB8888。如果学习过STM32 的话应该还听过RGB565 这种像素格式,在本章实验中我们使用ARGB8888 这种像素格式,一个像素占用4个字节的内存,这四个字节每个位的分配如图24.1.1.2 所示:

在这里插入图片描述
在图24.1.1.2 中,一个像素点是4 个字节,其中bit31~bit24 是Alpha 通道,bit23~bit16 是RED 通道,bit15~bit14 是GREEN 通道,bit7~bit0 是BLUE 通道。所以红色对应的值就是0X00FF0000,蓝色对应的值就是0X000000FF,绿色对应的值为0X0000FF00。通过调节R、G、B 的比例可以产生其它的颜色,比如0X00FFFF00 就是黄色,0X00000000 就是黑色,0X00FFFFFF
就是白色。大家可以打开电脑的“画图”工具,在里面使用调色板即可获取到想要的颜色对应的数值,如图24.1.1.3 所示:
在这里插入图片描述
3、LCD 屏幕接口

LCD 屏幕或者说显示器有很多种接口,比如在显示器上常见的VGA、HDMI、DP 等等,但是I.MX6U-ALPHA开发板不支持这些接口。I.MX6U-ALPHA 支持RGB 接口的LCD,RGBLCD接口的信号线如表24.1.1.1 所示:

信号线 描述
R[7:0] 8 根红色数据线。
G[7:0] 8 根绿色数据线。
B[7:0] 8 根蓝色数据线。
DE 数据使能线。
VSYNC 垂直同步信号线。
HSYNC 水平同步信号线。
PCLK 像素时钟信号线。

表24.1.1.1 就是RGBLCD 的信号线,R[7:0]、G[7:0]和B[7:0]这24 根是数据线,DE、VSYNC、HSYNC 和PCLK 这四根是控制信号线。RGB LCD 一般有两种驱动模式:DE 模式和HV 模式,这两个模式的区别是DE 模式需要用到DE 信号线,而HV 模式不需要用到DE 信号线,在DE模式下是可以不需要HSYNC 信号线的,即使不接HSYNC 信号线LCD 也可以正常工作。

ALIENTEK 一共有三款RGB LCD 屏幕,型号分别为:ATK-4342(4.3 寸,480272)、ATK-7084(7 寸,800480)和ATK-7016(7 寸,1024*600),本教程就以ATK-7016 这款屏幕为例讲解,ATK-7016 的屏幕接口原理图如图24.1.1.4 所示:
在这里插入图片描述
图中J1 就是对外接口,是一个40PIN 的FPC 座(0.5mm 间距),通过FPC 线,可以连接到I.MX6U-ALPHA 开发板上面,从而实现和I.MX6U 的连接。该接口十分完善,采用RGB888格式,并支持DE&HV 模式,还支持触摸屏和背光控制。右侧的几个电阻,并不是都焊接的,而是可以用户自己选择。默认情况,R1 和R6 焊接,设置LCD_LR 和LCD_UD,控制LCD 的扫描方向,是从左到右,从上到下(横屏看)。而LCD_R7/G7/B7 则用来设置LCD 的ID,由于RGBLCD 没有读写寄存器,也就没有所谓的ID,这里我们通过在模块上面,控制R7/G7/B7 的上/下拉,来自定义LCD 模块的ID,帮助MCU 判断当前LCD 面板的分辨率和相关参数,以提高程序兼容性。这几个位的设置关系如表24.1.1.2 所示:

M2 LCD_G7 M1 LCD_G7 M0 LCD_R7 LCD ID 说明
0 0 0 4342 ATK-4342 RGBLCD 模块,分辨率:480*272
0 0 1 7084 ATK-7084 RGBLCD 模块,分辨率:800*480
0 1 0 7016 ATK-7016,RGBLCD 模块,分辨率:1024 * 600
1 0 0 4384 ATK-4384,RGBLCD 模块,分辨率:800*480
X X X NC 暂时未用到

ATK-7016 模块,就设置M2:M0=010 即可。这样,我们在程序里面,读取LCD_R7/G7/B7,得到M0:M2 的值,从而判断RGBLCD 模块的型号,并执行不同的配置,即可实现不同LCD 模块的兼容。

4、LCD 时间参数
如果将LCD 显示一帧图像的过程想象成绘画,那么在显示的过程中就是用一根“笔”在不同的像素点画上不同的颜色。这根笔按照从左至右、从上到下的顺序扫描每个像素点,并且在像素画上对应的颜色,当画到最后一个像素点的时候一幅图像就绘制好了。假如一个LCD 的分辨率为1024*600,那么其扫描如图24.1.1.5 所示:
在这里插入图片描述

结合图24.1.1.5 我们来看一下LCD 是怎么扫描显示一帧图像的。一帧图像也是由一行一行组成的。HSYNC 是水平同步信号,也叫做行同步信号,当产生此信号的话就表示开始显示新的一行了,所以此信号都是在图24.1.1.5 的最左边。当VSYNC 信号是垂直同步信号,也叫做帧同步信号,当产生此信号的话就表示开始显示新的一帧图像了,所以此信号在图24.1.1.5 的左上角。

在图24.1.1.5 可以看到有一圈“黑边”,真正有效的显示区域是中间的白色部分。那这一圈“黑边”是什么东西呢?这就要从显示器的“祖先”CRT 显示器开始说起了,CRT 显示器就是以前很常见的那种大屁股显示器,在2019 年应该很少见了,如果在农村应该还是可以见到的。CRT 显示器屁股后面是个电子枪,这个电子枪就是我们上面说的“画笔”,电子枪打出的电子撞击到屏幕上的荧光物质使其发光。只要控制电子枪从左到右扫完一行(也就是扫描一行),然后从上到下扫描完所有行,这样一帧图像就显示出来了。也就是说,显示一帧图像电子枪是按照‘Z’形在运动,当扫描速度很快的时候看起来就是一幅完成的画面了。

当显示完一行以后会发出HSYNC 信号,此时电子枪就会关闭,然后迅速的移动到屏幕的左边,当HSYNC 信号结束以后就可以显示新的一行数据了,电子枪就会重新打开。在HSYNC信号结束到电子枪重新打开之间会插入一段延时,这段延时就图24.1.1.5 中的HBP。当显示完一行以后就会关闭电子枪等待HSYNC 信号产生,关闭电子枪到HSYNC 信号产生之间会插入一段延时,这段延时就是图24.1.1.5 中的HFP 信号。同理,当显示完一帧图像以后电子枪也会关闭,然后等到VSYNC 信号产生,期间也会加入一段延时,这段延时就是图24.1.1.5 中的VFP。VSYNC 信号产生,电子枪移动到左上角,当VSYNC 信号结束以后电子枪重新打开,中间也会加入一段延时,这段延时就是图24.1.1.5 中的VBP。

HBP、HFP、VBP 和VFP 就是导致图24.1.1.5 中黑边的原因,但是这是CRT 显示器存在黑边的原因,现在是LCD 显示器,不需要电子枪了,那么为何还会有黑边呢?这是因为RGB LCD屏幕内部是有一个IC 的,发送一行或者一帧数据给IC,IC 是需要反应时间的。通过这段反应时间可以让IC 识别到一行数据扫描完了,要换行了,或者一帧图像扫描完了,要开始下一帧图像显示了。因此,在LCD 屏幕中继续存在HBP、HFP、VPB 和VFP 这四个参数的主要目的是为了锁定有效的像素数据。这四个时间是LCD 重要的时间参数,后面编写LCD 驱动的时候要用到的,至于这四个时间参数具体值是多少,那要需要去查看所使用的LCD 数据手册了。

5、RGB LCD 屏幕时序
上面讲了行显示和帧显示,我们来看一下行显示对应的时序图,如图24.1.1.6 所示:

在这里插入图片描述
图24.1.1.6 就是RGB LCD 的行显示时序,我们来分析一下其中重要的几个参数:

HSYNC:行同步信号,当此信号有效的话就表示开始显示新的一行数据,查阅所使用的LCD 数据手册可以知道此信号是低电平有效还是高电平有效,假设此时是低电平有效。

HSPW:有些地方也叫做thp,是HSYNC 信号宽度,也就是HSYNC 信号持续时间。HSYNC信号不是一个脉冲,而是需要持续一段时间才是有效的,单位为CLK。

HBP:有些地方叫做thb,前面已经讲过了,术语叫做行同步信号后肩,单位是CLK。

HOZVAL:有些地方叫做thd,显示一行数据所需的时间,假如屏幕分辨率为1024*600,那么HOZVAL 就是1024,单位为CLK。

HFP:有些地方叫做thf,前面已经讲过了,术语叫做行同步信号前肩,单位是CLK。

当HSYNC 信号发出以后,需要等待HSPW+HBP 个CLK 时间才会接收到真正有效的像素数据。当显示完一行数据以后需要等待HFP 个CLK 时间才能发出下一个HSYNC 信号,所以显示一行所需要的时间就是:HSPW + HBP + HOZVAL + HFP。

一帧图像就是由很多个行组成的,RGB LCD 的帧显示时序如图24.1.1.7 所示:
在这里插入图片描述
图24.1.1.7 就是RGB LCD 的帧显示时序,我们来分析一下其中重要的几个参数:
VSYNC:帧同步信号,当此信号有效的话就表示开始显示新的一帧数据,查阅所使用的LCD 数据手册可以知道此信号是低电平有效还是高电平有效,假设此时是低电平有效。

VSPW:有些地方也叫做tvp,是VSYNC 信号宽度,也就是VSYNC 信号持续时间,单位为1 行的时间。

VBP:有些地方叫做tvb,前面已经讲过了,术语叫做帧同步信号后肩,单位为1 行的时间。

LINE:有些地方叫做tvd,显示一帧有效数据所需的时间,假如屏幕分辨率为1024*600,那么LINE 就是600 行的时间。

VFP:有些地方叫做tvf,前面已经讲过了,术语叫做帧同步信号前肩,单位为1 行的时间。

显示一帧所需要的时间就是:VSPW+VBP+LINE+VFP 个行时间,最终的计算公式:

T = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)

因此我们在配置一款RGB LCD 的时候需要知道这几个参数:HOZVAL(屏幕有效宽度)、LINE(屏幕有效高度)、HBP、HSPW、HFP、VSPW、VBP 和VFP。ALIENTEK 三款RGB LCD屏幕的参数如表24.1.1.3 所示:
在这里插入图片描述
在这里插入图片描述

6、像素时钟
像素时钟就是RGB LCD 的时钟信号,以ATK7016 这款屏幕为例,显示一帧图像所需要的时钟数就是:

= (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)
= (3 + 20 + 600 + 12) * (20 + 140 + 1024 + 160)
= 635 * 1344
= 853440。

显示一帧图像需要853440 个时钟数,那么显示60 帧就是:853440 * 60 = 51206400≈51.2M,所以像素时钟就是51.2MHz。

I.MX6U 的eLCDIF 接口时钟图如图24.1.1.8 所示:
在这里插入图片描述
①、此部分是一个选择器,用于选择哪个PLL 可以作为LCDIF 时钟源,由寄存器CCM_CSCDR2 的位LCDIF1_PRE_CLK_SEL(bit17:15)来决定,LCDIF1_PRE_CLK_SEL 选择设置如表24.1.1.4 所示:

时钟源
0 PLL2 作为LCDIF 的时钟源。
1 PLL3_PFD3 作为LCDIF 的时钟源。
2 PLL5 作为LCDIF 的时钟源。
3 PLL2_PFD0 作为LCDIF 的时钟源。
4 PLL2_PFD1 作为LCDIF 的时钟源。
5 PLL3_PFD1 作为LCDIF 的时钟源。

在第16 章讲解I.MX6U 时钟系统的时候说过有个专用的PLL5 给VIDEO 使用,所以LCDIF1_PRE_CLK_SEL 设置为2。

②、此部分是LCDIF 时钟的预分频器,由寄存器CCM_CSCDR2 的位LCDIF1_PRED 来决定预分频值。可设置值为0~ 7,分别对应1~8 分频。

③、此部分进一步分频,由寄存器CBCMR 的位LCDIF1_PODF 来决定分频值。可设置值为0~ 7,分别对应1~8 分频。

④、此部分是一个选择器,选择LCDIF 最终的根时钟,由寄存器CSCDR2 的位LCDIF1_CLK_SEL 决定,LCDIF1_CLK_SEL 选择设置如表24.1.1.5 所示:

时钟源
0 前面复用器出来的时钟,也就是前面PLL5 出来的时钟作为LCDIF 的根时钟。
1 ipp_di0_clk 作为LCDIF 的根时钟。
2 ipp_di1_clk 作为LCDIF 的根时钟。
3 ldb_di0_clk 作为LCDIF 的根时钟。
4 ldb_di1_clk 作为LCDIF 的根时钟。

这里肯定选择PLL5 出来的那一路时钟作为LCDIF 的根时钟,因此LCDIF1_CLK_SEL 设置为0。LCDIF 既然选择了PLL5 作为时钟源,那么还需要初始化PLL5,LCDIF 的时钟是由PLL5 和图24.1.1.8 中的②、③这两个分频值决定的,所以需要对这三个进行合理的设置以搭配出所需的时钟值,我们就以ATK7016 屏幕所需的51.2MHz 为例,看看如何进行配置。

PLL5 频率设置涉及到四个寄存器:CCM_PLL_VIDEO 、CCM_PLL_VIDEO_NUM 、CCM_PLL_VIDEO_DENOM 、CCM_MISC2 。其中CCM_PLL_VIDEO_NUM 和CCM_PLL_VIDEO_DENOM 这两个寄存器是用于小数分频的,我们这里为了简单不使用小数分频,因此这两个寄存器设置为0。

PLL5 的时钟计算公式如下:

PLL5_CLK = OSC24M * (loopDivider + (denominator / numerator)) / postDivider

不使用小数分频的话PLL5 时钟计算公式就可以简化为:
PLL5_CLK = OSC24M * loopDivider / postDivider

OSC24M 就是24MHz 的有源晶振,现在的问题就是设置loopDivider 和postDivider。先来看一下寄存器CCM_PLL_VIDEO,此寄存器结构如图24.1.1.9 所示:
在这里插入图片描述

寄存器CCM_PLL_VIDEO 用到的重要的位如下:

POST_DIV_SLECT(bit20:19):此位和寄存器CCM_ANALOG_CCMSC2 的VIDEO_DIV 位共同决定了postDivider,为0 的话是4 分频,为1 的话是2 分频,为2 的话是1 分频。本章设置为2,也就是1 分频。

ENABLE(bit13):PLL5(PLL_VIDEO)使能位,为1 的话使能PLL5,为0 的话关闭PLL5。

DIV_SELECT(bit6:0):loopDivider 值,范围为27~54,本章设置为32。

寄存器CCM_ANALOG_MISC2 的位VIDEO_DIV(bit31:30)与寄存器CCM_PLL_VIDEO 的位POST_DIV_SLECT(bit20:19)共同决定了postDivider,通过这两个的配合可以获得2、4、8、16 分频。本章将VIDEO_DIV 设置为0,也就是1 分频,因此postDivider 就是1,loopDivider
设置为32,PLL5 的时钟频率就是:

PLL5_CLK = OSC24M * loopDivider / postDivider
= 24M * 32 / 1
= 768MHz。

PLL5 此时为768MHz,在经过图24.1.1.8 中的②和③进一步分频,设置②中为3 分频,也就是寄存器CCM_CSCDR2 的位LCDIF1_PRED(bit14:12)为2。设置③中为5 分频,就是寄存器CCM_CBCMR 的位LCDIF1_PODF(bit25:23)为4。设置好以后最终进入到LCDIF 的时钟频率就是:768/3/5 =51.2MHz,这就是我们需要的像素时钟频率。

7、显存

在讲像素格式的时候就已经说过了,如果采用ARGB8888 格式的话一个像素需要4 个字节的内存来存放像素数据,那么1024 * 600 分辨率就需要1024 * 600 * 4=2457600B ≈ 2.4MB 内存。但是RGB LCD 内部是没有内存的,所以就需要在开发板上的DDR3 中分出一段内存作为RGB LCD 屏幕的显存,我们如果要在屏幕上显示什么图像的话直接操作这部分显存即可。

eLCDIF 接口

eLCDIF 是I.MX6U 自带的液晶屏幕接口,用于连接RGB LCD 接口的屏幕,eLCDIF 接口特性如下:

①、支持RGB LCD 的DE 模式。
②、支持VSYNC 模式以实现高速数据传输。
③、支持ITU-R BT.656 格式的4:2:2 的YCbCr 数字视频,并且将其转换为模拟TV 信号。
④、支持8/16/18/24/32 位LCD。

eLCDIF 支持三种接口:MPU 接口、VSYNC 接口和DOTCLK 接口,这三种接口区别如下:

1、MPU 接口
MPU 接口用于在I.MX6U 和LCD 屏幕直接传输数据和命令,这个接口用于6080/8080 接口的LCD 屏幕,比如我们学习STM32 的时候常用到的MCU 屏幕。如果寄存器LCDIF_CTRL的位DOTCLK_MODE、DVI_MODE 和VSYNC_MODE 都为0 的话就表示LCDIF 工作在MPU接口模式。关于MPU 接口的详细信息以及时序参考《I.MX6ULL 参考手册》第2150 页的“34.4.6 MPU Interface”小节,本教程不使用MPU 接口。

2、VSYNC 接口
VSYNC 接口时序和MPU 接口时序基本一样,只是多了VSYNC 信号来作为帧同步,当LCDIF_CTRL 的位VSYNC_MODE 为1 的时候此接口使能。关于VSYNC 接口的详细信息请参考《I.MX6ULL 参考手册》第2152 页的“34.4.7 VSYNC Interface”小节,本教程不使用VSYNC接口。

3、DOTCLK 接口
DOTCLK 接口就是用来连接RGB LCD 接口屏幕的,它包括VSYNC、HSYNC、DOTCLK和ENABLE(可选的)这四个信号,这样的接口通常被称为RGB 接口。DOTCLK 接口时序如图24.1.2.1 所示:
在这里插入图片描述
图24.1.2.1 是不是和图24.1.1.6、图24.1.1.7 很类似,因为DOTCLK 接口就是连接RGB 屏幕的,本教程使用的就是DOTCLK 接口。

eLCDIF 要驱动起来RGB LCD 屏幕,重点是配置好上一小节讲解的那些时间参数即可,这个通过配置相应的寄存器就可以了,所以我们接下来看一下eLCDIF 接口的几个重要的寄存器,首先看一下LCDIF_CTRL 寄存器,此寄存器结构如图24.1.2.1 所示:
在这里插入图片描述

寄存器LCDIF_CTRL 用到的重要位如下:

SFTRST(bit31):eLCDIF 软复位控制位,当此位为1 的话就会强制复位LCD。

CLKGATE(bit30):正常运行模式下,此位必须为0!如果此位为1 的话时钟就不会进入到LCDIF。

BYPASS_COUNT(bit19):如果要工作在DOTCLK 模式的话就此位必须为1。

VSYNC_MODE(bit18):此位为1 的话LCDIF 工作在VSYNC 接口模式。

DOTCLK_MODE(bit17):此位为1 的话LCDIF 工作在DOTCLK 接口模式。

INPUT_DATA_SWIZZLE(bit15:14):输入数据字节交换设置,此位为0 的话不交换字节也就是小端模式;为1 的话交换所有字节,也就是大端模式;为2 的话半字交换;为3 的话在每个半字内进行字节交换。本章我们设置为0,也就是不使用字节交换。

CSC_DATA_SWIZZLE(bit13:12) :CSC 数据字节交换设置,交换方式和
INPUT_DATA_SWIZZLE 一样,本章设置为0,不使用字节交换。
LCD_DATABUS_WIDTH(bit11:10):LCD 数据总线宽度,为0 的话总线宽度为16 位;为1 的话总线宽度为8 位;为2 的话总线宽度为18 位;为3 的话总线宽度为24 位。本章我们使用24 位总线宽度。

WORD_LENGTH(bit9:8):输入的数据格式,也就是像素数据宽度,为0 的话每个像素16位;为1 的话每个像素8 位;为2 的话每个像素18 位;为3 的话每个像素24 位。
MASTER(bit5):为1 的话设置eLCDIF 工作在主模式。
DATA_FORMAT_16_BIT(bit3):当此位为1 并且WORD_LENGTH 为0 的时候像素格式为ARGB555,当此位为0 并且WORD_LENGTH 为0 的时候像素格式为RGB565。

DATA_FORMAT_18_BIT(bit2):只有当WORD_LENGTH 为2 的时候此位才有效,此位为0 的话低18 位有效,像素格式为RGB666,高14 位数据无效。当此位为1 的话高18 位有效,像素格式依旧是RGB666,但是低14 位数据无效。
DATA_FORMAT_24_BIT(bit1):只有当WORD_LENGTH 为3 的时候此位才有效,为0 的时候表示全部的24 位数据都有效。为1 的话实际输入的数据有效位只有18 位,虽然输入的是24 位数据,但是每个颜色通道的高2 位数据会被丢弃掉。
RUN(bit0):eLCDIF 接口运行控制位,当此位为1 的话eLCDIF 接口就开始传输数据,也就是eLCDIF 的使能位。

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

接下来看一下寄存器LCDIF_TRANSFER_COUNT,这个寄存器用来设置所连接的RGB LCD 屏幕分辨率大小,此寄存器结构如图24.1.2.2 所示:

在这里插入图片描述

寄存器LCDIF_TRANSFER_COUNT 分为两部分,高16 位和低16 位,高16 位是V_COUNT,是LCD 的垂直分辨率。低16 位是H_COUNT,是LCD 的水平分辨率。如果LCD 分辨率为1024*600 的话,那么V_COUNT 就是600,H_COUNT 就是1024。

接下来看一下寄存器LCDIF_VDCTRL0,这个寄存器是VSYNC 和DOTCLK 模式控制寄存器0,寄存器结构如图24.1.2.3 所示:
在这里插入图片描述
寄存器LCDIF_VDCTRL0 用到的重要位如下:

VSYNC_OEB(bit29):VSYNC 信号方向控制位,为0 的话VSYNC 是输出,为1 的话VSYNC 是输入。

ENABLE_PRESENT(bit28):EBABLE 数据线使能位,也就是DE 数据线。为1 的话使能ENABLE 数据线,为0 的话关闭ENABLE 数据线。

VSYNC_POL(bit27):VSYNC 数据线极性设置位,为0 的话VSYNC 低电平有效,为1 的话VSYNC 高电平有效,要根据所使用的LCD 数据手册来设置。

HSYNC_POL(bit26):HSYNC 数据线极性设置位,为0 的话HSYNC 低电平有效,为1 的话HSYNC 高电平有效,要根据所使用的LCD 数据手册来设置。

DOTCLK_POL(bit25):DOTCLK 数据线(像素时钟线CLK) 极性设置位,为0 的话下降沿锁存数据,上升沿捕获数据,为1 的话相反,要根据所使用的LCD 数据手册来设置。
ENABLE_POL(bit24):EANBLE 数据线极性设置位,为0 的话低电平有效,为1 的话高电平有效。
VSYNC_PERIOD_UNIT(bit21):VSYNC 信号周期单位,为0 的话VSYNC 周期单位为像素时钟。为1 的话VSYNC 周期单位是水平行,如果使用DOTCLK 模式话就要设置为1。
VSYNC_PULSE_WIDTH_UNIT(bit20) :VSYNC 信号脉冲宽度单位,和
VSYNC_PERIOD_UNUT 一样,如果使用DOTCLK 模式的话要设置为1。
VSYNC_PULSE_WIDTH(bit17:0):VSPW 参数设置位。

接下来看一下寄存器LCDIF_VDCTRL1,这个寄存器是VSYNC 和DOTCLK 模式控制寄存器1,此寄存器只有一个功能,用来设置VSYNC 总周期,就是:屏幕高度+VSPW+VBP+VFP。

接下来看一下寄存器LCDIF_VDCTRL2,这个寄存器分为高16 位和低16 位两部分,高16位是HSYNC_PULSE_WIDTH,用来设置HSYNC 信号宽度,也就是HSPW。低16 位是HSYNC_PERIOD,设置HSYNC 总周期,就是:屏幕宽度+HSPW+HBP+HFP。

接下来看一下寄存器LCDIF_VDCTRL3,此寄存器结构如图24.1.2.4 所示:

在这里插入图片描述

寄存器LCDIF_VDCTRL3 用到的重要位如下:

HORIZONTAL_WAIT_CNT(bit27:16):此位用于DOTCLK 模式,用于设置HSYNC 信号产生到有效数据产生之间的时间,也就是HSPW+HBP。

VERTICAL_WAIR_CNT(bit15:0):和HORIZONTAL_WAIT_CNT 一样,只是此位用于VSYNC 信号,也就是VSPW+VBP。

接下来看一下寄存器LCDIF_VDCTRL4,此寄存器结构如图24.1.2.5 所示:
在这里插入图片描述

寄存器LCDIF_VDCTRL4 用到的重要位如下:

SYNC_SIGNALS_ON(bit18):同步信号使能位,设置为1 的话使能VSYNC、HSYNC、DOTCLK 这些信号。

DOTCLK_H_VALID_DATA_CNT(bit15:0):设置LCD 的宽度,也就是水平像素数量。

最后在看一下寄存器LCDIF_CUR_BUF 和LCDIF_NEXT_BUF,这两个寄存器分别为当前帧和下一帧缓冲区,也就是LCD 显存。一般这两个寄存器保存同一个地址,也就是划分给LCD的显存首地址。

关于eLCDIF 接口的寄存器就介绍到这里,关于这些寄存器详细的描述,请参考《I.MX6ULL参考手册》第2165 页的34.6 小节。本章我们使用I.MX6U 的eLCDIF 接口来驱动ALIENTEK的ATK7016 这款屏幕,配置步骤如下:

1、初始化LCD 所使用的IO
首先肯定是初始化LCD 所示使用的IO,将其复用为eLCDIF 接口IO。
2、设置LCD 的像素时钟
查阅所使用的LCD 屏幕数据手册,或者自己计算出的时钟像素,然后设置CCM 相应的寄存器。
3、配置eLCDIF 接口
设置LCDIF 的寄存器CTRL、CTRL1、TRANSFER_COUNT、VDCTRL0~4、CUR_BUF 和NEXT_BUF。根据LCD 的数据手册设置相应的参数。
4、编写API 函数
驱动LCD 屏幕的目的就是显示内容,所以需要编写一些基本的API 函数,比如画点、画线、画圆函数,字符串显示函数等。

硬件原理分析

本试验用到的资源如下:

①、指示灯LED0。
②、RGB LCD 接口。
③、DDR3
④、eLCDIF

RGB LCD 接口在I.MX6U-ALPHA 开发板底板上,原理图如图24.2.1 所示:
在这里插入图片描述

图24.2.1 中三个SGM3157 的目的是在未使用RGBLCD 的时候将LCD_DATA7、LCD_DATA15 和LCD_DATA23 这三个线隔离开来,因为ALIENTEK 的屏幕的LCD_R7/G7/B7这几个线用来设置LCD 的ID,所以这几根线上有上拉/下拉电阻。但是I.MX6U 的BOOT 设置也用到了LCD_DATA7、LCD_DATA15 和LCD_DATA23 这三个引脚,所以接上屏幕以后屏幕上的ID 电阻就会影响到BOOT 设置,会导致代码无法运行,所以先将其隔离开来,如果要使用RGB LCD 屏幕的时候再通过LCD_DE 将其“连接”起来。我们需要40P 的FPC 线将ATK7016屏幕和I.MX6U-ALPHA 开发板连接起来,如图24.2.2 所示:
在这里插入图片描述

实验程序编写

本实验对应的例程路径为:开发板光盘-> 1、裸机例程-> 15_lcd。

本章实验在上一章例程的基础上完成,更改工程名字为“lcd”,然后在bsp 文件夹下创建名为“lcd”的文件夹,在bsp/lcd 中新建bsp_lcd.c、bsp_lcd.h、bsp_lcdapi.c、bsp_lcdapi.h 和font.h这五个文件。bsp_lcd.c 和bsp_lcd.h 是LCD 的驱动文件,bsp_lcdapi.c 和bsp_lcdapi.h 是LCD 的API 操作函数文件,font.h 是字符集点阵数据数组文件。在bsp_lcd.h 中输入如下内容:

1 #ifndef _BSP_LCD_H
2 #define _BSP_LCD_H
3 /***************************************************************
4 Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
5 文件名: bsp_lcd.h
6 作者: 左忠凯
7 版本: V1.0
8 描述: LCD驱动文件头文件。
9 其他: 无
10 论坛: www.openedv.com
11 日志: 初版V1.0 2019/1/3 左忠凯创建
12 ***************************************************************/
13 #include "imx6ul.h"
14
15 /* 颜色宏定义*/
16 #define LCD_BLUE 0x000000FF
17 #define LCD_GREEN 0x0000FF00
18 #define LCD_RED 0x00FF0000
19 /* 省略掉其它宏定义,完整的请参考实验例程*/

在文件bsp_lcd.h 中一开始定义了一些常用的颜色宏定义,颜色格式都是ARGB8888 的。

第23 行的宏LCD_FRAMEBUF_ADDR 是显存首地址,此处将显存首地址放到了0X89000000地址处。这个要根据所使用的LCD 屏幕大小和DDR 内存大小来确定的,前面我们说了ATK7016这款RGB 屏幕所需的显存大小为2.4MB,而I.MX6U-ALPHA 开发板配置的DDR 有256 和512MB 两种类型,内存地址范围分别为0X80000000~ 0X90000000 和0X80000000~0XA0000000。所以LCD 显存首地址选择为0X89000000 不管是256MB 还是512MB 的DDR 都可以使用。

第26 行的结构体tftlcd_typedef 是RGB LCD 的控制参数结构体,里面包含了跟LCD 配置有关的一些成员变量。最后就是一些变量和函数是声明。

在bsp_lcd.c 中输入如下内容:

/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名: bsp_lcd.c
作者: 左忠凯
版本: V1.0
描述: LCD驱动文件。
其他: 无
论坛: www.openedv.com
日志: 初版V1.0 2019/1/3 左忠凯创建
***************************************************************/
1 #include "bsp_lcd.h"
2 #include "bsp_gpio.h"
3 #include "bsp_delay.h"
4 #include "stdio.h"
5
6 /* 液晶屏参数结构体*/
7 struct tftlcd_typedef tftlcd_dev;
8
9 /*
10 * @description : 始化LCD
11 * @param : 无
12 * @return : 无
13 */
14 void lcd_init(void)
15 {
16 lcdgpio_init(); /* 初始化IO */
17 lcdclk_init(32, 3, 5); /* 初始化LCD时钟*/
18
19 lcd_reset(); /* 复位LCD */
20 delayms(10); /* 延时10ms */
21 lcd_noreset(); /* 结束复位*/
22
23 /* RGB LCD参数结构体初始化*/
24 tftlcd_dev.height = 600; /* 屏幕高度*/
25 tftlcd_dev.width = 1024; /* 屏幕宽度*/

文件bsp_lcd.c 里面一共有10 个函数,第一个函数是lcd_init,这个是LCD 初始化函数,此函数先调用LCD 的IO 初始化函数、时钟初始化函数、复位函数等,然后会按照我们前面讲解的步骤初始化eLCDIF 相关的寄存器,最后使能eLCDIF。第二个函数是lcdgpio_init,这个是LCD 的IO 初始化函数。第三个函数lcdclk_init 是LCD 的时钟初始化函数。第四个函数lcd_reset和第五个函数lcd_noreset 分别为复位LCD 的停止LCD 复位函数。第六个函数lcd_enable 是eLCDIF 使能函数,用于使能eLCDIF。第七个和第八个是画点和读点函数,分别为lcd_drawpoint和lcd_readpoint,通过这两个函数就可以在LCD 的指定像素点上显示指定的颜色,或者读取指定像素点的颜色。第九个函数lcd_clear 是清屏函数,使用指定的颜色清除整个屏幕。最后一个
函数lcd_fill 是填充函数,使用此函数的时候需要指定矩形的起始坐标、终止坐标和填充颜色,这样就可以填充出一个矩形区域。

在bsp_lcdapi.h 中输入如下所示内容:

1 #ifndef BSP_LCDAPI_H
2 #define BSP_LCDAPI_H
3 /***************************************************************
4 Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
5 文件名: bsp_lcdapi.h
6 作者: 左忠凯
7 版本: V1.0
8 描述: LCD显示API函数。
9 其他: 无
10 论坛: www.openedv.com
11 日志: 初版V1.0 2019/3/18 左忠凯创建
12 ***************************************************************/
13 #include "imx6ul.h"
14 #include "bsp_lcd.h"
15
16 /* 函数声明*/
17 void lcd_drawline(unsigned short x1, unsigned short y1, unsigned
short x2, unsigned short y2);
18 void lcd_draw_rectangle(unsigned short x1, unsigned short y1,
unsigned short x2, unsigned short y2);
19 void lcd_draw_circle(unsigned short x0,unsigned short y0,
unsigned char r);
20 void lcd_showchar(unsigned short x,unsigned short y,
unsigned char num,unsigned char size,
unsigned char mode);
21 unsigned int lcd_pow(unsigned char m,unsigned char n);
22 void lcd_shownum(unsigned short x, unsigned short y,
unsigned int num, unsigned char len,
unsigned char size);
23 void lcd_showxnum(unsigned short x, unsigned short y,
unsigned int num, unsigned char len,
unsigned char size, unsigned char mode);
24 void lcd_show_string(unsigned short x,unsigned short y,
unsigned short width, unsigned short height,
unsigned char size, char *p);
25 #endif

文件bsp_lcdapi.h 内容很简单,就是函数声明。在bsp_lcdapi.c 中输入如下内容:

/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名: bsp_lcdapi.c
作者: 左忠凯
版本: V1.0
描述: LCD API函数文件。
其他: 无
论坛: www.openedv.com
日志: 初版V1.0 2019/3/18 左忠凯创建
***************************************************************/
1 #include "bsp_lcdapi.h"
2 #include "font.h"
3
4 /*
5 * @description : 画线函数
6 * @param - x1 : 线起始点坐标X轴
7 * @param - y1 : 线起始点坐标Y轴
8 * @param - x2 : 线终止点坐标X轴
9 * @param - y2 : 线终止点坐标Y轴
10 * @return : 无
11 */
12 void lcd_drawline(unsigned short x1, unsigned short y1,
unsigned short x2, unsigned short y2)
13 {
14 u16 t;
15 int xerr = 0, yerr = 0, delta_x, delta_y, distance;
16 int incx, incy, uRow, uCol;
17 delta_x = x2 - x1; /* 计算坐标增量*/
18 delta_y = y2 - y1;
19 uRow = x1;
20 uCol = y1;
21 if(delta_x > 0) incx = 1; /* 设置单步方向*/
22 else if(delta_x==0) incx = 0; /* 垂直线*/
23 else
24 {
25 incx = -1;
26 delta_x = -delta_x;
27 }
28

文件bsp_lcdapi.h 里面都是一些LCD 的API 操作函数,比如画线、画矩形、画圆、显示数字、显示字符和字符串等函数。这些函数都是从STM32 例程里面移植过来的,如果学习过ALIENTEK 的STM32 教程的话就会很熟悉,都是一些纯软件的东西。

lcd_showchar 函数是字符显示函数,要理解这个函数就得先了解一下字符(ASCII 字符集)在LCD 上的显示原理。要显示字符,我们先要有字符的点阵数据,ASCII 常用的字符集总共有95 个,从空格符开始,分别为:!"#$%&’()*+,-0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~.

我们先要得到这个字符集的点阵数据,这里我们介绍一个款很好的字符提取软件:PCtoLCD2002 完美版。该软件可以提供各种字符,包括汉字(字体和大小都可以自己设置)阵提取,且取模方式可以设置好几种,常用的取模方式,该软件都支持。该软件还支持图形模式,也就是用户可以自己定义图片的大小,然后画图,根据所画的图形再生成点阵数据,这功能在制作图标或图片的时候很有用。

该软件的界面如图24.3.1 所示:
在这里插入图片描述
然后我们点击字模选项按钮进入字模选项设置界面。设置界面中点阵格式和取模方式等参数配置如图24.3.2 所示:
在这里插入图片描述
上图设置的取模方式,在右上角的取模说明里面有,即:从第一列开始向下每取8 个点作为一个字节,如果最后不足8 个点就补满8 位。取模顺序是从高到低,即第一个点作为最高位。如*-------取为10000000。其实就是按如图24.3.3 所示的这种方式:
在这里插入图片描述
从上到下,从左到右,高位在前。我们按这样的取模方式,然后把ASCII 字符集按12 * 6 大小、16 * 8、24 * 12 和32 * 16 大小取模出来(对应汉字大小为12 * 12、16 * 16、24 * 24 和32 * 32,字符的只有汉字的一半大!)。将取出的点阵数组保存在font.h 里面,每个12 * 6 的字符占用12 个字节,每个16 * 8 的字符占用16 个字节,每个24 * 12 的字符占用36 个字节,每个32 * 16 的字符占用64 个字节。font.h 中的字符集点阵数据数组asc2_1206、asc2_1608、asc2_2412 和asc2_3216就对应着这四个大小字符集,具体见font.h 部分代码(该部分我们不再这里列出来了,请大家参考光盘里面的代码)。

最后在main.c 中输入如下所示内容:

/**************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名: main.c
作者: 左忠凯
版本: V1.0
描述: I.MX6U开发板裸机实验16 LCD液晶屏实验
其他: 本实验学习如何在I.MX6U上驱动RGB LCD液晶屏幕,I.MX6U有个
ELCDIF接口,通过此接口可以连接一个RGB LCD液晶屏。
论坛: www.openedv.com
日志: 初版V1.0 2019/1/15 左忠凯创建
**************************************************************/
1 #include "bsp_clk.h"
2 #include "bsp_delay.h"
3 #include "bsp_led.h"
4 #include "bsp_beep.h"
5 #include "bsp_key.h"
6 #include "bsp_int.h"
7 #include "bsp_uart.h"
8 #include "stdio.h"
9 #include "bsp_lcd.h"
10 #include "bsp_lcdapi.h"
11
12
13 /* 背景颜色数组*/

第37 行调用函数lcd_init 初始化LCD。
第39 行设置前景色,也就是画笔颜色为红色。
第40~44 行都是调用bsp_lcdapi.c 中的API 函数在LCD 上绘制各种图形和显示字符串。
第46 行的while 循环中每隔1S 中就调用函数lcd_fill 填充指定的区域,并且显示index值。

main 函数很简单,重点就是初始化LCD,然后调用LCD 的API 函数进行一些常用的操作,比如画线、画矩形、显示字符串和数字等等。

编译下载验证

编写Makefile 和链接脚本

修改Makefile 中的TARGET 为lcd,然后在INCDIRS 和SRCDIRS 中加入“bsp/lcd”,修改后的Makefile 如下:

1 CROSS_COMPILE ?= arm-linux-gnueabihf-
2 TARGET ?= lcd
3
4 /* 省略掉其它代码...... */
5
6 INCDIRS := imx6ul \
7 stdio/include \
8 bsp/clk \
9 bsp/led \
10 bsp/delay \
11 bsp/beep \
12 bsp/gpio \
13 bsp/key \
14 bsp/exit \
15 bsp/int \
16 bsp/epittimer \
17 bsp/keyfilter \
18 bsp/uart \
19 bsp/lcd
20
21 SRCDIRS := project \
22 stdio/lib \
23 bsp/clk \
24 bsp/led \
25 bsp/delay \

第2 行修改变量TARGET 为“lcd”,也就是目标名称为“lcd”。
第19 行在变量INCDIRS 中添加RGB LCD 驱动头文件(.h)路径。
第34 行在变量SRCDIRS 中添加RGB LCD 驱动驱动文件(.c)路径。
链接脚本保持不变。

编译下载

使用Make 命令编译代码,编译成功以后使用软件imxdownload 将编译完成的lcd.bin 文件下载到SD 卡中,命令如下:

chmod 777 imxdownload //给予imxdownload 可执行权限,一次即可
./imxdownload lcd.bin /dev/sdd //烧写到SD 卡中,不能烧写到/dev/sda 或sda1 设备里面!

烧写成功以后将SD 卡插到开发板的SD 卡槽中,然后复位开发板。程序开始运行,LED0每隔1S 闪烁依次,屏幕下半部分会每1S 刷新依次,并且在屏幕的右上角显示索引值,LCD屏幕显示如图24.4.3 所示
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RGBLCD显示实验————复习到这 的相关文章

  • 如何访问Loader的sourceComponent中的QML对象?

    我可能需要读取或写入的一些属性Loader s sourceComponent来自一些外部函数 访问该房产的方式是什么x里面的对象的Loader s sourceComponent import QtQuick 2 0 Item width
  • jq中如何分组?

    这是 json 文档 name bucket1 clusterName cluster1 name bucket2 clusterName cluster1 name bucket3 clusterName cluster2 name bu
  • 在脚本内使用不带密码的 sudo

    由于某种原因 我需要作为用户在没有 sudo 的情况下运行脚本 script sh 该脚本需要 root 权限才能工作 我认为将 sudo 放入 script sh 中是唯一的解决方案 让我们举个例子 script sh bin sh su
  • 如何在 Bash 中给定超时后终止子进程?

    我有一个 bash 脚本 它启动一个子进程 该进程时不时地崩溃 实际上是挂起 而且没有明显的原因 闭源 所以我对此无能为力 因此 我希望能够在给定的时间内启动此进程 如果在给定的时间内没有成功返回 则将其终止 有没有simple and r
  • 需要一些建议来开始在 ARM(使用 Linux)平台上编程

    我 也许 很快就会在托管 Linux 发行版的 ARM 平台上工作 我不知道哪个发行版 我知道该项目涉及视频流 但我无法告诉你更多信息 其实我只收到通知 还没见到任何人 我从来没有在这样的平台上工作过 所以我的想法是在项目开始之前进行测试
  • 如何在qt中创建正确的退出按钮

    我正在尝试创建一个退出按钮来正确关闭我在 QT 中制作的 GUI 我尝试通过以下方式执行此操作 include
  • 进程退出后 POSIX 名称信号量不会释放

    我正在尝试使用 POSIX 命名信号量进行跨进程同步 我注意到进程死亡或退出后 信号量仍然被系统打开 在进程 打开它 死亡或退出后是否有办法使其关闭 释放 早期的讨论在这里 当将信号量递减至零的进程崩溃时 如何恢复信号量 https sta
  • 监视目录的更改

    很像一个类似的问题 https stackoverflow com questions 112276 directory modification monitoring 我正在尝试监视 Linux 机器上的目录以添加新文件 并希望在这些新文
  • 快速像素绘图库

    我的应用程序以每像素的方式生成 动画 因此我需要有效地绘制它们 我尝试过不同的策略 库 但结果并不令人满意 尤其是在更高分辨率的情况下 这是我尝试过的 SDL 好的 但是慢 OpenGL 像素操作效率低下 xlib 更好 但仍然太慢 svg
  • 如何从 matlab 调用 Qtproject?

    我在 matlab 中有一个函数可以写入一个 file txt 我在 qt 项目中使用它 So 当我使用 unix 获取要运行的 qt 编译可执行文件时 我有一个 Matlab 文件 但出现错误 代码 unix home matt Desk
  • NUMA 在虚拟内存中是如何表示的?

    有许多资源 https en wikipedia org wiki Non uniform memory access从硬件角度描述NUMA的架构性能影响 http practical tech com infrastructure num
  • 高效的内存屏障

    我有一个多线程应用程序 其中每个线程都有一个整数类型的变量 这些变量在程序执行期间递增 在代码中的某些点 线程将其计数变量与其他线程的计数变量进行比较 现在 我们知道在多核上运行的线程可能会无序执行 一个线程可能无法读取其他线程的预期计数器
  • Qt中正确的线程方式

    我的图像加载非常耗时 图像很大 并且在加载时也完成了一些操作 我不想阻止应用程序 GUI 我的想法是在另一个线程中加载图像 发出图像已加载的信号 然后用该图像重绘视图 我的做法 void Window loadImage ImageLoad
  • 在 unix 中编译 dhrystone 时出错

    我是使用基准测试和 makefile 的新手 我已经从下面的链接下载了 Dhrystone 基准测试 我正在尝试编译它 但我遇到了奇怪的错误 我尝试解决它 但没有成功 有人可以帮助我运行 dhrystone 基准测试吗 以下是我尝试编译的两
  • 无法在 Perl 中找到 DBI.pm 模块

    我使用的是 CentOS 并且已经安装了 Perl 5 20 并且默认情况下存在 Perl 5 10 我正在使用 Perl 5 20 版本来执行 Perl 代码 我尝试使用 DBI 模块并收到此错误 root localhost perl
  • 从 systemd bash 内联脚本创建 filename_$(date %Y-%m-%d)

    我正在尝试执行systemd计时器并希望将执行脚本的输出保存在每个日期的文件中 这是我的ExecStart脚本中的 service file ExecStart bin bash c echo date Y m d gt gt home u
  • 使用 plistBuddy 获取值数组

    var keychain access groups declare a val usr libexec PlistBuddy c Print var sample plist echo val echo val 0 Ouput Array
  • 限制 Imagemagick 使用的空间和内存

    我在 Rails 应用程序上使用 Imagemagick 使用 rmagick 但我的服务器 Ubuntu 不是很大 当我启动转换进程时 Imagemagick 占据了我的服务器 30GB HDD 的所有位置 内存 我想限制内存和 tmp
  • QWidget::showMinimized() 不起作用

    在 Ubuntu 13 04 上 如果使用QWidget showMinimized 为了最小化窗口 我发现通过单击系统任务栏上的应用程序图标恢复它后 调用QWidget showMinimized 无法工作 connect minimum
  • 如何从 PROC 获取有关子进程的信息

    我正在尝试编写一个以几个进程作为参数的程序 然后父进程执行每个子进程并打印出一些相关的统计信息 示例 generate ls l 将生成一个程序 打印出有关 ls l 的一些统计信息 特别是其系统时间 用户时间和上下文切换次数 我不想使用

随机推荐

  • 从“制造”之城,到“智造”标杆,长沙何以站上发展新高地?

    图片源自网络 文 易不二 来源 智能相对论 ID aixdlun 中国中部的湖南是众多制造业企业走向数字化 网络化 最终以智能制造为目标的聚集地 上个月 长沙城市品牌塑造及国际形象传播研讨会后 11家国际媒体中 越南之声广播电台刊在 中国将
  • 【开关电源四】电源拓扑之Cuk、Sepic、Zeta

    个人主页 highman110 作者简介 一名硬件工程师 持续学习 不断记录 保持思考 输出干货内容 目录 1 Cuk变换器 1 1 Cuk电路工作原理 1 2 Cuk电路输入输出关系推导 2 Sepic变换器 2 1 Sepic电路工作原
  • C盘空间不足怎么清理,详细的c盘清理方法归类

    C盘空间不足怎么清理 当你的计算机告诉你C盘空间不足时 这意味着你需要清理一些文件或程序来腾出更多的空间 在本文中 我们将介绍一些常用的方法 帮助你清理C盘空间 方法一 清理临时文件 许多应用程序和操作系统会在C盘上创建临时文件 这些文件会
  • U盘装完系统之后磁盘容量变小解决办法

    我在用Win32 Disk Imager工具制作U盘系统盘之后 发现U盘大小变为2M 另外的大小没有被分配 解决办法如下 http jingyan baidu com article 59703552e754e48fc00740ed htm
  • 一个tomcat部署多个项目(同端口,多项目,不同访问路径)

    个人觉得简单易操作的两种部署方式 使用tomcat的自动部署 适用于文件和war包 不需要重启tomcat服务 自定义web部署文件 只适用于文件形式的 需要重启tomcat服务 一 自动部署 步骤 浏览器输入127 0 0 1 8080
  • uniapp 小程序中使用逆地址解析 获取当前详细地址

    描述 获取当前定位的经纬度后使用 逆地址解析 获取到详细的地址 uniapp和微信小程序获取地址有两个API getLocation和chooseLocation 但都没有返回省市区等具体信息 那我们可以获取当前经纬度 然后使用逆地址解析接
  • 数据分析案例-大数据相关招聘岗位可视化分析_招聘信息数据集

    文章目录 数据集介绍 数据预处理 数据可视化 数据集介绍 本次数据集来源于xx招聘网共计4223条招聘信息 每条招聘信息字段包括岗位名称 公司名称 工作经验要求 学历要求 工作地点 薪酬 公司规模 发布时间 公司福利共9条字段信息 数据预处
  • 粒子系统学习(1)

    Particle System Duration 产生 发射 粒子的时间 比如不勾选Looping Duration为5 Start Lifetime为6 那么在运行11s的时候粒子效果消失 Looping 是否循环 发射 产生 和Dura
  • [Pyhon疫情大数据分析] 一.腾讯实时数据爬取、Matplotlib和Seaborn可视化分析全国各地区、某省各城市、新增趋势

    思来想去 虽然很忙 但还是挤时间针对这次肺炎疫情写个Python大数据分析系列博客 包括网络爬虫 可视化分析 GIS地图显示 情感分析 舆情分析 主题挖掘 威胁情报溯源 知识图谱 预测预警及AI和NLP应用等 希望该系列线上远程教学对您有所
  • DeepLearnToolbox使用总结

    目录 DeepLearnToolbox Directories included in the toolbox Setup GitHub链接 DeepLearnToolbox DeepLearnToolbox A Matlab toolbo
  • CAP、BASE、一致性

    感谢博主 转自 从分布式一致性谈到CAP理论 BASE理论 问题的提出 在计算机科学领域 分布式一致性是一个相当重要且被广泛探索与论证问题 首先来看三种业务场景 1 火车站售票 假如说我们的终端用户是一位经常坐火车的旅行家 通常他是去车站的
  • Visual Studio查找搜索类和方法的快捷方法

    Visual Studio 2010有 Navigate To 命令 键盘快捷键是 CTRL 或 Ctrl T
  • 什么是拦截器?什么是过滤器?

    原文链接 https www longkui site program frontend pipe 4408 0 背景 写项目的时候用到了拦截器 会决定哪些接口拦截 哪些接口不拦截 偶尔一次等保测评的时候又遇到了筛选器 这篇文章简单总结一下
  • echarts 折现图和柱状图 样式修改 设置折线样式 背景(文末附带完整代码)

    1 设置折线图样式 修改后 背景竖条纹间隔 去掉边框 设置折线和节点颜色 设置数据字体颜色 设置折线样式 设置折线图的背景样式 2 设置柱状图样式 修改后 设置柱子的样式 设置柱状图背景 完整代码 路径配置 require config p
  • postman中,发送接口请求,报错Error: connect ECONNREFUSED 10.10.10.33:1111(未完成)

    1 问题 postman发送接口请求 报错Error connect ECONNREFUSED 10 10 10 33 1111 postman执行接口 用的是ip 端口 接口路径进行访问 图1 拒绝连接 图2 2 解决 在网上找了一个 说
  • 野蛮生长的前端,从杂牌军到正规军

    笔者从事后台研发多年 对前端实在是没有多少发言权 下面就斗胆以门外汉的角度聊聊近来对前端技术的一些见解 也自当整理一下思路 使前端技术如何更好的融入到整个产品研发架构中来 这里的前端语言不仅限于js 还是css html等等 来看一看201
  • Java动态绑定和静态绑定

    Java动态绑定和静态绑定 程序绑定 静态绑定 动态绑定 程序绑定 程序绑定 一个方法的调用与方法所在的类 方法主题 关联起来 即计算机要明确最终执行的方法是谁的方法 对Java来说 绑定分为静态绑定和动态绑定 或者叫做前期绑定和后期绑定
  • bash: scp: 未找到命令 lost connection

    通过ssh免密通道上传备份时报错 bash scp 未找到命令 lost connection 解决 分别查看发送端服务器 接收端服务器 1 查找命令是否存在 whereis scp 不存在就重新安装 yum install openssh
  • PyQt5实现父窗口内点击按钮显示子窗口(窗口嵌套功能)

    摘要 在软件中 常会有点击某个按钮 显示一个新的子界面的需求 本文介绍如何在PyQt5中实现这一功能 主要涉及知识点是 信号与槽函数的自动绑定 程序说明 1 开发环境 win10系统 pycharm2021 python3 7 2 实现功能
  • RGBLCD显示实验————复习到这

    目录 LCD 和eLCDIF 简介 LCD 简介 eLCDIF 接口 硬件原理分析 实验程序编写 编译下载验证 编写Makefile 和链接脚本 编译下载 LCD 液晶屏是常用到的外设 通过LCD 可以显示绚丽的图形 界面等 提高人机交互的