文章目录
-
- 前言
- 一、PWM控制LCD亮度
-
- [1.1 PWM](#1.1 PWM)
- [1.2 PWM引脚配置](#1.2 PWM引脚配置)
- [1.3 PWM寄存器配置](#1.3 PWM寄存器配置)
- [1.4 PWM控制亮度具体实现](#1.4 PWM控制亮度具体实现)
- 二、GT9147触控芯片
-
- [2.1 触控屏种类](#2.1 触控屏种类)
- [2.2 GT9147](#2.2 GT9147)
-
- [2.2.1 I2C](#2.2.1 I2C)
- [2.2.2 中断与复位引脚配置](#2.2.2 中断与复位引脚配置)
- [2.2.3 芯片的地址](#2.2.3 芯片的地址)
- [2.2.4 芯片复位及参数获取](#2.2.4 芯片复位及参数获取)
- [2.2.5 点坐标的获取](#2.2.5 点坐标的获取)

前言
在上篇【ARM 裸机开发 (IMX6ULL-mini)】RGB-LCD 驱动与时序详解文章中,对LCD屏进行了一定的了解与基本使用;在上篇文章中提到有一个引脚PWM是决定屏幕显示亮度的,在本片文章中会对其具体使用进行解释;除此之外,在现代的显示器使用中,屏幕的作用并不单单只是显示图像了,还能够根据触摸做出应答。因此,本篇文章还会详细讲解触控芯片gt1148。
一、PWM控制LCD亮度
1.1 PWM
在昨天的LCD代码中:

我们将PWM输出的引脚直接设置为高电平,使LCD屏幕满亮度显示。在这篇文章中我们将通过这个引脚输出PWM来实现亮度的控制。我们重新创建一个PWM的文件来放关于这个PWM输出引脚的代码,将之前关于这个引脚的代码全部注释掉。
IMX6ULL中PWM的原理框图:

FIFO 深度 = 4,可以预先缓存 4 组占空比样本。写 PWMSAR 就是往 FIFO 压入占空比数值。
1.2 PWM引脚配置
在IMX6ULL原理图中,这个PWM引脚为GPIO8的复用功能。

在参考手册中,我们需要找到这个引脚使用的为PWM1。

我们需要先将其引脚复用功能配置为PWM输出功能,并配置电气属性:

1.3 PWM寄存器配置
接下来就是对PWM相关的寄存器进行配置:

| 寄存器名 | 英文全称 | 中文名称 | 核心功能 |
|---|---|---|---|
| PWMx_PWMCR | PWM Control Register | PWM 控制寄存器 | 最核心寄存器:PWM 模块使能、时钟源选择、预分频、输出极性、FIFO 水位、休眠控制、重载模式等 |
| PWMx_PWMSR | PWM Status Register | PWM 状态寄存器 | 状态标志位:FIFO 满 / 空、中断标志、错误状态,用来查询 PWM 运行状态 |
| PWMx_PWMIR | PWM Interrupt Register | PWM 中断寄存器 | 中断使能配置,开启 / 关闭各类 PWM 中断(FIFO 中断、比较中断等) |
| PWMx_PWMSAR | PWM Sample Register | PWM 采样寄存器(FIFO 数据寄存器) | 存放 PWM 占空比计数值,写这个寄存器把占空比送入硬件 FIFO |
| PWMx_PWMPR | PWM Period Register | PWM 周期寄存器 | 设置 PWM 输出周期,决定 PWM 频率 公式:PWM 频率 = PWM 时钟 / (PWMPR + 2) |
| PWMx_PWMCNR | PWM Counter Register | PWM 计数寄存器 | 只读,PWM 内部当前计数值,可以读取计数器实时数值 |
PWMx_PWMCR



PWMx_PWMSR

PWMx_PWMIR

PWMx_PWMSAR

PWMx_PWMPR

1.4 PWM控制亮度具体实现

c
float global_ratio = 1.0;
//设置占空比
void set_ratio(void)
{
int i = 0;
for (i = 0; i < 4; i++)
{
PWM1->PWMSAR = PWM1->PWMPR * global_ratio;
}
}
//FIFO空中断服务函数
void pwm1_interrupt_handler(void)
{
if((PWM1->PWMSR & (1 << 3)) != 0)
{
set_ratio();
PWM1->PWMSR |= (1 << 3);
}
}
void pwm1_init(void)
{
//引脚复用
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_PWM1_OUT, 0);
//引脚电气配置
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_PWM1_OUT, 0xB9);
PWM1->PWMCR = 0;
PWM1->PWMCR |= (1 << 26) | (1 << 16) | (65 << 4) | (3 << 1);
PWM1->PWMIR |= (1 << 0);
PWM1->PWMPR = 998;
set_ratio();
//注册PWM1中断
system_interrupt_register(PWM1_IRQn, pwm1_interrupt_handler);
// 设置PWM1中断优先级
GIC_SetPriority(PWM1_IRQn, 0);
// GIC使能PWM1中断
GIC_EnableIRQ(PWM1_IRQn);
//使能 PWM1
PWM1->PWMCR |= (1 << 0);
}
通过改变global_ratio就可以达到改变亮度的效果。
二、GT9147触控芯片
2.1 触控屏种类
| 项目 | 电容触控屏 | 四线电阻触摸屏 |
|---|---|---|
| 检测对象 | 感应电压变化量(mV级),检测电场耦合变化 | 触摸点分压电压,电压值直接对应位置 |
| 电压来源 | TX电极输出交流驱动,RX电极感应得到微弱感应电压 | 在ITO导电层两端施加直流参考电压,按压触点产生分压 |
| 触发条件 | 导电物体(手指/电容笔),不需要压力 | 需要按压,使两层ITO膜接触,指甲、塑料笔均可触摸 |
| 多点触摸 | 支持多点触摸 | 只支持单点触摸 |
| 校准需求 | 一般出厂校准,用户基本无需重新校准 | 装配、温度会带来偏差,嵌入式产品需要开机5点校准 |
在正点原子IMX6ULL这块上我们使用的使GT9147触控芯片。
2.2 GT9147
2.2.1 I2C

显而易见,这个触控芯片采用I2C协议通信,因此我们需要先将I2C2进行初始化:
在【ARM 裸机开发 (IMX6ULL-mini)】I2C协议详解这篇文章中有对I2C协议的详细解释,我们只需要将I2C1改为I2C2就可以应用到触控芯片中使用。
这里,为了方便I2C的使用,我们定义了一个关于I2C信息的结构体,以及一个读写的复用函数:


这样就可以实现GT9147的读写函数了:

2.2.2 中断与复位引脚配置
除此以外,我们还需要对中断与复位两个引脚进行配置:

2.2.3 芯片的地址
在这个屏幕提供的芯片编程指南中,有两种触控芯片:GT1158和GT9147;
因此,它们作为从机的地址也不同:

GT9147 与主机通信采用标准 I2C 通信,最高速率可以支持至 400Kbps。当主机采用 200 Kbps 以上的通信速率时,需要特别注意 I2C 的外部上拉电阻阻值,以保证SCL、SDA边沿足够陡峭。其2C设备地址由7位设备地址加1位读写控制位组成,高7位为地址,bit0为读写控制位。
2.2.4 芯片复位及参数获取
每次上电或复位时需要使用INT脚进行C地址设置。经过测试发现,两种芯片的复位方式是一样的。

代码实现:

要使用触控功能,首先我们需要确认它的ID型号,通过I2C协议读取0x8140的四个字节,就可以得到它的ID以及INT引脚的中断触发方式:


得到INT中断触发方式后,我们需要对IMX6ULL上的INT引脚寄存器进行配置:

然后就是注册中断服务函数,设置优先级,使能中断这一套老招数了:

这样,我们的GT9147初始化就完成了。
2.2.5 点坐标的获取
接下来,就是对GT9147触控芯片的简单使用了,所有的触控操作肯定都是建立在知道你触摸的点在哪里的前提下,因此,在这篇文章中我们就来实现触摸点坐标的获取。

我们定义这样一个结构体来存储触摸时的数据。
在芯片的编程手册中,给出了坐标信息:


这里编程手册写错了,五个触控点存储的位置分别为:0x8150, 0x8158, 0x8160, 0x8168, 0x8170;
根据地址特性,我们这样定义一个数组来存储地址:

实现代码:
- I2C 读
0x814E→ 获取触摸点个数 - 根据点数,依次读取每个触摸点 4 字节,拼接 X、Y 原始坐标
- 设置 available 标记,告诉主程序有无触摸
- 写 0 到 0x814E ,清除中断 / 就绪标志,GT9147 准备下一轮检测

我们将其显示在LCD屏幕上:

这样就完成了触控芯片的简单使用了,更多的使用等待后面分享吧!