找回密码
 立即注册
查看: 66|回复: 10

STC32G12K128接电阻式触摸TFT彩屏, 用MCU自己的ADC实现触摸检测

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 5 天前 | 显示全部楼层 |阅读模式
STC32G12K128接电阻式触摸TFT彩屏,
用MCU自己的ADC实现触摸检测,
想把XPT2046触摸屏检测芯片去掉,


帮提供方案
截图202606301018561218.jpg

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 5 天前 | 显示全部楼层

好的,我来为您整理 STC32G12K128 片内 ADC 直驱 4 线电阻触摸屏、去掉 XPT2046 的完整方案


✅ 方案可行性结论

完全可以。STC32G12K128 内置 12位高速ADC(15通道),性能足够替代 XPT2046 实现电阻触摸检测。论坛已有成功先例:

网友实测: 利用 STC32G12K128 的 ADC 直连电阻触摸 TFT 彩屏,手写识别效果很好
—— 来源:STC 论坛 #11264(乘风*** 帖 & 神*** 回复确认)


🔧 方案原理

4 线电阻触摸屏结构

触摸屏有 4 根线:X+、X-、Y+、Y-

检测内容 供电方向 从哪根线读取电压
X 坐标 X+ → VCC, X- → GND Y+(或 Y-)上测电压
Y 坐标 Y+ → VCC, Y- → GND X+(或 X-)上测电压
触摸检测 任一方向通电后,检测 ADC 值是否变化

🔌 硬件接线方案(推荐)

用 STC32G12K128 4 个 I/O 口接触摸屏的 4 根线,其中至少 2 个必须是 ADC 通道

触摸屏引脚 接 MCU 引脚 功能说明
X+ P1.0 / ADC0 既可当 ADC 输入(读 Y 坐标),也可推挽输出 VCC
X- P1.1 / ADC1 或 普通 I/O 既可当 ADC 输入,也可推挽输出 GND
Y+ P1.4 / ADC4 或 普通 I/O 推挽输出 VCC(读 X 坐标时)或高阻输入(读 Y 坐标)
Y- P1.5 / ADC5 或 普通 I/O 推挽输出 GND(读 X 坐标时)或高阻输入(读 Y 坐标)

引脚选择建议: STC32G12K128 的 ADC 通道有 ADC0ADC14,分布在 P1.0/P1.1/P1.4P1.7、P0.0~P0.7 等引脚(详见手册第4章管脚功能表)。
建议选 P1 口(P1.0/P1.1/P1.4/P1.5),它们自带 ADC 功能,并且不和 TFT 并口/LCM 接口冲突。

Vref+ 必须处理

STC32G12K128 的 Vref+(第20脚) 不能浮空,必须接:

  • 方案 A(推荐): Vref+ 直接短接到 VCC,用 VCC 作 ADC 基准(论坛案例即用此法)
  • 方案 B: 外接精密基准(如 TL431/REF3025)

🧠 软件控制逻辑

步骤一:检测触摸(是否有按下)

X+ 推挽输出高,X- 推挽输出低(或反之)
Y+、Y- 设为高阻输入,不参与
ADC 读取 Y+(或 Y-)上的电压
若 ADC 值在合理范围内 → 有触摸

步骤二:读取 X 坐标

X+ → 推挽输出高
X- → 推挽输出低
Y+ → 高阻输入(作为 ADC 采样脚)
Y- → 高阻输入(悬空)
ADC 通道切换到 Y+(如 ADC4)读取电压值

步骤三:读取 Y 坐标

Y+ → 推挽输出高
Y- → 推挽输出低
X+ → 高阻输入(作为 ADC 采样脚,如 ADC0)
X- → 高阻输入(悬空)
ADC 通道切换到 X+(如 ADC0)读取电压值

提高效率的技巧

论坛回复中提到:

"用 DMA 来支持 ADC,这样减少 CPU 的压力 —— STC32G12K128 有 DMA 支持 ADC"(来源:神*** 回复,帖子 #10867)

STC32G 手册第 30 章 DMA 支持 ADC→内存传输,可实现自动连续采样,CPU 只需读取最终结果,大幅提升触摸响应速度。


⚠️ 注意事项

注意事项 说明
I/O 模式切换 检测时需快速切换 I/O 的推挽输出/高阻模式,注意设置 PxM0/PxM1 寄存器
ADC 时序 ADC 时钟 = sysclk/2/分频系数,建议设置 ADCTIM 和 ADCCFG 优化采样速度
校准 四角校准法:触摸屏四角采集 ADC 值,建立线性映射关系
手写 vs 菜单 做菜单按键效果很好;手写可接受但精度不如专用芯片(XPT2046)
触摸中断 可将某根线接到带中断的 I/O 口(如 INT0/INT1),实现触摸唤醒省电

📚 参考资料

  1. STC32G 数据手册 — 第 22 章 ADC(12位ADC寄存器及例程)、第 30 章 DMA
  2. 论坛成功案例

如果您需要,我可以进一步提供具体的初始化代码框架或引脚分配方案。


🔍 搜索 "STC32G12K128接电阻式触摸TFT彩屏 用MCU自己的ADC实现触摸检测 想把 XPT2046触摸屏检测芯片去掉"

📌 相关论坛讨论

  1. STC8H8K64U接电阻式触摸TFT彩屏,用MCU自己的ADC实现触摸
  2. 请教一下 《38-2.4寸 ILI9325驱动TFT显示屏实验程序-带触摸功能》
  3. 请帮忙推荐一个试验箱
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 5 天前 | 显示全部楼层

有具体的参考程序吗

截图202606301021533252.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 5 天前 | 显示全部楼层

好的,以下是为 STC32G12K128 量身整理的完整参考程序。程序基于 4 线电阻触摸屏 的驱动原理,使用片内 12位ADC 分时切换测量 X/Y 坐标,并包含触摸检测功能。


📁 参考程序(C语言,适用于 STC32G12K128)

/******************************************************************************
 * 文件名:Touch_ADC_STC32G12K128.c
 * 功能  :使用 STC32G12K128 片内 ADC 驱动 4 线电阻触摸屏
 *         替代 XPT2046 触摸检测芯片
 * 硬件连接:
 *   触摸屏 X+  → P1.0 (ADC0)   — 既是ADC输入,也做驱动输出
 *   触摸屏 X-  → P1.1 (ADC1)   — 既是ADC输入,也做驱动输出
 *   触摸屏 Y+  → P1.4 (ADC4)   — 既是ADC输入,也做驱动输出
 *   触摸屏 Y-  → P1.5 (ADC5)   — 既是ADC输入,也做驱动输出
 *   Vref+     → 接 VCC(用VCC做ADC基准)
 * 工作频率 :11.0592MHz / 40MHz 均可
 ******************************************************************************/

#include "stc32g.h"
#include "intrins.h"

// 触摸屏引脚定义(可自行修改)
#define TOUCH_XP_PIN     1   // P1.0
#define TOUCH_XM_PIN     1   // P1.1
#define TOUCH_YP_PIN     4   // P1.4
#define TOUCH_YM_PIN     5   // P1.5

#define ADC_XP_CH    0       // ADC通道0 → P1.0
#define ADC_XM_CH    1       // ADC通道1 → P1.1
#define ADC_YP_CH    4       // ADC通道4 → P1.4
#define ADC_YM_CH    5       // ADC通道5 → P1.5

// 触摸阈值(根据实际屏体调试)
#define TOUCH_THRESHOLD     200     // 低于此值认为有触摸按下

// 触摸坐标结构体
typedef struct {
    uint16_t x;
    uint16_t y;
    uint8_t  pressed;
} TouchPoint_t;

// 全局变量
TouchPoint_t g_tTouch;

//---------------------------------------------------------------------------
// 函数原型
void Touch_GPIO_Init(void);
void Touch_ADC_Init(void);
uint16_t Touch_ReadADC(uint8_t ch);
void Touch_SetDrive_X(void);     // X方向供电
void Touch_SetDrive_Y(void);     // Y方向供电
void Touch_SetIdle(void);        // 高阻空闲
uint8_t Touch_DetectPress(void);
uint16_t Touch_ReadX(void);
uint16_t Touch_ReadY(void);
void Touch_GetPoint(TouchPoint_t *pt);
void delay_us(uint16_t us);

//---------------------------------------------------------------------------
// GPIO初始化:所有触摸引脚设为高阻输入
void Touch_GPIO_Init(void)
{
    // P1.0, P1.1, P1.4, P1.5 设为高阻输入(ADC模式)
    P1M0 &= ~(0x33);    // P1.0/P1.1/P1.4/P1.5 的M0位清零
    P1M1 |=  (0x33);    // P1.0/P1.1/P1.4/P1.5 的M1位置1 → 高阻
}

//---------------------------------------------------------------------------
// ADC初始化(12位,右对齐,最快速度)
void Touch_ADC_Init(void)
{
    EAXFR = 1;                  // 使能访问XFR
    ADCTIM = 0x3F;              // ADC内部时序:最长采样时间
    ADCCFG = 0x20 | 0x00;       // bit5(RESFMT)=1: 右对齐;SPEED=0: 最快速度
    ADC_POWER = 1;              // 使能ADC模块
    delay_us(10);               // 等待ADC稳定
}

//---------------------------------------------------------------------------
// 读取单次ADC值(查询方式)
uint16_t Touch_ReadADC(uint8_t ch)
{
    uint16_t res;

    ADC_CONTR = (ADC_CONTR & 0xF0) | ch;   // 选择ADC通道
    ADC_START = 1;                          // 启动转换
    _nop_(); _nop_();
    while (!ADC_FLAG);                      // 等待转换完成
    ADC_FLAG = 0;                           // 清除标志

    res = ((uint16_t)ADC_RES << 8) | ADC_RESL;  // 12位结果(右对齐)
    return res;
}

//---------------------------------------------------------------------------
// X方向供电:X+ → VCC,X- → GND
// Y+、Y- 为高阻输入,作为ADC采样点
void Touch_SetDrive_X(void)
{
    // X+ (P1.0) → 推挽输出高
    P1M0 |= 0x01;   P1M1 &= ~0x01;
    P10 = 1;

    // X- (P1.1) → 推挽输出低
    P1M0 |= 0x02;   P1M1 &= ~0x02;
    P11 = 0;

    // Y+ (P1.4)、Y- (P1.5) → 高阻输入(ADC采样)
    P1M0 &= ~0x30;  P1M1 |= 0x30;
}

//---------------------------------------------------------------------------
// Y方向供电:Y+ → VCC,Y- → GND
// X+、X- 为高阻输入,作为ADC采样点
void Touch_SetDrive_Y(void)
{
    // Y+ (P1.4) → 推挽输出高
    P1M0 |= 0x10;   P1M1 &= ~0x10;
    P14 = 1;

    // Y- (P1.5) → 推挽输出低
    P1M0 |= 0x20;   P1M1 &= ~0x20;
    P15 = 0;

    // X+ (P1.0)、X- (P1.1) → 高阻输入(ADC采样)
    P1M0 &= ~0x03;  P1M1 |= 0x03;
}

//---------------------------------------------------------------------------
// 全部引脚恢复高阻(空闲状态/省电)
void Touch_SetIdle(void)
{
    P1M0 &= ~0x33;
    P1M1 |= 0x33;
}

//---------------------------------------------------------------------------
// 检测是否有触摸按下
uint8_t Touch_DetectPress(void)
{
    uint16_t val;

    // 随便选一个方向供电,看ADC是否有变化
    Touch_SetDrive_X();
    delay_us(5);

    // 从Y+读取电压
    val = Touch_ReadADC(ADC_YP_CH);
    Touch_SetIdle();

    // 有触摸时ADC值较低(相当于分压接地)
    // 无触摸时IO浮空,ADC值接近满量程(4095)
    if (val < TOUCH_THRESHOLD)
        return 1;   // 检测到触摸
    else
        return 0;   // 无触摸
}

//---------------------------------------------------------------------------
// 读取X坐标
uint16_t Touch_ReadX(void)
{
    uint16_t val;

    Touch_SetDrive_X();
    delay_us(5);

    // X方向供电时,在Y+上读取X坐标分压
    val = Touch_ReadADC(ADC_YP_CH);
    Touch_SetIdle();

    return val;     // 原始ADC值,范围0~4095
}

//---------------------------------------------------------------------------
// 读取Y坐标
uint16_t Touch_ReadY(void)
{
    uint16_t val;

    Touch_SetDrive_Y();
    delay_us(5);

    // Y方向供电时,在X+上读取Y坐标分压
    val = Touch_ReadADC(ADC_XP_CH);
    Touch_SetIdle();

    return val;     // 原始ADC值,范围0~4095
}

//---------------------------------------------------------------------------
// 一次完整的触摸采样(含消抖、坐标读取)
void Touch_GetPoint(TouchPoint_t *pt)
{
    uint8_t i;
    uint32_t sum_x = 0, sum_y = 0;

    // 检测触摸
    if (!Touch_DetectPress())
    {
        pt->pressed = 0;
        pt->x = 0;
        pt->y = 0;
        return;
    }

    // 连续采样8次取平均(软件滤波)
    for (i = 0; i < 8; i++)
    {
        sum_x += Touch_ReadX();
        sum_y += Touch_ReadY();
        delay_us(2);
    }

    pt->x = (uint16_t)(sum_x >> 3);    // 除以8
    pt->y = (uint16_t)(sum_y >> 3);
    pt->pressed = 1;
}

//---------------------------------------------------------------------------
// 简易延时
void delay_us(uint16_t us)
{
    uint16_t i;
    while (us--)
    {
        i = 12;     // 11.0592MHz下约1us
        while (i--);
    }
}

//---------------------------------------------------------------------------
// 坐标校准:四角校准法(示例:将ADC值映射到LCD分辨率)
// 假设 LCD 分辨率为 320×240
// 需先采集触摸屏四角的ADC原始值:
//   左上(x_min,y_min),右下(x_max,y_max)
void Touch_Calibrate(uint16_t *px, uint16_t *py,
                     uint16_t x_min, uint16_t x_max,
                     uint16_t y_min, uint16_t y_max,
                     uint16_t lcd_w,  uint16_t lcd_h)
{
    // 注意:电阻触摸屏的X/Y通常与LCD反向
    // 这里做线性映射
    if (*px > x_max) *px = x_max;
    if (*px < x_min) *px = x_min;
    if (*py > y_max) *py = y_max;
    if (*py < y_min) *py = y_min;

    *px = (uint16_t)((uint32_t)(*px - x_min) * lcd_w / (x_max - x_min));
    *py = (uint16_t)((uint32_t)(*py - y_min) * lcd_h / (y_max - y_min));
}

//---------------------------------------------------------------------------
// 主函数(示例)
void main(void)
{
    uint16_t lcd_x, lcd_y;

    // 系统初始化
    WTST = 0x00;        // 程序代码等待参数设为0(最快)
    CKCON = 0x00;       // 外部数据总线速度为最快
    EAXFR = 1;

    Touch_GPIO_Init();
    Touch_ADC_Init();

    // 这里加入您的 TFT LCD 初始化代码(如 ILI9341/ILI9488 等)

    while (1)
    {
        Touch_GetPoint(&g_tTouch);

        if (g_tTouch.pressed)
        {
            // 原始ADC值 → LCD像素坐标(需四角校准后使用)
            lcd_x = g_tTouch.x;
            lcd_y = g_tTouch.y;

            // 使用校准函数(需先标定四角坐标)
            // Touch_Calibrate(&lcd_x, &lcd_y,
            //                 x_min, x_max, y_min, y_max,
            //                 320, 240);

            // 将触摸坐标用于您的应用...
            // 例如:在触摸点画一个点、响应菜单按键等
        }
        else
        {
            // 无触摸时的处理(如进入省电模式)
        }

        // 避免采样过快
        delay_us(1000);
    }
}

🧪 关键要点说明

要点 说明
引脚选择 P1.0/P1.1/P1.4/P1.5 兼具 ADC 功能,且不与 TFT 并口/LCM 接口冲突,是首选
Vref+处理 必须接 VCC 或外部基准电压,不能浮空(手册第22章明确要求)
I/O模式切换 测量时需要把供电引脚切为推挽输出,采样引脚切为 高阻输入
触摸检测 Y+上读电压:有触摸时ADC值低(屏体受压导通),无触摸时ADC接近满量程
软件滤波 程序中做了8次采样取平均,有效降低噪声抖动
四角校准 使用 Touch_Calibrate() 做线性映射,将ADC原始值转为LCD像素坐标

📚 已有例程/源码获取

除了上面的参考代码,您还可以从以下渠道获取 可直接编译运行的完整工程

1️⃣ 屠龙刀-STC32G12K128 官方例程包

2️⃣ 实验箱8.3例程(ILI9341 + 触摸)

  • 下载地址:https://www.stcai.com/syx
  • 帖子 #11264 的附件例子,针对 2.4寸ILI9341
  • 接线修改:将触摸电路断开后连接到 P1.4~P1.7,ADC基准改为 VCC
  • 已确认 STC32G12K128 在此方案下手写识别效果很好

3️⃣ 8H8K64U 触摸源码(原理完全通用)

  • 帖子 #10867 附件 "ST7571工程.zip"(190KB)
  • 虽然是8H系列+ST7571驱动,但 触摸ADC采样的核心逻辑 与STC32G完全一致,直接参考

4️⃣ 使用 DMA 提升性能

论坛管理员神*** 建议:"用 DMA 来支持 ADC,这样减少 CPU 的压力 — STC32G12K128 有 DMA 支持 ADC"(帖子 #10867 回复)

查阅 STC32G 手册第 30 章 DMA,可实现 ADC→内存自动传输,无需 CPU 逐次查询,大幅提升触摸响应速度。


如果您需要,我可以进一步帮您将上述代码适配到您的具体 LCD型号(如ILI9341/ILI9488/ST7789等)屏幕分辨率,或者给出 DMA+ADC 的优化版本。


🔍 搜索 "有具体的参考程序吗"

📌 相关论坛讨论

  1. 我是怎样用 CosyOS构建系统的
  2. 关于单片机与PC之间的USB通讯问题
  3. 再次论述嵌入式系统现代编程的认知模型
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:142
  • 最近打卡:2026-07-04 10:53:37
已绑定手机

5

主题

331

回帖

6374

积分

论坛元老

积分
6374
发表于 5 天前 | 显示全部楼层
建议增加一项:检测接触电阻,以免轻轻点击时位置飘移。
参考:
https://www.cnblogs.com/we-hjb/archive/2009/12/16/1626020.html
傲游截图20260630104222.jpg

点评

帮提供详细案例,方便大家学习,完善 STC【AI助手】知识库  详情 回复 发表于 5 天前
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 5 天前 | 显示全部楼层
lcws*** 发表于 2026-6-30 10:43
建议增加一项:检测接触电阻,以免轻轻点击时位置飘移。
参考:
https://www.cnblogs.com/we-hjb/archive/2 ...

帮提供详细案例,方便大家学习,完善 STC【AI助手】知识库
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:142
  • 最近打卡:2026-07-04 10:53:37
已绑定手机

5

主题

331

回帖

6374

积分

论坛元老

积分
6374
发表于 5 天前 | 显示全部楼层
神*** 发表于 2026-6-30 10:55
帮提供详细案例,方便大家学习,完善 STC【AI助手】知识库


傲游截图20260630110728.jpg

参考链接中给了公式,能算出接触电阻,我也只是很久以前试过一次,


之后未经太多的测试,不保证准确性,仅供参考:
  1. #define BIT(x)    (1<<(x))
  2. #define IOSET(port,x)  (port)|=(x)
  3. #define IOCLR(port,x)  (port)&=~(x)
  4. #define X0_H        IOSET(P1,BIT(0))
  5. #define X0_L        IOCLR(P1,BIT(0))
  6. #define X0_IN        {IOCLR(P1M1,BIT(0));IOSET(P1M0,BIT(0)}
  7. #define X0_OUT        {IOCLR(P1M0,BIT(0));IOSET(P1M1,BIT(0)}
  8. #define X0_UP        {IOCLR(P1M1,BIT(0));IOCLR(P1M0,BIT(0));IOSET(P1,BIT(0));}
  9. #define X1_H        IOSET(P1,BIT(2))
  10. #define X1_L        IOCLR(P1,BIT(2))
  11. #define X1_IN        {IOCLR(P1M1,BIT(2));IOSET(P1M0,BIT(2)}
  12. #define X1_OUT        {IOCLR(P1M0,BIT(2));IOSET(P1M1,BIT(2)}
  13. #define X1_UP        {IOCLR(P1M1,BIT(2));IOCLR(P1M0,BIT(2));IOSET(P1,BIT(2));}
  14. #define Y0_H        IOSET(P1,BIT(1))
  15. #define Y0_L        IOCLR(P1,BIT(1))
  16. #define Y0_IN        {IOCLR(P1M1,BIT(1));IOSET(P1M0,BIT(1)}
  17. #define Y0_OUT        {IOCLR(P1M0,BIT(1));IOSET(P1M1,BIT(1)}
  18. #define Y0_UP        {IOCLR(P1M1,BIT(1));IOCLR(P1M0,BIT(1));IOSET(P1,BIT(1));}
  19. #define Y1_H        IOSET(P1,BIT(3))
  20. #define Y1_L        IOCLR(P1,BIT(3))
  21. #define Y1_IN        {IOCLR(P1M1,BIT(3));IOSET(P1M0,BIT(3)}
  22. #define Y1_OUT        {IOCLR(P1M0,BIT(3));IOSET(P1M1,BIT(3)}
  23. #define Y1_UP        {IOCLR(P1M1,BIT(3));IOCLR(P1M0,BIT(3));IOSET(P1,BIT(3));}
  24. //读取x的AD
  25. #define readadx0() adc_read(0)
  26. //读取y的AD
  27. #define readady0() adc_read(1)
  28. //读取x脚的电平状态
  29. #define readiox() (P1&BIT(2))
  30. //x上拉
  31. #define X_UP        {IOCLR(P1M1,BIT(0)+BIT(2));IOCLR(P1M0,BIT(0)+BIT(2));IOSET(P1,BIT(0)+BIT(2));}
  32. //X置为输入
  33. #define X_IN        {IOCLR(P1M1,BIT(0)+BIT(2));IOSET(P1M0,BIT(0)+BIT(2));}
  34. //X置为输出
  35. #define X_OUT        {IOCLR(P1M0,BIT(0)+BIT(2));IOSET(P1M1,BIT(0)+BIT(2));}
  36. #define Y_IN         {IOCLR(P1M1,BIT(1)+BIT(3));IOSET(P1M0,BIT(1)+BIT(3));}
  37. #define Y_OUT        {IOCLR(P1M0,BIT(1)+BIT(3));IOSET(P1M1,BIT(1)+BIT(3));}
  38. //x1,y1 置为输出
  39. #define Z_OUT        {IOCLR(P1M0,BIT(2)+BIT(3));IOSET(P1M1,BIT(2)+BIT(3));}
  40. #define Z_IN         {IOCLR(P1M1,BIT(2)+BIT(3));IOSET(P1M0,BIT(2)+BIT(3));}
  41. //--------------------------------------------------
  42. //相关变量
  43. //--------------------------------------------------
  44. #define BUFCNT 5
  45. U16 xbuf[BUFCNT],ybuf[BUFCNT];
  46. //--------------------------------------------------
  47. //取得x座标
  48. //--------------------------------------------------
  49. U16 TS_getx(void)
  50. {
  51.         U16 x;
  52.         //Y0_L;Y1_L;delayms(1);//放电
  53.         //Y_IN;
  54.         X0_H;X1_L;X_OUT;delayus(100);//delayms(1);
  55.         readady0();
  56.         x=readady0();
  57.         //X0_L;delayms(1);
  58.         X_IN;
  59.         return x;
  60. }
  61. //--------------------------------------------------
  62. //取得y座标
  63. //--------------------------------------------------
  64. U16 TS_gety(void)
  65. {
  66.         U16 y;
  67.         Y0_H;Y1_L;Y_OUT;delayus(100);//delayms(1);
  68.         readadx0();
  69.         y=readadx0();
  70.         //Y0_L;delayms(1);
  71.         Y_IN;
  72.         return y;
  73. }
  74. //--------------------------------------------------
  75. //取得是否被按下的状态
  76. //--------------------------------------------------
  77. U8 TS_gets(void)
  78. {
  79.         U8 s;
  80.         Y0_L;Y1_L;Y_OUT;
  81.         X0_H;X1_H;X_OUT;delayus(100);//delayms(1);//放电
  82.         X_UP;delayms(1);//X上拉输入       
  83.         if(readiox()==0)
  84.                 s=1;
  85.         else
  86.                 s=0;
  87.         //X0_L;X1_L;delayms(1);
  88.         X_IN;Y_IN;
  89.         return s;
  90. }
  91. //--------------------------------------------------
  92. //取得触摸电阻
  93. //x1,y1 为输出
  94. //--------------------------------------------------
  95. void TS_getz(U16* Vz1,U16* Vz2)
  96. {
  97. //        U16 z1,z2;
  98.         X1_H;Y1_L;Z_OUT;delayus(100);//delayms(1);
  99.         readadx0();
  100.         *Vz1=readadx0();
  101.         readady0();
  102.         *Vz2=readady0();
  103.         //Y0_L;delayms(1);
  104.         Z_IN;
  105. }
  106. //--------------------------------------------------
  107. //n个数里求平均值(n>=3)
  108. //--------------------------------------------------
  109. U16 average(U16 a[],U8 n)
  110. {
  111.         U16 max,min,ave=0,sum=0;
  112.         U8 i;
  113.         if(n<3)return 0;
  114.     max=a[0];
  115.     min=a[0];
  116.     for(i=0;i<n;i++)
  117.         {
  118.                 if(max<a[i])max=a[i];
  119.                 if(min>a[i])min=a[i];
  120.                 sum+=a[i];
  121.         }
  122.         ave=(sum-min-max)/(n-2);
  123.         return ave;
  124. }
  125. //--------------------------------------------------
  126. //获取坐标及是否按下
  127. //--------------------------------------------------
  128. void Touch_GetData(U8 *ud,U16 *x,U16 *y)
  129. {
  130.         U8  s,i;
  131.         U16 Vz1,Vz2;
  132.         U16 tempy,Rt;
  133.         s=TS_gets();
  134.         if(s)
  135.         {
  136.                 for(i=0;i<BUFCNT;i++)
  137.                 {
  138.                         xbuf[i]=TS_getx();
  139.                         tempy=TS_gety();
  140.                         ybuf[i]=tempy;
  141.                         TS_getz(&Vz1,&Vz2);
  142.                         if(Vz2==0)Vz2=1;//除数不能为0
  143.                         Rt=(U32)tempy*(Vz1-Vz2)/Vz2;//接触电阻
  144.                         if(Rt>1500)s=0;//接触电阻过大
  145.                 }
  146.                 if(s)s=TS_gets();
  147.                 if(s)
  148.                 {
  149.                         *x=average(xbuf,BUFCNT);
  150.                         *y=average(ybuf,BUFCNT);
  151.                 }
  152.         }
  153.         *ud=s;
  154. }
  155. //--------------------------------------------------
  156. //屏初始化
  157. //--------------------------------------------------
  158. void TS_init(void)
  159. {
  160.         X_IN;//引脚置为输入
  161.         Y_IN;
  162. }
  163. //--------------------------------------------------
  164. //主函数
  165. //--------------------------------------------------
  166. void main(void)
  167. {
  168.         U16 x,y;
  169.         U8 w,s,s0;
  170.         init_devices();
  171.         while(1)
  172.         {
  173.                 for(w=0;w<200;w++)
  174.                 {
  175.                         Touch_GetData(&s,&x,&y);
  176.                         if(s)break;
  177.                         if(s0)break;
  178.                         delayms(1);
  179.                 }
  180.                 uart1_sendbyte(0xaa);
  181.                 uart1_sendbyte(s);
  182.                 uart1_sendbyte(x>>8);
  183.                 uart1_sendbyte(x);
  184.                 uart1_sendbyte(y>>8);
  185.                 uart1_sendbyte(y);
  186.                 s0=s;
  187.         }
  188. }
复制代码


点评

帮给个 STC8H8K64U的帮 8位世界也前进下  详情 回复 发表于 5 天前
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:299
  • 最近打卡:2026-07-04 00:01:55
已绑定手机

66

主题

808

回帖

3037

积分

论坛元老

DIY玩家

积分
3037
发表于 5 天前 | 显示全部楼层
lcws*** 发表于 2026-6-30 11:21
参考链接中给了公式,能算出接触电阻,我也只是很久以前试过一次,

良好的经验参考
后来者可参考设计应用
永怀这学徒心
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 5 天前 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:142
  • 最近打卡:2026-07-04 10:53:37
已绑定手机

5

主题

331

回帖

6374

积分

论坛元老

积分
6374
发表于 5 天前 | 显示全部楼层
神*** 发表于 2026-6-30 11:35
帮给个 STC8H8K64U的帮 8位世界也前进下
STC8H8K64U接电阻式触摸TFT彩屏,用MCU自己的ADC实现触摸 - TFT彩 ...

不管8位、32位,原理是一样的。

刚翻了一下XPT2046的手册,其中的“压力测量”、“触摸电阻”也是一样的:
傲游截图20260630113655.jpg

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-7-5 08:03 , Processed in 0.084256 second(s), 87 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表