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

8H1K17T SOP-16 上位机读取不到触摸数据

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

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-17 01:59:50 | 显示全部楼层 |阅读模式
// 头文件
/*
        不要少了ASM文件
        CSEG                AT 011BH
        LJMP                006BH
        
        END
*/

#include "STC8H.h"                          // 芯片头文件
#include <intrins.h>                        // 内联汇编指令


// 宏定义
// 数据类型
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
// 数据存储
#define MAIN_Fosc           11059200UL      // 主时钟频率
#define Baudrate            115200L         // 串口波特率


// 端口定义
sbit P_K0_LED  = P3^7;                      // TK0对应指示灯
sbit P_K1_LED  = P3^6;                      // TK1对应指示灯


// 声明
// 数组
u16        xdata TK_cnt[16];                       // 存储16路触摸的当前实时电容值
u16        xdata TK_zero[16];                      // 存储16路触摸的基准值
u16        xdata TK_differ[16];                    // 存储16路触摸的差值--判断触摸是否发生
u16        xdata TK_lowest[16];                    // 存储16路触摸的最小电容值

u8        xdata Zero_Add_Cnt[16];                 // 向上追踪延时计数器
u8        xdata Zero_Sub_Cnt[16];                 // 向下追踪延时计数器
u8        xdata TK_counter[16];                   // 状态缓冲计数器-判断有效触摸
u8  xdata RX1_Buffer[64];                   // 串口接收缓冲区

//               TP0  TP1  TP2  TP3  TP4  TP5  TP6  TP7   TP8  TP9   TP10  TP11  TP12  TP13  TP14  TP15
u16 code DIFF[]={350, 360, 800, 600, 600, 850, 850, 1200, 850, 1000, 800,  900,  550,  600,  900,  430};   
// 检测阈值=(未触摸值-触摸值)/2
// 函数
void Timer0_init(u32 clk);                  // timer0初始化函数
void UART1_config(u32 clk, u32 brt);            // UART1波特率发生器----
void UART1_TxByte(u8 dat);                  // 串口1发送一个字节函数
void JudgeKey(u8 tkn);                      // 判断键值是否有效
void ReadZeroData(void);                    // 获取触摸按键的零值
void system_init(void);                     // 系统初始化
void TK_init(void);                         // 触摸按键初始化
// 变量
bit        B_TX1_Busy;                                        // 串口通信忙标志位 (防止串口数据丢失)
bit        B_Zero_Flag;                            // 控制是否保存按键未触摸时的基准值
bit B_1ms;                                  // 定时器0-1ms中断标志位

u8        i;                                      // 通用变量
u8  TK_TimeOut;                             // 触摸按键扫描超时
u8        read_cnt;                               // 记录触摸按键读取次数
u8  RX1_Cnt;                                // 串口接收计数器

u16        tpFlag;                                 // 16位标志位-用于存储触摸按键的状态并根据位置执行对应程序(第0位就是TK0)
u16        JudgeFlag;                              // 16位标志位-用于防止重复触发触摸按键(第0位就是TK0)
u16 ScanFreq;                               // 按键扫描,扫描50次执行1次,保证输出稳定
u16        ChannelSet;                             // 16位标志位-用于存储触摸按键的总使能情况(0x0003就是TK0 TK1 使能)


// 函数模块
// UART1波特率发生器----
void UART1_config(u32 clk, u32 brt)
{
    brt = 65536UL - (clk / 4) / brt;
    TR1 = 0;
    AUXR &= ~0x01;                                    // S1 BRT Use Timer1;
    AUXR |=  (1<<6);                            // Timer1 set as 1T mode
    TMOD &= ~(1<<6);                            // Timer1 set As Timer
    TMOD &= ~0x30;                                    // Timer1_16bitAutoReload;
    TH1 = (u8)(brt >> 8);
    TL1 = (u8)brt;
    ET1 = 0;                        // 禁止Timer1中断
    INTCLKO &= ~0x02;        // Timer1不输出高速时钟
    TR1  = 1;                        // 运行Timer1

    P_SW1 &= 0x3f;
    P_SW1 |= 0x00;      //UART1 switch to, 0x00: P3.0 P3.1, 0x40: P3.6 P3.7, 0x80: P1.6 P1.7, 0xC0: P4.3 P4.4

    SCON = (SCON & 0x3f) | (1<<6);        // 8位数据, 1位起始位, 1位停止位, 无校验
    ES  = 1;        //允许中断
    REN = 1;        //允许接收

    B_TX1_Busy = 0;
    RX1_Cnt = 0;
}

// 串口1发送一个字节函数----
void UART1_TxByte(u8 dat)
{
    B_TX1_Busy = 1;                        //标志发送忙
    SBUF = dat;                                        //发一个字节
    while(B_TX1_Busy);        //等待发送完成
}

// timer0初始化函数(固定)
void Timer0_init(u32 clk)
{
    TR0 = 0;                                            //停止计数
    ET0 = 1;                                            //允许中断
    TMOD &= ~0x03;
    TMOD |= 0;                                          //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
    TMOD &= ~0x04;                                      //定时
    INTCLKO &= ~0x01;                                   //不输出时钟

    // 设置定时器0的时钟--小于则1T else 12T
    if (clk < 65536UL)
    {
        AUXR |=  0x80;                                  // 1T mode
        TH0 = (u8)((65536UL - clk) / 256);
        TL0 = (u8)((65536UL - clk) % 256);
    }
    else
    {
        AUXR &= ~0x80;                                  // 12T mode
        TH0 = (u8)((65536UL - clk/12) / 256);
        TL0 = (u8)((65536UL - clk/12) % 256);
    }

    TR0 = 1;    //开始运行
}

// 判断键值是否有效并设置触摸状态标志(固定)
void JudgeKey(u8 tkn)
{
    if(tkn > 15) return;  // 检查通道序号是否合法(最多支持16个通道)

    if(ChannelSet & (1<<tkn))  // 如果当前通道启用
    {
        if(TK_cnt[tkn] > TK_zero[tkn])  // 当前通道采样值高于基准零点(无触摸状态)
        {
            Zero_Sub_Cnt[tkn] = 0;  // 清除减计数(用于延迟下降)
            
            // 增计数未达到上限,则继续增加
            if(Zero_Add_Cnt[tkn] < 10)
            {
                Zero_Add_Cnt[tkn]++;
            }
            else
            {
                TK_zero[tkn] += 1;  // 增量追踪:慢慢抬高零点,适应环境变化
            }

            // 没有触摸的话,按键计数器慢慢减小
            if(TK_counter[tkn] > 0)
            {
                TK_counter[tkn]--;
            }
            else
            {
                // 若无持续触摸,则清除触摸标志位
                JudgeFlag &= ~(1<<tkn);
                tpFlag &= ~(1<<tkn);
            }
        }
        else if(TK_cnt[tkn] <= (TK_zero[tkn] - TK_differ[tkn]))  // 按键触摸有效(低于阈值)
        {
            Zero_Sub_Cnt[tkn] = 0;
            Zero_Add_Cnt[tkn] = 0;

            if(TK_cnt[tkn] <= (TK_zero[tkn] - TK_lowest[tkn]))  // 太低可能是干扰
            {
                TK_counter[tkn] = 0;  // 清除状态,干扰处理
            }
            else if((JudgeFlag & (1<<tkn)) == 0)  // 还没有设置按键触发标志
            {
                TK_counter[tkn]++;  // 连续触摸计数
                if(TK_counter[tkn] > ScanFreq)  // 达到设定的有效连续次数
                {
                    JudgeFlag |= (1<<tkn);  // 设置为有效触摸
                    tpFlag |= (1<<tkn);     // 同步触摸标志
                }
            }
        }
        else  // 处于过渡状态(无明显触摸、也不是回零)
        {
            Zero_Add_Cnt[tkn] = 0;

            // 延迟减计数,防止频繁追踪零点
            if(Zero_Sub_Cnt[tkn] < 100)
            {
                Zero_Sub_Cnt[tkn]++;
            }
            else
            {
                if(TK_cnt[tkn] < TK_zero[tkn])  // 如果当前值还是低于零点
                {
                    TK_zero[tkn] -= 1;  // 零点下调(自适应环境)
                    Zero_Sub_Cnt[tkn] = 0;
                }
            }

            // 如果没有稳定触摸,按键计数器也逐渐递减
            if(TK_counter[tkn] > 0)
            {
                TK_counter[tkn]--;
            }
            else
            {
                JudgeFlag &= ~(1<<tkn);  // 清除有效触摸标志
                tpFlag &= ~(1<<tkn);
            }
        }
    }
}

// 获取触摸按键的零值--环境自适应校准(固定)
void ReadZeroData(void)
{
    u8 i;

    // 获取零值
    if(B_Zero_Flag)
    {
        TK_TimeOut++;                           // 触摸按键超时计数器
        if(TK_TimeOut > 250)                        // 查看是否打到读取间隔
        {
            TK_TimeOut = 0;                     // 重置超时计数器
            read_cnt++;                         // 读取次数加1
        }
        
        // 如果已经读取超过100次(延迟足够长时间,环境稳定)
        if(read_cnt > 100)
        {
            // 扫描所有的通道
            for(i=0; i<16; i++)
            {
                TK_zero = TK_cnt;                // 保存当前计数为零点参考值
                TK_counter = 0;              // 清除运行中的计数器
            }
            B_Zero_Flag = 0;
        }
    }
}

// 触摸按键初始化
void TK_init(void)
{
    TSRT = 0x00;                                            // 没有LED分时扫描
    TSCHEN1 = 0x03;                                        // TK00~TK07
    TSCHEN2 = 0x00;                                        // TK08~TK15
    TSCFG1  = (7<<4) + 3;                                // 开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), 放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最小3
    TSCFG2  = 2;                                                    // 配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4)  1(1/2)  2(5/8)  3(3/4)
    TSCTRL = 0xA0;                                                // 开始自动扫描, 无平均, B7: TSGO,  B6: SINGLE,  B5: TSWAIT, B4: TSWUCS, B3: TSDCEN, B2: TSWUEN, B1 B0: TSSAMP
    IE2 |= 0x80;                                                // 使能触摸中断

    UART1_config(MAIN_Fosc, Baudrate);
    EA = 1;                                                    // 允许全局中断

    for(i=0; i<16; i++)
    {
        TK_differ = DIFF;                            // 设置初始差值
        TK_lowest = DIFF*3;                        // 设置初始下限值, 检测下限 = 阈值*3
        TK_counter = 0;
        Zero_Sub_Cnt = 0;
        Zero_Add_Cnt = 0;
    }
    tpFlag = 0;
    JudgeFlag = 0;
    read_cnt=0;
    TK_TimeOut = 0;
    B_Zero_Flag = 1;
    ChannelSet = ((u16)TSCHEN2 << 8) | TSCHEN1;

    ScanFreq = 50;                                            // 设置有效触摸按键持续检测时间
}

// 系统初始化
void system_init(void)
{
    P_SW2 |= 0x80;                                        // 允许访问XSF

    P1M0 &= ~0x03; P1M1 |= 0x03;                    // P10 11 高阻输入
    P3M0 |= 0xc0; P3M1 &= ~0xc0;                    // P36 37 推挽输出

    P_K0_LED = 1;                                        // 灭灯
    P_K1_LED = 1;

    Timer0_init(MAIN_Fosc/1000);                    // Timer 0 中断频率, 1000次/秒
    TK_init();                                      // 触摸按键初始化
}

// 主函数
void main(void)
{
    system_init();                                  // 系统初始化

    while (1)
    {
        ReadZeroData();
        
        if(B_1ms)
        {
            B_1ms = 0;

            for(i=0;i<16;i++)
            {
                JudgeKey(i);                            // 判断键值
            }

            B = (u8)tpFlag;
            if(B & 0x01) P_K0_LED = ~P_K0_LED;      // bit0
            if(B & 0x02) P_K1_LED = ~P_K1_LED;      // bit1
            
            tpFlag = 0;
            
            UART1_TxByte((u8)(TK_cnt[15] >> 8));    //发送触摸按键0的键值到串口绘图
            UART1_TxByte((u8)(TK_cnt[15]));
        }
    }
}

// timer0中断函数(固定)
void timer0_int (void) interrupt 1
{
    B_1ms = 1;      //1ms标志
}

// 串口1中断函数----
void UART1_int (void) interrupt 4
{
    if(RI)
    {
        RI = 0;
        if(RX1_Cnt >= 64) RX1_Cnt = 0;
        RX1_Buffer[RX1_Cnt] = SBUF;
        RX1_Cnt++;
    }

    if(TI)
    {
        TI = 0;
        B_TX1_Busy = 0;
    }
}

// 触摸按键中断(固定)
void TKSU_Interrupt(void) interrupt 13
{
    u8        j;
    j = TSSTA2;
    if(j & 0x40)        //数据溢出, 错误处理(略)
    {
        TSSTA2 |= 0x40;        //写1清零
    }
    if(j & 0x80)        //扫描完成
    {
        j &= 0x0f;
        TK_cnt[j] = TSDAT;        //保存某个通道的读数
        TSSTA2 |= 0x80;        //写1清零
        read_cnt++;                //读次数+1, 用于延时或读键计数
        TK_TimeOut = 0;
    }
}


以上整个代码已经可以用于触摸按键,但是触摸状态不太理想,想调试一下灵敏度
但是现在使用上位机读取不到数据
回复

使用道具 举报 送花

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

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-17 02:01:27 | 显示全部楼层
如图 现在正在测试的是TK0 TK1但是串口没数据
主频只能设置 获取不到 配置同理也是能设置 获取不到
截图202504170200384718.jpg

点评

这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考: https://www.stcaimcu.com/forum.p ... =3971&pid=51046 由于 8H1K08T 的这两个触摸按键跟串口脚复用: P3.0(TK08) P3.1(TK09) 如果使用 P3.0, P3.1 做  详情 回复 发表于 2025-4-17 10:14
回复 支持 反对

使用道具 举报 送花

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

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-17 10:14:27 | 显示全部楼层
HyunYon*** 发表于 2025-4-17 02:01
如图 现在正在测试的是TK0 TK1但是串口没数据
主频只能设置 获取不到 配置同理也是能设置 获取不到 ...

这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.p ... =3971&pid=51046
由于 8H1K08T 的这两个触摸按键跟串口脚复用: P3.0(TK08)   P3.1(TK09)
如果使用 P3.0, P3.1 做串口输出触摸值的话,TK08与TK09就不能使能触摸功能
DebugLab
回复 支持 反对

使用道具 举报 送花

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

6

主题

18

回帖

98

积分

注册会员

积分
98
发表于 2025-4-17 12:54:29 | 显示全部楼层
Debu*** 发表于 2025-4-17 10:14
这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.p ... =3971 ...

就是根据整个贴的内容修改的
没有串口数据
回复 支持 反对

使用道具 举报 送花

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

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-17 14:20:15 | 显示全部楼层
你使能的是TK0,TK1,但是串口输出的是TK15的数据:
  1.             UART1_TxByte((u8)(TK_cnt[15] >> 8));    //发送触摸按键0的键值到串口绘图
  2.             UART1_TxByte((u8)(TK_cnt[15]));
复制代码

如果希望输出TK0数据的话,TK_cnt[15] 要改成 TK_cnt[0]。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 02:30 , Processed in 0.191257 second(s), 75 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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