K230基础-获取触摸坐标

第二十二章 获取触摸坐标-K230触摸屏交互基础

🎯 本章目标

掌握在 K230 开发板(如 CanMV-K230)上通过 I2C 接口获取触摸屏坐标 的方法,学会使用 touch 模块或 I2C 协议读取 X、Y 坐标与触摸状态,实现触摸交互功能,为构建图形用户界面(GUI)打下基础。


1. 触摸屏硬件概述

1.1 常见触摸屏类型

类型 说明 是否适用于 K230
电阻式 压力感应,需按压 ✅ 支持(较少)
电容式 指尖感应,支持多点 ✅ 推荐(常见于 TFT 屏)

📌 K230 典型配置
TFT LCD + 电容触摸屏 (如 2.8"、3.5" 屏),通过 I2C 传输触摸数据。


1.2 主流触摸控制器芯片

芯片 接口 I2C 地址 特点
FT6236 / FT6336 I2C 0x38 电容式,2点触控
GT911 I2C 0x140x5D 多点触控,需配置
XPT2046 SPI - 电阻式,SPI 接口

本章重点FT6336 + I2C 获取触摸坐标(最常见)


2. 硬件连接

触摸屏引脚 K230 引脚 说明
SCL I2C1_SCLK(如 Pin3) I2C 时钟
SDA I2C1_SDA(如 Pin2) I2C 数据
GND GND
VDD 3.3V 电源
INT 可选 GPIO 中断输出(通知有触摸)
RST 可选 GPIO 复位引脚

注意

触摸控制器与 OLED/EEPROM 共用 I2C 总线,需通过 i2c.scan() 确认地址。


3. 使用 touch 模块(CanMV 官方支持)

⚠️ 前提 :固件需包含 touch 模块(非所有版本支持)

python 复制代码
import touch
import time

3.1 初始化触摸屏

python 复制代码
# 创建触摸对象
ts = touch.Touch(screen_width=320, screen_height=240)

# 检查是否初始化成功
if ts.init():
    print("✅ 触摸屏初始化成功")
else:
    print("❌ 触摸屏初始化失败")
    raise Exception("Touch init failed")

3.2 读取触摸坐标

python 复制代码
while True:
    # 获取触摸状态
    touch_points = ts.points()

    if touch_points:
        for point in touch_points:
            x, y, event_type, id = point
            # event_type: 0=按下, 1=释放, 2=移动
            # id: 触摸点 ID
            print(f"触摸: ID={id}, X={x}, Y={y}, 事件={event_type}")
    else:
        # 无触摸
        pass

    time.sleep_ms(10)

输出示例

c 复制代码
触摸: ID=0, X=120, Y=100, 事件=0
触摸: ID=0, X=125, Y=102, 事件=2
触摸: ID=0, X=0, Y=0, 事件=1

4. 手动 I2C 读取触摸数据(通用方法)

若无 touch 模块,可直接通过 I2C 读取触摸芯片寄存器。

4.1 FPIOA 映射与 I2C 初始化

python 复制代码
from fpioa_manager import fm
from machine import I2C, Pin

# I2C 引脚
I2C_SDA = 2
I2C_SCL = 3

fm.register(I2C_SDA, fm.fpioa.I2C1_SDA)
fm.register(I2C_SCL, fm.fpioa.I2C1_SCL)

i2c = I2C(I2C.I2C1, freq=400_000, sda=Pin(I2C_SDA), scl=Pin(I2C_SCL))

4.2 扫描 I2C 设备确认触摸芯片

python 复制代码
devices = i2c.scan()
print("I2C 设备地址:", [hex(dev) for dev in devices])

# FT6336 地址通常为 0x38
TOUCH_ADDR = 0x38
if TOUCH_ADDR not in devices:
    print(f"❌ 未检测到触摸芯片 @ 0x38")
else:
    print(f"✅ 检测到触摸芯片 @ 0x{TOUCH_ADDR:02X}")

4.3 读取 FT6336 触摸数据

python 复制代码
# FT6336 寄存器地址
REG_TD_STATUS = 0x02  # 触摸点数
REG_P1_XH     = 0x03  # 第一个触摸点 X 高位

def read_touch():
    # 读取状态寄存器
    try:
        data = i2c.readfrom_mem(TOUCH_ADDR, REG_TD_STATUS, 1)[0]
        num_points = data & 0x0F

        if num_points > 0:
            # 读取第一个触摸点(2 个字节 X,2 个字节 Y)
            raw = i2c.readfrom_mem(TOUCH_ADDR, REG_P1_XH, 4)

            # 解析 X: [XH(高4位), XL] → 12位
            x = ((raw[0] & 0x0F) << 8) | raw[1]
            # 解析 Y: [YH(高4位), YL]
            y = ((raw[2] & 0x0F) << 8) | raw[3]

            return x, y
        else:
            return None, None
    except:
        return None, None

# 循环读取
while True:
    x, y = read_touch()
    if x is not None and y is not None:
        print(f"触摸坐标: X={x}, Y={y}")
    else:
        # print("无触摸")
        pass
    time.sleep_ms(50)

5. 坐标映射到屏幕显示区域

触摸屏原始坐标通常为 0~4095,需映射到屏幕分辨率(如 320x240)。

python 复制代码
def map_touch_to_screen(x_raw, y_raw, screen_w=320, screen_h=240):
    x = int(x_raw * screen_w / 4095)
    y = int(y_raw * screen_h / 4095)
    return x, y

# 使用
x_raw, y_raw = read_touch()
if x_raw:
    x, y = map_touch_to_screen(x_raw, y_raw)
    print(f"屏幕坐标: X={x}, Y={y}")

校准建议:实际使用中可能需手动校准映射系数。


6. 实战项目:触摸点显示在 TFT 屏上

python 复制代码
# 假设已初始化 TFT 屏幕(见第13章)
import st7789
import vga1_8x8 as font

# 清屏
tft.fill(0)
tft.text(font, "触摸测试", 100, 100, st7789.YELLOW)

while True:
    x_raw, y_raw = read_touch()

    if x_raw and y_raw:
        # 映射到 240x240 屏幕
        x = int(x_raw * 240 / 4095)
        y = int(y_raw * 240 / 4095)

        # 限制范围
        x = max(0, min(239, x))
        y = max(0, min(239, y))

        # 显示触摸点
        tft.fill(0)  # 清屏
        tft.text(font, "Touch:", 10, 10, st7789.CYAN)
        tft.text(font, f"X={x}", 10, 30, st7789.YELLOW)
        tft.text(font, f"Y={y}", 10, 50, st7789.YELLOW)
        tft.pixel(x, y, st7789.RED)  # 画点
        tft.circle(x, y, 5, st7789.GREEN)  # 画圈
    else:
        tft.fill_rect(10, 70, 200, 20, 0)  # 清除提示

7. 高级技巧与优化

7.1 使用中断引脚(INT)减少轮询

python 复制代码
from machine import Pin

INT_PIN = 12
fm.register(INT_PIN, fm.fpioa.GPIOHS0)
int_pin = Pin(INT_PIN, Pin.IN)

# 仅在 int_pin.value() == 0 时读取触摸
if not int_pin.value():
    x, y = read_touch()

优势:降低 CPU 占用


7.2 触摸事件去抖与滤波

python 复制代码
last_x, last_y = None, None
threshold = 5

def smooth_touch(new_x, new_y):
    global last_x, last_y
    if last_x is None:
        last_x, last_y = new_x, new_y
        return new_x, new_y

    # 简单滤波
    x = (last_x * 2 + new_x) // 3
    y = (last_y * 2 + new_y) // 3
    last_x, last_y = x, y
    return x, y

8. 常见问题与调试

❌ 问题1:无法读取触摸数据

排查

  • I2C 地址是否正确?
  • 接线是否松动?
  • 电源是否稳定?

❌ 问题2:坐标跳变或不准

解决

  • 增加滤波(均值、中值)
  • 检查屏幕方向是否匹配
  • 手动校准映射参数

❌ 问题3:touch 模块导入失败

原因 :固件未包含该模块
解决:使用 I2C 手动读取(通用方法)


9. 性能与限制

操作 耗时
I2C 读取一次 ~2ms
坐标解析 < 0.1ms
轮询频率 建议 10~50ms 间隔

建议

  • 使用定时器周期读取
  • 结合 GUI 框架实现按钮、滑动等交互

本章你已掌握

  • 触摸屏硬件连接与 I2C 通信
  • 使用 touch 模块获取坐标
  • 手动 I2C 读取 FT6336 数据
  • 坐标映射与显示
  • 触摸去抖与优化

相关推荐
小鱼儿电子1 小时前
46-基于STM32的智能宠物屋设计与实现
stm32·腾讯云·宠物屋·智能宠物屋
Jerry丶Li2 小时前
十九、STM32的TIM(十)(编码器)
stm32·单片机·嵌入式硬件
IT阳晨。2 小时前
【STM32】串口通信及相关实验和项目
stm32·单片机·嵌入式硬件
安庆平.Я11 小时前
STM32——IWDG
stm32·单片机·嵌入式硬件
太空1号11 小时前
VxWorks入门小白菜鸟教程4 —— 异步I/O库(AIO)的使用
嵌入式硬件
怀民民民11 小时前
轮询&中断 串口实训
单片机·嵌入式硬件·串口·中断·轮询·学习日志·keill
卍郝凝卍12 小时前
NVR(网络视频录像机)和视频网关的工作方式
网络·图像处理·物联网·音视频·视频解决方案
kaka❷❷12 小时前
STM32 单片机 ESP8266 联网 和 MQTT协议
stm32·单片机·嵌入式硬件·物联网·mqtt·esp8266
古译汉书13 小时前
Stm32江科大入门教程--各章节详细笔记---查阅传送门
数据结构·stm32·单片机·嵌入式硬件·算法
brave and determined14 小时前
硬件-内存学习DAY20——GDDR6革命:显存技术如何重塑游戏与AI未来
嵌入式硬件·ddr·ddr4·ddr5·ddr6·内存原理·内存技术