找回密码
 立即注册
查看: 71|回复: 4

8H1K17T触摸按键

[复制链接]
  • 打卡等级:偶尔看看II
  • 打卡总天数:20
  • 最近打卡:2025-09-02 10:48:00
已绑定手机

10

主题

33

回帖

196

积分

注册会员

积分
196
发表于 2025-8-25 20:08:37 | 显示全部楼层 |阅读模式
// 头文件
#include "STC8H.H"                                  // 引入STC8系列单片机的头文件
#include "intrins.h"                                // 引入Keil的内部函数头文件
// 宏定义
// 数据类型
#define  u32   unsigned long                        // 定义32位无符号整数类型
#define  u16   unsigned int                         // 定义16位无符号整数类型
#define  u8    unsigned char                        // 定义8位无符号整数类型
// 数据存储
#define MAIN_Fosc       20000000L                   // 定义主时钟


// 引脚定义
sbit    TK0  = P1^0;
sbit    LED  = P3^7;


// 声明
// 数组
u16 xdata TK_cnt[16];   // 按键计数值, 16位
u16 xdata TK_zero[16];  // 按键0点值, 16位
//                         K0     K1     K2     K3     K4     K5      K6    K7     K8     K9     K10   K11    K12    K13    K14    K15
// 触摸后的变化值
u16 code T_KeyPress[16]={ 700,  2000,  900,   800,   900,   1000,   1100, 1400,  1000,  1200,   900,  1200,  750,   900,   1300,  1800};
// 16个键对应的状态, 0为未触摸,1为触摸   
u16 code T_KeyState[16]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};  
// 函数
void delay_ms(u8 ms);
void ReturnValue(u8 channel, u16 value);
// 变量
bit B_TK_Lowpass;                                   // 低通允许, 1允许, 0禁止
u8  read_cnt;                                       // 读次数
u16 KeyState;                                       // 按键状态, 每个bit对应一个键, 1为按下, 0为释放


// 函数模块
// 主函数
void main(void)
{
    u8  i;
    u16 j;

    P1M0 &= ~0x01; P1M1 |= 0x01;                    // P10为高阻输入
    P3M0 |= 0x80; P3M1 &= ~0x80;                    // P37为推挽输出

    LED = 0;

    P_SW2 |= 0x80;                                  // 允许访问扩展寄存器xsfr
    EA = 1;                                         // 开总中断

    TSCHEN1 = 0x01;                                 // TK0~TK7
    TSCHEN2 = 0x00;                                 // TK8~TK15
    TSCFG1  = (7<<4) + 6;                           // B6~B4:开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), B2~B0:放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最好大于等于3(1000)
    TSCFG2  = 1;                                    // B1~B0:配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4)  1(1/2)  2(5/8)  3(3/4)
    TSRT = 0x00;                                    // 没有LED分时扫描
    IE2 |= 0x80;                                    // 允许触摸按键中断

    delay_ms(50);                                   // 延时一下

    B_TK_Lowpass = 0;                               // 禁止低通滤波

    for(read_cnt=0; read_cnt<10; read_cnt++)        // 扫描10次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
    {
        TSCTRL = (1<<7) + (1<<6);                   // 开始扫描, 无平均
        delay_ms(50);                               // 延时一下, 等待扫描完成
    }

    for(i=0; i<16; i++)     TK_zero = TK_cnt; // 保存0点
    B_TK_Lowpass = 1;                               // 允许低通滤波
    KeyState = 0;
    read_cnt = 0;

    while (1)
    {
        TSCTRL = (1<<7) + (1<<6);                   // 开始扫描, 无平均
        delay_ms(20);                               // 延时一下, 根据实际扫描速度调整

        if(++read_cnt >= 3)
        {
            read_cnt = 0;
            j = KeyState;
            for(i=0; i<16; i++)
            {
                if(TK_zero> TK_cnt)          // 0点值比当前值大, 则键按下, 缓慢0点跟踪
                {
                    TK_zero--;                   // 缓慢0点跟随
                         if((TK_zero - TK_cnt) >= T_KeyPress/2)    KeyState |=  T_KeyState;         // 变化值大于最大变化值的1/2, 则判断键已触摸
                    else if((TK_zero - TK_cnt) <= T_KeyPress/3)    KeyState &= ~T_KeyState;         // 变化值小于最大变化值的1/3, 则判断键已释放
                }
                else                                                                                            // 0点值比当前值小, 则键释放
                {
                    KeyState &= ~T_KeyState;                                                                 // 键状态: 释放
                    if((TK_cnt - TK_zero) > 100)  TK_zero += 100;                                      // 差别很大, 则快速回0点
                    else                                TK_zero += 10;                                       // 差别不大, 则慢速回0点
                }
            }

            j = (j ^ KeyState) & KeyState;                                                                      // LED指示处理
            B = (u8)j;
            if(B0)  LED = ~LED;
        }
    }
}


// 描述: 延时函数。
void delay_ms(u8 ms)
{
    u16 i;
    do
    {
        i = MAIN_Fosc / 10000;
        while(--i);
    }
    while(--ms);
}


// 描述: 触摸按键中断服务函数
void TKSU_ISR(void) interrupt TKSU_VECTOR
{
    u8  j;

    j = TSSTA2;

    if(j & 0x40)                                                                // 数据溢出, 错误处理(略)
    {
        TSSTA2 |= 0x40;                                                         // 写1清零
    }
    if(j & 0x80)                                                                // 扫描完成
    {
        j &= 0x0f;
        TSSTA2 |= 0x80;                                                         // 写1清零
        if(!B_TK_Lowpass)   TK_cnt[j] = TSDAT;                                  // 保存某个通道的读数    1.1us @24MHz
        else                TK_cnt[j] = (TK_cnt[j] >> 1) + (TSDAT >> 1);        // 保存某个通道的读数    1/2低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500.
    }
}

这是我根据例程修改成单通道控制单个LED 的触摸按键程序
这样配置没问题么 为什么在实际使用的过程中触摸按键不是很灵敏
回复

使用道具 举报 送花

3

主题

2001

回帖

850

积分

等待验证会员

积分
850
发表于 2025-8-25 20:12:00 | 显示全部楼层
尊敬的开发者,您好:

感谢您对STC8H1K17T触摸按键应用的关注。以下是对该芯片在触摸按键功能实现中的技术说明与建议,供您参考。

一、概述

STC8H1K17T是STC推出的一款基于增强型8051内核的高性能单片机,具备丰富的外设资源,包括多通道ADC、PWM、定时器及触摸按键检测功能。其内置的触摸按键模块支持电容式触摸检测,适用于低功耗、高灵敏度的触控应用场景。

二、触摸按键功能简介

STC8H1K17T支持通过内部ADC通道进行触摸按键检测。其原理是利用电容变化引起的电压波动来判断是否有按键被按下。具体流程如下:

1. 初始化配置:设置相关寄存器,启用触摸检测功能。
2. 采集数据:通过ADC读取触摸引脚的电压值。
3. 阈值判断:根据预设的基准值判断是否触发按键。
4. 去抖处理:防止误触发,提升稳定性。

三、代码示例与说明

以下为基于Keil C51环境的简化代码示例,用于演示如何使用STC8H1K17T实现触摸按键功能:

  1. c
  2. include "STC8HH.h"
  3. include "intrinsh.h"
  4. define u32 unsigned int
  5. define u8  unsigned char
  6. // 定义触摸引脚(例如P3.0)
  7. define TOUCHPIN P30
  8. // 触摸阈值设定
  9. define TOUCHTHRESHOLD 100
  10. // ADC配置函数
  11. void ADCInit(void) {
  12.     ADCCON1 = 0x80;           // 选择ADC通道0,开启ADC
  13.     ADCCON3 = 0x00;           // 设置采样时间等参数
  14. }
  15. // 读取ADC值
  16. u16 ReadADC(void) {
  17.     ADCCON1 |= 0x01;          // 启动一次转换
  18.     while (ADCCON1 & 0x01);   // 等待转换完成
  19.     return ADCDATA;
  20. }
  21. // 检测触摸按键
  22. bit CheckTouch(void) {
  23.     u16 adcval = ReadADC();
  24.     if (adcval > TOUCHTHRESHOLD) {
  25.         return 1;  // 触发
  26.     } else {
  27.         return 0;  // 未触发
  28.     }
  29. }
  30. // 主函数
  31. void main(void) {
  32.     ADCInit();
  33.     while (1) {
  34.         if (CheckTouch()) {
  35.             // 执行按键响应逻辑
  36.         }
  37.         nop();  // 延时去抖
  38.     }
  39. }
复制代码


四、注意事项

1. 引脚配置:确保触摸引脚已正确配置为输入模式,并连接外部电容或金属片作为触摸感应点。
2. 校准与调参:实际应用中需根据硬件环境调整TOUCHTHRESHOLD值,以获得最佳灵敏度与稳定性。
3. 去抖处理:建议采用软件延时或硬件滤波方式减少误触发。
4. 电源与地线:良好的电源和接地设计对触摸检测性能至关重要。

五、优化建议
使用多通道ADC并行检测多个触摸点,提高系统灵活性。
结合中断机制实现更高效的按键响应。
在低功耗模式下合理管理ADC唤醒机制,以延长电池寿命。

如您在开发过程中遇到具体问题,欢迎进一步沟通。我们将持续为您提供技术支持与文档资料,助力项目顺利推进。

此致  
敬礼!

国芯人工智能团队  
2025年4月

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:547
  • 最近打卡:2025-09-03 09:00:23
已绑定手机

85

主题

6045

回帖

1万

积分

超级版主

积分
11110
发表于 2025-8-25 21:24:56 | 显示全部楼层
看到了您使用了带零点跟踪的例程,例程都是测试通过的不应存在问题,那么问题应该是硬件导致的,比如绝缘介质过厚、PCB设计不合理等原因,先按照您的硬件实物调试,尝试根据触摸后的变化值修改T_KeyPress,如果仍未解决,需要上传PCB图或实物照片具体分析
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:20
  • 最近打卡:2025-09-02 10:48:00
已绑定手机

10

主题

33

回帖

196

积分

注册会员

积分
196
发表于 2025-8-26 11:03:44 | 显示全部楼层
我现在修改了K0 的T_KeyPress 但是不是大就是小了
如图箭头所指向的位置触碰后触摸就会起作用 但是灵敏度很奇怪
截图202508261103416778.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:20
  • 最近打卡:2025-09-02 10:48:00
已绑定手机

10

主题

33

回帖

196

积分

注册会员

积分
196
发表于 6 天前 | 显示全部楼层
触摸按键可以了
例程是OK的

触摸充放电的电容引脚差错了 20 和 16脚封装看错
例程改一下触摸通道和LED的引脚就可以使用了
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-9-3 10:34 , Processed in 0.126066 second(s), 74 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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