今天的学习进入了人机交互(HMI)的核心领域------显示与触摸。从LCD屏幕的显存映射、底层硬件信号线,到PWM控制背光/蜂鸣器,再到GT9147电容触摸屏的驱动编写,最后结合之前学的LM75温度传感器,完成了一个能在屏幕上显示温度的实战小项目。信息量极大,整理一下核心笔记。
一、 LCD显示原理与显存映射
要想在屏幕上画画,首先要搞懂屏幕是怎么显示图像的。
1. 分辨率与显存计算
-
屏幕分辨率 :横向像素点个数 * 纵向像素点个数(如
800 * 480)。 -
显存(Frame Buffer):专门存放图像数据的内存空间。
-
假设每个像素点占4个字节(ARGB格式),一块 800*480 的屏幕,需要的显存大小为:
800 * 480 * 4 = 1.5MB。 -
结合之前的内存映射知识,IMX6ULL分配给LCD控制器的显存起始地址通常在
0x89000000。
-
2. 像素颜色格式
-
RGB888 :每个像素点占3个字节,8bit面板,能显示 1670万色。
-
RGB565:每个像素点占2个字节(红色5位,绿色6位,蓝色5位),节省内存。
-
ARGB:每个像素点占4个字节,多了一个Alpha通道(透明度)。
3. 显存指针操作(核心代码)
如果我们将显存首地址 0x89000000 强制转换为 unsigned int *p,那么屏幕上第 y 行、第 x 列的像素点怎么表示?
c
// 公式:*(p + 屏幕宽度 * y + x) = 颜色值;
*(p + 800 * y + x) = col;
(注:如果屏幕是 800480,那么这里的宽度就是 800)*
二、 LCD硬件信号线详解
结合硬件框图,LCD接口线比较多,主要分为以下几类:
Q2: LCD有哪几根线?
-
数据线 :
R0-R7(红色)、G0-G7(绿色)、B0-B7(蓝色),共24根(RGB888模式)。如果只接16根(如R0-R4, G0-G5, B0-B4),则为RGB565模式。 -
时钟信号线 :
PCLK。 -
同步信号线 :
HSYNC、VSYNC。 -
使能信号线 :
DE。 -
其他:电源线、地线、背光控制线。
Q3: PCLK、HSYNC、VSYNC、DE 信号线作用?
-
PCLK (Pixel Clock,像素时钟):同步像素点发送的时间间隔。每来一个PCLK脉冲,RGB数据线上就传输一个像素点的数据。
-
HSYNC (Horizontal Sync,水平/行同步):同步每一行发送的时间间隔。告诉屏幕"这一行发完了,准备从下一行的开头开始发"。
-
VSYNC (Vertical Sync,垂直/帧同步):同步每一帧图像的时间间隔。告诉屏幕"这一帧画面发完了,准备从第一行开始重新发下一帧"。
-
DE (Data Enable,数据使能):有效数据区域指示。DE为高电平时,表示当前传输的RGB数据是有效像素;DE为低电平时,表示传输的是消隐区(Blank)数据,屏幕不显示。
三、 PWM控制原理(背光与占空比)
PWM(脉冲宽度调制)在屏幕背光调节、电机控速中极其常用。
-
基本概念 :假设计数器时钟是
1MHz(周期1us),PWM频率设为1KHz(周期1ms),那么计数值到1000就是一个周期。 -
周期与占空比:
-
PWM周期:由"周期寄存器"决定。
-
PWM占空比:由"采样寄存器"(即比较点)决定。
-
-
引脚极性:
-
引脚默认高电平 :采样寄存器中的值越大 ,高电平时间越长,占空比越大。
-
引脚默认低电平 :采样寄存器中的值越大 ,低电平时间越长,占空比越小。
-
四、 电容触摸屏(GT9147)驱动开发
现代屏幕不仅用来显示,还能触摸。传统的电阻屏需要校准,而电容屏靠感应电压变化工作,无需校准。
1. 触摸芯片(GT9147)
-
I2C设备地址 :
0x5D。 -
核心寄存器:
-
0x8140:芯片ID(读取为 "9147")。 -
0x804D / 0x8056:中断触发方式配置(如01表示下降沿触发)。 -
0x8158 - 0x815B:触控坐标寄存器(存放X、Y坐标)。
-
2. GT9147 驱动初始化流程
根据流程图,驱动步骤如下:
-
引脚配置 :配置
RST和INT引脚的复用功能及电气属性。 -
硬件复位 :拉低
RST引脚,将触摸芯片复位。 -
I2C初始化:初始化I2C控制器,准备与芯片通信。
-
编写读写函数 :封装
gt9147_read和gt9147_write基于I2C的函数。 -
读取芯片ID :读取
0x8140,校验是否为 "9147"。 -
配置中断触发 :向
0x804D/0x8056写入01(下降沿触发)。 -
使能INT中断:配置GPIO为输入,并使能GPIO引脚中断。
-
GIC注册中断:在GIC中断控制器中注册中断号,设置优先级,使能该IRQ通道。
-
中断服务函数(ISR) :当手指按下(INT下降沿),触发中断。进入ISR后,读取
0x8158-0x815B获取X、Y坐标及按下点数,处理完后清除中断标志。
五、 实战:LCD显示LM75传感器采集的温
结合之前学的I2C读取LM75温度,加上今天的LCD度显示,就能做一个智能温度计了!
Q1: LCD显示LM75传感器采集的温度(上传运行结果)
这里写一下代码实现的逻辑框架
c
// 1. 获取温度函数(基于之前的LM75 I2C代码)
float get_lm75_temperature(void) {
// 读寄存器、拼接数据、转换
return temperature_value;
}
// 2. LCD显示数字与字符(需要字库支持)
void lcd_show_string(int x, int y, char *str, unsigned int color, unsigned int size) {
// 遍历字符串,调用lcd_show_char在指定位置画点
}
void main() {
// 初始化
lcd_init(); // 初始化LCD
lm75_init(); // 初始化LM75传感器
lcd_clear(0xFFFFFF); // 刷白屏
while (1) {
float temp = get_lm75_temperature();
// 将浮点温度转为字符串,例如 "Temp: 25.5 C"
char buf[32];
sprintf(buf, "Temp: %.1f C", temp);
// 在屏幕坐标 (100, 100) 处显示白色字符串
lcd_show_string(100, 100, buf, 0x000000, 24); // 黑色字体
// 延时,避免刷新过快
delay(500);
}
}
实现步骤说明:
-
确保移植或编写了基本的LCD画点函数(操作显存
0x89000000)。 -
准备常用的ASCII字库,实现字符显示函数。
-
通过I2C定时读取LM75传感器的温度值。
-
使用
sprintf将数值格式化,调用LCD字符显示函数进行刷新。
今日总结与反思
-
LCD的显存操作 :其实显示的本质就是往内存里填颜色,
*(p + 800*y + x) = col这个公式非常精辟,底层画图全指望它。 -
信号线的协同:PCLK、HSYNC、VSYNC、DE 构成了屏幕刷新的"交通信号灯",少一个信号,屏幕就会花屏或撕裂。
-
触摸屏中断:电容屏不像电阻屏需要一直轮询ADC,它通过INT引脚在按下时主动触发中断,极大地节省了CPU资源。GT9147的驱动流程非常标准:复位 -> 验ID -> 配中断 -> 注册GIC -> 读坐标。
踩坑心得:调试LCD时如果发现花屏,首先检查显存地址和像素格式(RGB565还是RGB888);调试触摸屏时,如果坐标不对,可能是X、Y轴被交换了,或者屏幕方向(横屏/竖屏)没有做坐标映射转换。