嵌入式学习 day60:ARM汇编——触摸屏与SPI

一、GT9147 触摸屏

GT9147 是什么

GT9147 是一款电容触摸屏控制器。它负责检测触摸屏上的触摸点,通过 I2C 把坐标告诉主控。

主要特性

参数 值
通信接口 I2C
设备地址 0x14(GT1151)或 0x5D(GT9147)
支持触摸点 最多 5 点
中断输出 有,触摸时产生中断
复位 有,通过 RST 引脚复位

和主控的连接

  • I2C2:SDA、SCL,用来读坐标和写配置

  • GPIO1_IO09:中断引脚(CT_INT),触摸时产生中断

  • GPIO5_IO09:复位引脚(CT_RST),控制复位

工作原理

  1. 上电后,主控通过 RST 引脚复位 GT9147

  2. 主控通过 I2C 读设备 ID,确认芯片型号

  3. 配置 GT9147 进入"读坐标"模式

  4. 触摸发生时,GT9147 拉低中断引脚,产生中断

  5. 主控在中断服务函数里通过 I2C 读触摸点数量、坐标

  6. 处理完后,通过 I2C 清中断标志

二、GT9147 的寄存器

寄存器 作用
0x8140 设备 ID(4 字节)
0x814E 触摸状态寄存器
0x8150 触摸点 0 坐标
0x8158 触摸点 1 坐标
0x8160 触摸点 2 坐标
0x8168 触摸点 3 坐标
0x8170 触摸点 4 坐标
0x8040 控制寄存器,进入读坐标模式

触摸状态寄存器(0x814E)

  • 低 4 位:触摸点数量(0~5)

  • bit7:坐标就绪标志

坐标寄存器

每个触摸点的坐标占 4 字节:

  • 字节 0~1:X 坐标(低字节在前)

  • 字节 2~3:Y 坐标(低字节在前)

三、gt9147初始化

1. I2C 初始化

c

复制代码
i2c_init(I2C2);

GT9147 接在 I2C2 上。

2. 引脚复用

c

复制代码
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0);  // CT_INT
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09, 0);   // CT_RST
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09, 0x10B0);
  • GPIO1_IO09:中断引脚

  • GPIO5_IO09:复位引脚

3. 设置方向

c

复制代码
GPIO1->GDIR |= (1 << 9);   // 中断引脚先设为输出
GPIO5->GDIR |= (1 << 9);   // 复位引脚设为输出

4. 复位 GT9147

c

复制代码
GPIO1->DR &= ~(1 << 9);    // 中断引脚拉低
GPIO5->DR &= ~(1 << 9);    // 复位引脚拉低
delay_ms(50);
GPIO5->DR |= (1 << 9);     // 复位引脚拉高,释放复位
delay_ms(100);

复位序列:拉低复位引脚,延时,拉高,延时。GT9147 复位后进入工作状态。

5. 读设备 ID

c

复制代码
unsigned char buffer[128] = {0};
gt9147_read(0x8140, buffer, 4);
printf("Gesture ID = %s\n", buffer);

读 0x8140 寄存器的 4 个字节,就是芯片型号字符串。根据读到的型号,选择对应的设备地址和坐标寄存器地址。

6. 配置中断

c

复制代码
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0x0800);   // 开漏
GPIO1->GDIR &= ~(1 << 9);    // 设为输入
GPIO1->ICR1 |= (3 << 18);    // 触发方式:上升沿
GPIO1->IMR |= (1 << 9);      // 中断屏蔽解除
  • 电气特性改成开漏(0x0800)

  • 中断引脚设为输入

  • ICR1 设置触发方式

  • IMR 使能中断

7. 配置 GIC

c

复制代码
GIC_SetPriority(GPIO1_Combined_0_15_IRQn, 0);
system_interrupt_register(GPIO1_Combined_0_15_IRQn, touch_irq_hangdler);
GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);

和之前中断一样,设置优先级、注册处理函数、使能。

8. 进入读坐标模式

c

复制代码
buffer[0] = 0;
gt9147_write(0x8040, buffer, 1);

写 0x8040 寄存器,告诉 GT9147 进入读坐标模式。

四、中断处理

c

复制代码
void touch_irq_hangdler(void)
{
    if ((GPIO1->ISR & (1 << 9))  != 0)
    {
        unsigned char buffer[64] = {0};
        gt9147_read(0x814E, buffer, 1);
        unsigned char num = buffer[0] & 0x0F;

        if (_gt9147.num != num)
        {
            _gt9147.num = num;
            int i = 0;
            for (i = 0; i < num; i++)
            {
                gt9147_read(pointer_add[i], buffer, 4);
                _gt9147.x[i] = (buffer[1] << 8) | (buffer[0] << 0); 
                _gt9147.y[i] = (buffer[3] << 8) | (buffer[2] << 0); 
            }
            _gt9147.vail = 1;
            show_pointer();
        }

        buffer[0] = 0;
        gt9147_write(0x814E, buffer, 1);
        GPIO1->ISR |= (1 << 9);
    }
}

1. 检查中断状态

c

复制代码
if ((GPIO1->ISR & (1 << 9))  != 0)

检查 GPIO1_IO09 的中断状态,确认是触摸中断。

2. 读触摸点数量

c

复制代码
gt9147_read(0x814E, buffer, 1);
unsigned char num = buffer[0] & 0x0F;

读 0x814E 寄存器,低 4 位是触摸点数量。

3. 读坐标

c

复制代码
for (i = 0; i < num; i++)
{
    gt9147_read(pointer_add[i], buffer, 4);
    _gt9147.x[i] = (buffer[1] << 8) | (buffer[0] << 0); 
    _gt9147.y[i] = (buffer[3] << 8) | (buffer[2] << 0); 
}

每个触摸点读 4 字节:X 低字节、X 高字节、Y 低字节、Y 高字节。合成 16 位坐标。

4. 显示坐标

c

复制代码
show_pointer();

打印触摸点数量和坐标。

5. 清中断标志

c

复制代码
buffer[0] = 0;
gt9147_write(0x814E, buffer, 1);
GPIO1->ISR |= (1 << 9);
  • 写 0x814E 寄存器,告诉 GT9147 处理完毕

  • 写 1 清 GPIO1 的中断标志位

清标志是必须的,不清的话中断会一直触发。

五、SPI 通信

SPI 是什么

SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信协议,比 I2C 快。

四根线

线 名称 作用
SCLK 时钟 主机产生
MOSI Master Out Slave In 主机发,从机收
MISO Master In Slave Out 从机发,主机收
SS Slave Select 片选,选择从机

和 I2C 的区别

部分 I2C SPI
线数 2(SCL、SDA) 4(SCLK、MOSI、MISO、SS)
速度 较慢 较快
拓扑 一主多从,有地址 一主多从,有片选
应答 有 ACK/NACK 无
全双工 半双工 全双工

SPI 的优点

  • 速度快:可以到几十 MHz

  • 全双工:收发可以同时进行

  • 协议简单:没有地址、应答,只有片选

SPI 的缺点

  • 线多:每个从机需要一根片选线

  • 没有应答:不知道对方收没收到

六、SPI 初始化

1. 引脚复用

c

复制代码
IOMUXC_SetPinMux(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0);
IOMUXC_SetPinMux(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0);
IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0);
IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_ECSPI3_SS0, 0);

把 UART2 的四个引脚复用成 ECSPI3 的 MOSI、MISO、SCLK、SS0。

2. 电气特性

c

复制代码
IOMUXC_SetPinConfig(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0x10B1);
// ...

0x10B1 配置电气特性,比之前用的 0x10B0 多一点,可能开了上拉或其他特性。

3. 片选引脚

c

复制代码
GPIO1->GDIR |= (1 << 20);
GPIO1->DR |= (1 << 20);

GPIO1_IO20 用作片选,设为输出,默认拉高(不选中)。

4. 配置 CONREG

c

复制代码
ECSPI3->CONREG = 0;
ECSPI3->CONREG |= (7 << 20) | (14 << 12) | (2 << 8) | (1 << 4) | (1 << 3);
  • bits 20-23:PRE_DIV,预分频

  • bits 12-15:POST_DIV,后分频

  • bits 8-11:CHANNEL_MODE,通道模式

  • bit 4:SMC,开始模式控制

  • bit 3:SCLK_POL,时钟极性

5. 配置 CONFIGREG

c

复制代码
ECSPI3->CONFIGREG = 0;
ECSPI3->CONFIGREG |= (1 << 20) | (1 << 4) | (1 << 0);
  • bit 20:SCLK_CTL,时钟控制

  • bit 4:DATA_CTL,数据控制

  • bit 0:SS_CTL,片选控制

6. 使能 SPI

c

复制代码
ECSPI3->CONREG |= (1 << 0);

CONREG 的 bit0 是 EN,SPI 使能位。

七、收发数据

c

复制代码
unsigned int ecspi3_write_and_read(unsigned int data)
{
    unsigned int ret = 0;
    while((ECSPI3->STATREG & (1 << 0)) == 0);   // 等 TX FIFO 就绪
    ECSPI3->TXDATA = data;                        // 写数据
    while((ECSPI3->STATREG & (1 << 3)) == 0);   // 等 RX FIFO 有数据
    ret = ECSPI3->RXDATA;                         // 读数据
    return ret;
}

SPI 是全双工的:发一个字节的同时,也收一个字节。

流程:

  1. 等 STATREG 的 bit0(TE,TX FIFO Empty),表示可以写数据

  2. 写 TXDATA

  3. 等 STATREG 的 bit3(RR,RX FIFO Ready),表示收到数据

  4. 读 RXDATA

注意:SPI 没有"只发"或"只收",每次收发都是同时进行的。要读数据,必须发一个"哑字节"(dummy byte,通常是 0xFF)来产生时钟。

八、今日总结

今天学了 GT9147 触摸屏和 SPI 通信,核心要点:

GT9147

  • 电容触摸屏控制器,通过 I2C 通信

  • 引脚:I2C2(SDA、SCL)、GPIO1_IO09(中断)、GPIO5_IO09(复位)

  • 初始化:复位 → 读设备 ID → 配中断 → 进入读坐标模式

  • 中断处理:读触摸点数量 → 读坐标 → 清中断标志

  • 坐标格式:每点 4 字节,X 低、X 高、Y 低、Y 高

SPI

  • 同步串行通信,四根线(SCLK、MOSI、MISO、SS)

  • 全双工:收发同时进行

  • 寄存器:CONREG(控制)、CONFIGREG(配置)、STATREG(状态)、TXDATA/RXDATA(数据)

  • 收发流程:等 TX 就绪 → 写数据 → 等 RX 就绪 → 读数据

  • 特点:速度快,无应答,用片选选择从机

相关推荐
额额额对了2 小时前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
问天_观心2 小时前
大模型训练与推理优化(二)
人工智能·深度学习·学习·大模型·transformer
海海不掉头发3 小时前
软件项目管理学习笔记-从软件危机到敏捷与DevOps
笔记·学习·devops
传奇开心果编程4 小时前
【SwiftUI入门练中学】第7课 动画与手势:让界面更灵动
学习·macos·ui·ios·swiftui·swift
幼儿园蛋小黄4 小时前
SPI 多点触摸屏学习嵌入式总结
学习
dadaobusi4 小时前
学习:顶点着色器输出后,三角形为什么是四个分量
学习
lengxuenong5 小时前
枚举及其优化学习手册
c++·学习·算法·青少年编程
M78佐菲6 小时前
ARM学习笔记(12)
linux·arm开发·笔记·嵌入式硬件·学习
奇思妙想聪明勤奋的小羊6 小时前
ai-agent-book第五章:Coding Agent 与通用 Agent 学习笔记
人工智能·笔记·学习