8H1K17T SOP-16 上位机读取不到触摸数据
// 头文件/*
不要少了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路触摸的当前实时电容值
u16 xdata TK_zero; // 存储16路触摸的基准值
u16 xdata TK_differ; // 存储16路触摸的差值--判断触摸是否发生
u16 xdata TK_lowest; // 存储16路触摸的最小电容值
u8 xdata Zero_Add_Cnt; // 向上追踪延时计数器
u8 xdata Zero_Sub_Cnt; // 向下追踪延时计数器
u8 xdata TK_counter; // 状态缓冲计数器-判断有效触摸
u8xdata RX1_Buffer; // 串口接收缓冲区
// TP0TP1TP2TP3TP4TP5TP6TP7 TP8TP9 TP10TP11TP12TP13TP14TP15
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; // 通用变量
u8TK_TimeOut; // 触摸按键扫描超时
u8 read_cnt; // 记录触摸按键读取次数
u8RX1_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 > TK_zero)// 当前通道采样值高于基准零点(无触摸状态)
{
Zero_Sub_Cnt = 0;// 清除减计数(用于延迟下降)
// 增计数未达到上限,则继续增加
if(Zero_Add_Cnt < 10)
{
Zero_Add_Cnt++;
}
else
{
TK_zero += 1;// 增量追踪:慢慢抬高零点,适应环境变化
}
// 没有触摸的话,按键计数器慢慢减小
if(TK_counter > 0)
{
TK_counter--;
}
else
{
// 若无持续触摸,则清除触摸标志位
JudgeFlag &= ~(1<<tkn);
tpFlag &= ~(1<<tkn);
}
}
else if(TK_cnt <= (TK_zero - TK_differ))// 按键触摸有效(低于阈值)
{
Zero_Sub_Cnt = 0;
Zero_Add_Cnt = 0;
if(TK_cnt <= (TK_zero - TK_lowest))// 太低可能是干扰
{
TK_counter = 0;// 清除状态,干扰处理
}
else if((JudgeFlag & (1<<tkn)) == 0)// 还没有设置按键触发标志
{
TK_counter++;// 连续触摸计数
if(TK_counter > ScanFreq)// 达到设定的有效连续次数
{
JudgeFlag |= (1<<tkn);// 设置为有效触摸
tpFlag |= (1<<tkn); // 同步触摸标志
}
}
}
else// 处于过渡状态(无明显触摸、也不是回零)
{
Zero_Add_Cnt = 0;
// 延迟减计数,防止频繁追踪零点
if(Zero_Sub_Cnt < 100)
{
Zero_Sub_Cnt++;
}
else
{
if(TK_cnt < TK_zero)// 如果当前值还是低于零点
{
TK_zero -= 1;// 零点下调(自适应环境)
Zero_Sub_Cnt = 0;
}
}
// 如果没有稳定触摸,按键计数器也逐渐递减
if(TK_counter > 0)
{
TK_counter--;
}
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+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 >> 8)); //发送触摸按键0的键值到串口绘图
UART1_TxByte((u8)(TK_cnt));
}
}
}
// 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 = 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 = TSDAT; //保存某个通道的读数
TSSTA2 |= 0x80; //写1清零
read_cnt++; //读次数+1, 用于延时或读键计数
TK_TimeOut = 0;
}
}
以上整个代码已经可以用于触摸按键,但是触摸状态不太理想,想调试一下灵敏度
但是现在使用上位机读取不到数据 如图 现在正在测试的是TK0 TK1但是串口没数据
主频只能设置 获取不到 配置同理也是能设置 获取不到 HyunYong_7782 发表于 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 发表于 2025-4-17 10:14
这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.p ... =3971 ...
就是根据整个贴的内容修改的
没有串口数据 你使能的是TK0,TK1,但是串口输出的是TK15的数据:
UART1_TxByte((u8)(TK_cnt >> 8)); //发送触摸按键0的键值到串口绘图
UART1_TxByte((u8)(TK_cnt));
如果希望输出TK0数据的话,TK_cnt 要改成 TK_cnt。
页:
[1]