找回密码
 立即注册
查看: 89|回复: 9

AI8H1K17T触摸按键读取

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-17 01:59:50
已绑定手机

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-14 23:29:21 | 显示全部楼层 |阅读模式
// 单片机-AI8H1K17T
// 头文件
#include "STC8H.h"
#include <intrins.h>
#include <stdio.h>


// 端口定义
sbit LED0 = P3^7;
sbit LED1 = P3^6;
sbit TK0  = P1^0;
sbit TK1  = P1^1;


// 宏定义
// 数据类型
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
// 数据存储
#define MAIN_Fosc            11059200        //定义主时钟 11059200
#define BAUD        (65536 - MAIN_Fosc/4/115200)     //定义串口波特率重装值

// 声明
// 数组
u16        xdata TK_cnt[16];        // 键计数值
u16        xdata TK_zero[16];        // 0点读数
u16 code T_KeyState[16] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
    0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
// 读数有平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同
u16 code T_KeyPress[16] = {200,150,100,100, 200,150,100,100,
     200,150,100,100, 200,150,100,100};        
// 函数
void delay_ms(u8 ms);                   // 延时函数
u8 CheckKey(u16 j);                     // 检测键值
void TK_system_init();                  // 触摸按键初始化
void uart_init();                       // 串口波特率发生器
char putchar(char dat);                 // 重定义putchar系统函数
void system_init();                     // 系统初始化
// 变量
u16        KeyState;                // 键状态
u8        KeyCode;                // 键码 1~16
bit        B_TK_Lowpass;        // 允许低通
bit        B_ReadKeyOk;        // 标志已转换完成16个键
bit fBusy;                                     //串口发送忙标志
u16 AUXR_ISR_YN=0;
u8        TrigLimit;                // 触发转换限时
u8        KeyValue;                // 显示参数的键号, 0~15
u8        read_cnt;
u8        isr_index;
u8 i,j;


// 函数模块
// 延时函数
void delay_ms(u8 ms)
{
        u16 i;
        do
        {
                i = MAIN_Fosc / 10000;
                while(--i)        ;
        }while(--ms);
}

// 检测键值
u8 CheckKey(u16 j)
{
        u8 i;
        if(j == 0)
    {
        return 0;        //无键按下
    }

        for(i=0; i<8; i++)
        {
                if(j & 0x0001)        break;
                j >>= 1;
        }

        return (i+1);        //键码1~8
}

// 触摸按键初始化
void TK_system_init()
{
    TSCHEN1 = 0x03;         // 使能TK0 TK1
    TSCHEN2 = 0x00;
    TSRT    = 0x00;         // 关闭LED驱动分时多任务功能
    TSCFG1  = (7<<4) + 6;        //开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), 放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最小3
        TSCFG2  = 1;                //配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4)  1(1/2)  2(5/8)  3(3/4)
    IE2 |= 0x80;                //允许触摸按键中断
        EA = 1;

    delay_ms(50);
    B_TK_Lowpass = 1;        //允许低通滤波
        for(read_cnt=0; read_cnt<40; read_cnt++)                //读40次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
        {
                TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
                B_ReadKeyOk = 0;
                for(i=0; i<100; i++)
                {
                        if(B_ReadKeyOk)        break;
                        delay_ms(1);
                }
        }
        for(i=0; i<16; i++)                TK_zero = TK_cnt;        //保存0点
        
        B_TK_Lowpass = 1;        //允许低通
        KeyState = 0;
        read_cnt = 0;
        
        B_ReadKeyOk = 0;
        KeyValue = 10;
        KeyCode = 0;
        delay_ms(2000);
    printf("开始测试----\r\n");
}

// 串口波特率发生器
void uart_init()
{
    AUXR = 0x40;                                //使用定时器1作为串口波特率发生器
    TMOD = 0x00;
    TL1 = BAUD;
    TH1 = BAUD >> 8;
    TR1 = 1;
    SCON = 0x50;
    ES = 1;
}

// 重定义putchar系统函数
char putchar(char dat)                          
{
    while (fBusy);
    fBusy = 1;
    SBUF = dat;   
    return dat;
}

// 系统初始化
void system_init()
{
    P1M0 &= ~0x03; P1M1 |= 0x03;        // P10 11 高阻输入
    P3M0 |= 0xc0; P3M1 &= ~0xc0;        // P36 37 TUIWANSHUCHU

    P_SW2 |= 0x80;        //允许访问XSFR(扩展特殊功能寄存器)

    uart_init();                        // 串口波特率发生器
}

// 主函数
void main()
{
    system_init();
    TK_system_init();


    // 主循环
        while (1)
        {
                delay_ms(1);
        if(AUXR_ISR_YN){printf("AUXR_ISR_YN=%d\r\n",AUXR_ISR_YN);AUXR_ISR_YN=0;}
                if(++TrigLimit >= 100)        //触发转换
                {
                        TrigLimit = 0;
                        TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
                }
               
                if(B_ReadKeyOk)                        // 16个键都转换完毕
                {
                        B_ReadKeyOk = 0;
                        TrigLimit = 100;

                        j = KeyState;                //读入上一次键状态
                        for(i=0; i<8; i++)
                        {
                                if(TK_zero > TK_cnt)        //计算与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
                                {
                                        KeyState &= ~T_KeyState;
                                        if((TK_cnt - TK_zero) > 100)        
                                                TK_zero += 50;        //差别很大, 则快速回0点
                                        else                        TK_zero += 10;        //差别不大, 则慢速回0点
                                }
                        }
                        j = (j ^ KeyState) & KeyState;        //检测键是否按下
                        if(j != 0)
                        {
                                KeyCode = CheckKey(j);        //计算键码 1~8                                
                printf("KeyCode:%d\r\n",(u16)KeyCode);
                                if(KeyCode == 0)
                                {
                                        LED0=!LED0;
                                }
                else if(KeyCode == 1)
                {
                    LED1=!LED1;
                }
                        }
                }
        }
}

// 中断服务函数
void AUXR_ISR(void) interrupt 13
{        
        switch(isr_index)
        {
                case 32:                //0103H 波形发生器5 中断入口
                break;

                case 33:                //010BH        波形发生器异常2 中断入口
                break;

                case 34:                //0113H        波形发生器异常4 中断入口
                break;

                case 35:                //011BH        触摸按键 中断入口
                        j = TSSTA2;

                        if(j & 0x40)        //数据溢出, 错误处理(略)
                        {
                                TSSTA2 |= 0x40;        //写1清零                                
                        }

                        if(j & 0x80)        //扫描完成
                        {
                                j &= 0x0f;
                                TSSTA2 |= 0x80;        //写1清零

                                if(!B_TK_Lowpass)
                {
                    TK_cnt[j] = TSDAT/4;        //保存某个通道的读数        无低通滤波
                }
                                else
                {
                    TK_cnt[j] = ((TK_cnt[j] * 3)>>2) + TSDAT/16;        //保存某个通道的读数        低通滤波
                }        

                                if(j == 7)        
                {
                    B_ReadKeyOk = 1;        //读完一次循环
                                }
                        }
                break;

                case 36:                //0123H        RTC 中断入口
                break;

                case 37:                //012BH        P0口中断入口
                break;

                case 38:                //0133H        P1口中断入口
                break;

                case 39:                //013BH        P2口中断入口
                break;

                case 40:                //0143H        P3口中断入口
                break;

                case 41:                //014BH        P4口中断入口
                break;

                case 42:                //0153H        P5口中断入口
                break;

                case 43:                //015BH        P6口中断入口
                break;

                case 44:                //0163H        P7口中断入口
                break;

                case 45:                //016BH        P8口中断入口
                break;

                case 46:                //0173H        P9口中断入口
                break;
               
                default:
                break;
        }
}

void uart_isr() interrupt 4
{
    if (TI)
    {
        TI = 0;
        fBusy = 0;
    }
   
    if (RI)
    {
        RI = 0;
    }
}
回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-14 23:38:00 | 显示全部楼层
针对您提供的代码片段,我将从专业角度进行分析和优化建议,主要围绕STC8H1K17T单片机的触摸按键读取功能展开。

1. 代码分析

1.1 头文件与端口定义
  1. c
  2. include "STC8H.h"
  3. include
  4. include
  5. sbit LED0 = P3^7;
  6. sbit LED1 = P3^6;
  7. sbit TK0  = P1^0;
  8. sbit TK1  = P1^1;
复制代码
#include "STC8H.h":这是STC8H系列单片机的专用头文件,包含了该系列单片机的寄存器定义和常用宏。
sbit 用于定义位变量,方便对单个引脚进行操作。LED0和LED1分别连接到P3.7和P3.6,TK0和TK1分别连接到P1.0和P1.1,用于触摸按键的检测。

1.2 宏定义与数据类型
  1. c
  2. define u8 unsigned char
  3. define u16 unsigned int
  4. define u32 unsigned long
  5. define MAINFosc 24000000L
复制代码
定义了常用的数据类型别名,便于代码的简洁性和可读性。
MAINFosc 定义了主时钟频率为24MHz,这是单片机工作的基准时钟。

1.3 数组与变量声明
  1. c
  2. u16 xdata TKcnt;    // 键计数值
  3. u16 xdata TKzero;   // 0点读数
  4. u16 code TKeyState = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
  5.     0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
  6. u16 code TKeyPress = {200,150,100,100, 200,150,100,100,
  7.      200,150,100,100, 200,150,100,100};
复制代码
TKcnt 和 TKzero 是用于存储触摸按键的计数值和零点读数。
TKeyState 和 TKeyPress 分别是按键状态和按键按下时的变化值数组,用于判断按键是否被按下。

1.4 函数声明
  1. c
  2. void delayms(u8 ms);                   // 延时函数
  3. u8 CheckKey(u16 j);                     // 按键检测函数
复制代码
delayms 是一个延时函数,用于实现毫秒级的延时。
CheckKey 是按键检测函数,用于判断按键是否被按下。

2. 优化建议

2.1 头文件包含
建议在包含头文件时,确保所有必要的头文件都已包含。例如,#include  和 #include  可能存在缺失,应根据实际需求补充相应的头文件。

2.2 数据类型定义
建议使用stdint.h标准库中的数据类型,以提高代码的可移植性。例如:
  1. c
  2. include
  3. typedef uint8t u8;
  4. typedef uint16t u16;
  5. typedef uint32t u32;
复制代码

2.3 数组定义
TKeyState 和 TKeyPress 数组的定义可以进一步优化,使用更具描述性的名称,并添加注释说明每个元素的含义。

2.4 延时函数
delayms 函数的实现需要考虑主时钟频率,建议根据MAINFosc计算延时周期,以确保延时的准确性。

2.5 按键检测函数
CheckKey 函数的实现需要结合TKeyState和TKeyPress数组,判断按键是否被按下。建议在函数内部添加详细的注释,说明判断逻辑。

3. 总结
该代码片段展示了STC8H1K17T单片机触摸按键读取的基本框架,但在头文件包含、数据类型定义、数组命名和函数实现等方面仍有优化空间。通过上述建议,可以提高代码的可读性、可维护性和可移植性。

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

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-17 01:59:50
已绑定手机

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-15 00:17:33 | 显示全部楼层
rt
截图202504150017223136.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-17 01:59:50
已绑定手机

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-15 10:25:28 | 显示全部楼层

代码是用在STC9H1K17T SOP16上的,但是烧录以后
TK0 TK1没有反应,串口也检测不到读数
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-15 11:20:06 | 显示全部楼层
请直接使用例程测试:
STC8H4K64Txx-触摸按键校验检测.zip (3.49 MB, 下载次数: 2)
STC8H系列-触摸按键相关程序.rar (295.49 KB, 下载次数: 2)
触摸按键配套上位机测试软件.zip (3.19 MB, 下载次数: 2)
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-17 01:59:50
已绑定手机

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-15 14:53:49 | 显示全部楼层
直接烧录了第一个压缩包的例程 所有的端口都是这样的 这是正常的吗
截图202504151453191762.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-15 16:27:40 | 显示全部楼层
这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.p ... =3971&pid=51046

由于 8H1K08T 的这两个触摸按键跟串口脚复用: P3.0(TK08)   P3.1(TK09)
如果使用 P3.0, P3.1 做串口输出触摸值的话,TK08与TK09就不能使能触摸功能。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-17 01:59:50
已绑定手机

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-15 17:03:52 | 显示全部楼层
乘风*** 发表于 2025-4-15 16:27
这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.php?mod=redir ...

我这里已经用P30 31做串口输出了,我可否直接用您的代码更改一下触摸口测试呢
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-15 17:13:21 | 显示全部楼层
HyunYon*** 发表于 2025-4-15 17:03
我这里已经用P30 31做串口输出了,我可否直接用您的代码更改一下触摸口测试呢 ...

可以的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-17 01:59:50
已绑定手机

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-15 19:23:16 | 显示全部楼层
.
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 02:38 , Processed in 0.145764 second(s), 105 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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