新手自学嵌入式 | 学习日记:LCD显示原理、PWM控制、电容触摸屏(GT9147)驱动开发与项目实战

今天的学习进入了人机交互(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有哪几根线?

  1. 数据线 :R0-R7 (红色)、G0-G7 (绿色)、B0-B7 (蓝色),共24根(RGB888模式)。如果只接16根(如R0-R4, G0-G5, B0-B4),则为RGB565模式。

  2. 时钟信号线 :PCLK。

  3. 同步信号线 :HSYNC、VSYNC。

  4. 使能信号线 :DE。

  5. 其他:电源线、地线、背光控制线。

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 驱动初始化流程

根据流程图,驱动步骤如下:

  1. 引脚配置 :配置 RST 和 INT 引脚的复用功能及电气属性。

  2. 硬件复位 :拉低 RST 引脚,将触摸芯片复位。

  3. I2C初始化:初始化I2C控制器,准备与芯片通信。

  4. 编写读写函数 :封装 gt9147_read 和 gt9147_write 基于I2C的函数。

  5. 读取芯片ID :读取 0x8140,校验是否为 "9147"。

  6. 配置中断触发 :向 0x804D/0x8056 写入 01(下降沿触发)。

  7. 使能INT中断:配置GPIO为输入,并使能GPIO引脚中断。

  8. GIC注册中断:在GIC中断控制器中注册中断号,设置优先级,使能该IRQ通道。

  9. 中断服务函数(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); 
    }
}

实现步骤说明:

  1. 确保移植或编写了基本的LCD画点函数(操作显存 0x89000000)。

  2. 准备常用的ASCII字库,实现字符显示函数。

  3. 通过I2C定时读取LM75传感器的温度值。

  4. 使用 sprintf 将数值格式化,调用LCD字符显示函数进行刷新。


今日总结与反思

  1. LCD的显存操作 :其实显示的本质就是往内存里填颜色,*(p + 800*y + x) = col 这个公式非常精辟,底层画图全指望它。

  2. 信号线的协同:PCLK、HSYNC、VSYNC、DE 构成了屏幕刷新的"交通信号灯",少一个信号,屏幕就会花屏或撕裂。

  3. 触摸屏中断:电容屏不像电阻屏需要一直轮询ADC,它通过INT引脚在按下时主动触发中断,极大地节省了CPU资源。GT9147的驱动流程非常标准:复位 -> 验ID -> 配中断 -> 注册GIC -> 读坐标。

踩坑心得:调试LCD时如果发现花屏,首先检查显存地址和像素格式(RGB565还是RGB888);调试触摸屏时,如果坐标不对,可能是X、Y轴被交换了,或者屏幕方向(横屏/竖屏)没有做坐标映射转换。

相关推荐
LXT7122 小时前
每日英语一读|为什么夏天的雷雨,总爱在傍晚出现?
深度学习·学习
知识分享小能手2 小时前
C学习教程,从入门到精通,C语言文件 — 完整知识点详解(14)
c语言·网络·学习
羊羊一洋2 小时前
ROM&RAM
c语言·stm32·学习
优化Henry3 小时前
LTE小区光路降质告警排查与处理实录
运维·网络·学习·5g·tdd
暖馒3 小时前
运动控制框架相关知识
学习
stereohomology4 小时前
我对DeepSeek4.1flash能力变化的感觉和第三方评估相当
人工智能·学习·llm
zbyyd4 小时前
Linux驱动:UART串口通信、GT9147触摸屏与IIO-ADC驱动开发
linux·驱动开发·arm
syagain_zsx5 小时前
protobuf 实战:从 .proto 到 C++ 序列化的完整链路
c++·学习·程序人生·谷歌·protobuf
zbyyd5 小时前
Linux驱动:SPI子系统与ADXL345三轴加速度传感器驱动开发
linux·驱动开发·arm