【Avnet | NXP FRDM-MCXN947试用活动】测评6--移植触摸屏
# 触摸屏介绍触摸屏介绍参见(https://www.eefocus.com/forum/forum.php?mod=forumdisplay&fid=353&filter=typeid&typeid=1316)
它的主要几个参数如下:
| 项目 | 参数 | 单位 |
| ------ | ----------------------- | ------ |
| 有效区尺寸| 3.2 | inch |
| 触摸屏类型| 电容触摸屏 | - |
| 触摸屏分辨率 | 240x320 | pixels |
| 驱动IC | FT6336U | - |
| 可视窗口尺寸 | 49.20±0.15(W)x65.40±(H) | mm |
| 通信接口 | IIC | - |
| 结构材质 | G+F | - |
| 工作温度 | -20~60 | ℃ |
| 存储温度 | -30~70 | ℃ |
## 与MCXN947连接关系
触摸屏信号包含通信信号和复位信号。这里4个管脚全部配置为 GPIO ,用 GPIO 模拟 IIC。
| 编号| MCXN947 管脚 | 触摸屏管脚 | 说明 |
| --- | -------------- | ------- | ------------------------------- |
| 1 | J4.6-- P0_14 | CTP_SCL | 电容触摸屏IIC总线时钟信号 |
| 2 | J4.8-- P0_22 | CTP_RST | 电容触摸屏复位控制信号,低电平复位 |
| 3 | J4.10 -- P0_15 | CTP_SDA | 电容触摸屏IIC总线数据信号 |
| 4 | J4.5-- P4_16 | CTP_INT | 电容触摸屏IIC总线触摸中断信号,产生触摸时,输入低电平到主控 |
# 移植触摸接口
这里选择GPIO模拟IIC的通信方式,简单,易于移植。
参考 (https://www.eefocus.com/forum/forum.php?mod=forumdisplay&fid=353&filter=typeid&typeid=1316)
## 管脚配置
使用 MCUXpresso Config Tools 大大方便管脚配置工作。
!(https://www.eefocus.com/forum/data/attachment/forum/202411/29/101218ghespc4rctrtmcce.png)
!(https://www.eefocus.com/forum/data/attachment/forum/202411/29/101253s2212w9ff2dh2mff.png)
保存配置生成代码,最终生成两个函数 `TFT_Touch_Init()`, `TFT_Touch_Deinit()` 其中 `TFT_Touch_Init()` 函数定义如下,会被 `BOARD_InitBootPins()` 调用,无需我们手动调用。
```c
void TFT_Touch_Init(void)
{
/* Enables the clock for GPIO0: Enables clock */
CLOCK_EnableClock(kCLOCK_Gpio0);
/* Enables the clock for GPIO4: Enables clock */
CLOCK_EnableClock(kCLOCK_Gpio4);
/* Enables the clock for PORT0 controller: Enables clock */
CLOCK_EnableClock(kCLOCK_Port0);
/* Enables the clock for PORT4: Enables clock */
CLOCK_EnableClock(kCLOCK_Port4);
gpio_pin_config_t CTP_SCL_config = {
.pinDirection = kGPIO_DigitalOutput,
.outputLogic = 0U
};
/* Initialize GPIO functionality on pin PIO0_14 (pin E11)*/
GPIO_PinInit(TFT_TOUCH_INIT_CTP_SCL_GPIO, TFT_TOUCH_INIT_CTP_SCL_PIN, &CTP_SCL_config);
gpio_pin_config_t CTP_SDA_config = {
.pinDirection = kGPIO_DigitalOutput,
.outputLogic = 0U
};
/* Initialize GPIO functionality on pin PIO0_15 (pin G13)*/
GPIO_PinInit(TFT_TOUCH_INIT_CTP_SDA_GPIO, TFT_TOUCH_INIT_CTP_SDA_PIN, &CTP_SDA_config);
gpio_pin_config_t CTP_RST_config = {
.pinDirection = kGPIO_DigitalOutput,
.outputLogic = 0U
};
/* Initialize GPIO functionality on pin PIO0_22 (pin B8)*/
GPIO_PinInit(TFT_TOUCH_INIT_CTP_RST_GPIO, TFT_TOUCH_INIT_CTP_RST_PIN, &CTP_RST_config);
gpio_pin_config_t CTP_INT_config = {
.pinDirection = kGPIO_DigitalInput,
.outputLogic = 0U
};
/* Initialize GPIO functionality on pin PIO4_16 (pin R8)*/
GPIO_PinInit(TFT_TOUCH_INIT_CTP_INT_GPIO, TFT_TOUCH_INIT_CTP_INT_PIN, &CTP_INT_config);
/* PORT0_14 (pin E11) is configured as PIO0_14 */
PORT_SetPinMux(TFT_TOUCH_INIT_CTP_SCL_PORT, TFT_TOUCH_INIT_CTP_SCL_PIN, kPORT_MuxAlt0);
PORT0->PCR = ((PORT0->PCR &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
/* PORT0_15 (pin G13) is configured as PIO0_15 */
PORT_SetPinMux(TFT_TOUCH_INIT_CTP_SDA_PORT, TFT_TOUCH_INIT_CTP_SDA_PIN, kPORT_MuxAlt0);
PORT0->PCR = ((PORT0->PCR &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
/* PORT0_22 (pin B8) is configured as PIO0_22 */
PORT_SetPinMux(TFT_TOUCH_INIT_CTP_RST_PORT, TFT_TOUCH_INIT_CTP_RST_PIN, kPORT_MuxAlt0);
PORT0->PCR = ((PORT0->PCR &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
/* PORT4_16 (pin R8) is configured as PIO4_16 */
PORT_SetPinMux(TFT_TOUCH_INIT_CTP_INT_PORT, TFT_TOUCH_INIT_CTP_INT_PIN, kPORT_MuxAlt0);
PORT4->PCR = ((PORT4->PCR &
/* Mask bits to zero which are setting */
(~(PORT_PCR_IBE_MASK)))
/* Input Buffer Enable: Enables. */
| PORT_PCR_IBE(PCR_IBE_ibe1));
}
```
## 触摸接口文件说明
此屏幕厂商给的触摸屏相关的文件如下:
1. **touch.h** 是触摸屏对外的接口文件,声明 `TP_Init()` 函数和一个全局变量 `extern _m_tp_dev tp_dev` 表示触摸状态信息;
2. **touch.c** 是触摸屏接口实现文件,实现 `TP_init()` 函数并初始化全局变量 `tp_dev`;
3. **ctpiic.h** 是IIC接口的声明,这里以GPIO模拟IIC,所以需要提供 IIC 各种基础信号的声明,如发出起始信号、停止信号、发送一个字节、读取一个字节、发送ACK、接收ACK等基础信号的声明;
4. **ctpiic.c** 是IIC接口的实现,以GPIO模拟IIC的实现;
5. **ft6336.h** 是这颗 FT6336 触摸IC的驱动文件,包含寄存器定义和寄存器读写函数、获取触摸状态信息的函数的声明;
6. **ft6336.c** 是这颗 FT6336 触摸IC驱动的实现文件,包含寄存器读写函数的实现、扫描触摸屏获取状态的函数的实现;
## 触摸接口移植适配
主要适配工作是GPIO模拟IIC功能的实现,即修改 **ctpiic.c** 和 **ctpiic.h** 文件。
在头文件中需要提供几个宏定义,如下所示,因为是 GPIO 模拟 IIC,所以需要实现如下的 API:
1. `CTP_IIC_Init()` 初始化 IIC 两个管脚,初始配置为输出模式,高电平;
2. `CTP_IIC_Start()` IIC 作为 Master 发起起始信号;
3. `CTP_IIC_Stop()`IIC 作为 Master 发起结束信号;
4. `CTP_IIC_Send_Byte()` IIC 以GPIO模拟的方式,移位以 MSB 的方式发送一个字节;
5. `CTP_IIC_Read_Byte()`IIC 切换 SDA 为输入方向,读取一个字节;
6. `CTP_IIC_Wait_Ack()`IIC 作为 Master 等待 ACK 信号;
7. `CTP_IIC_Ack()` IIC 发送一个 ACK 信号;
8. `CTP_IIC_Nack()` IIC 发送一个 NAK 信号;
虽说有这么多的接口需要实现,但实际上我只需要实现 `CTP_IIC_Init()` 初始化 SCL/SDA 对应的两个管脚,然后实现下面的几个宏定义即可,如下代码所示:
1. `CTP_SDA_IN()` 切换 SDA 管脚为输入方向,每种MCU的驱动调用不同,这里调用 NXP 的 API 也同时以寄存器的访问方式相结合,实现 SDA 管脚切换为输入方式;
2. `CTP_SDA_OUT()` 切换为 SDA 管脚为输出方向,原理同上;
3. `CTP_IIC_SCL(n)` 实现 SCL 管脚输出高低电平;
4. `CTP_IIC_SDA(n)` 实现 SDA 管脚输出高低电平;
5. `CTP_READ_SDA` 实现读取 SDA 管脚输入电平,这几个宏定义直接调用 NXP 的库函数即可;
```c
#ifndef __CTPIIC_H
#define __CTPIIC_H
#include <stdint.h>
#include "pin_mux.h"
#include "fsl_gpio.h"
//IIC IO方向设置
#define CTP_SDA_IN() \
do { \
GPIO_PortInputEnable(TFT_TOUCH_INIT_CTP_SDA_GPIO, TFT_TOUCH_INIT_CTP_SDA_GPIO_PIN_MASK);\
TFT_TOUCH_INIT_CTP_SDA_GPIO->PDDR &= GPIO_FIT_REG(~(1UL << TFT_TOUCH_INIT_CTP_SDA_GPIO_PIN)); \
} while (0)
#define CTP_SDA_OUT() \
do { \
GPIO_PortInputDisable(TFT_TOUCH_INIT_CTP_SDA_GPIO, TFT_TOUCH_INIT_CTP_SDA_GPIO_PIN_MASK); \
TFT_TOUCH_INIT_CTP_SDA_GPIO->PDDR |= GPIO_FIT_REG(1UL << TFT_TOUCH_INIT_CTP_SDA_GPIO_PIN); \
} while (0)
//IO操作函数
#define CTP_IIC_SCL(n) GPIO_PinWrite(TFT_TOUCH_INIT_CTP_SCL_GPIO, TFT_TOUCH_INIT_CTP_SCL_GPIO_PIN, (n))
#define CTP_IIC_SDA(n) GPIO_PinWrite(TFT_TOUCH_INIT_CTP_SDA_GPIO, TFT_TOUCH_INIT_CTP_SDA_GPIO_PIN, (n))
#define CTP_READ_SDA GPIO_PinRead(TFT_TOUCH_INIT_CTP_SDA_GPIO, TFT_TOUCH_INIT_CTP_SDA_GPIO_PIN)
//IIC所有操作函数
void CTP_IIC_Init(void);
void CTP_IIC_Start(void);
void CTP_IIC_Stop(void);
void CTP_IIC_Send_Byte(uint8_t txd);
uint8_t CTP_IIC_Read_Byte(unsigned char ack);
uint8_t CTP_IIC_Wait_Ack(void);
void CTP_IIC_Ack(void);
void CTP_IIC_NAck(void);
#endif
```
后面的几个 API 都依赖于上面的宏定义,我们无需过多关心。下面给出其中一个函数的实现,可以看出都依赖于上面的宏定义。
```c
void CTP_IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
CTP_SDA_OUT();
CTP_IIC_SCL(0);//拉低时钟开始数据传输
for (t = 0;t < 8;t++)
{
CTP_IIC_SDA((txd & 0x80) >> 7);
txd <<= 1;
CTP_IIC_SCL(1);
CTP_Delay();
CTP_IIC_SCL(0);
CTP_Delay();
}
}
```
# 运行效果
先运行厂商提供的触摸屏测试程序,发现很卡,屏幕刷新很卡,触摸屏也不灵敏。这个是由原因的,模组厂商的刷屏函数是一个一个打点,没有发挥 FLEXIO_SPI_EDMA 的优势,所以刷屏很卡,继而影响触摸效果。
视频参见B站:
(https://www.bilibili.com/video/BV1c4BRYtEBY/?vd_source=8f2bbf56b70c541bec2ea0b9f102ebee)
下一个帖子 LVGL 移植触摸,效果好很多。
页:
[1]