AI8H1K17T触摸按键读取
// 单片机-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; // 键计数值
u16 xdata TK_zero; // 0点读数
u16 code T_KeyState = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
// 读数有平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同
u16 code T_KeyPress = {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+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 = TSDAT/4; //保存某个通道的读数 无低通滤波
}
else
{
TK_cnt = ((TK_cnt * 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;
}
}
针对您提供的代码片段,我将从专业角度进行分析和优化建议,主要围绕STC8H1K17T单片机的触摸按键读取功能展开。
1. 代码分析
1.1 头文件与端口定义
c
include "STC8H.h"
include
include
sbit LED0 = P3^7;
sbit LED1 = P3^6;
sbit TK0= P1^0;
sbit TK1= P1^1;
#include "STC8H.h":这是STC8H系列单片机的专用头文件,包含了该系列单片机的寄存器定义和常用宏。
sbit 用于定义位变量,方便对单个引脚进行操作。LED0和LED1分别连接到P3.7和P3.6,TK0和TK1分别连接到P1.0和P1.1,用于触摸按键的检测。
1.2 宏定义与数据类型
c
define u8 unsigned char
define u16 unsigned int
define u32 unsigned long
define MAINFosc 24000000L
定义了常用的数据类型别名,便于代码的简洁性和可读性。
MAINFosc 定义了主时钟频率为24MHz,这是单片机工作的基准时钟。
1.3 数组与变量声明
c
u16 xdata TKcnt; // 键计数值
u16 xdata TKzero; // 0点读数
u16 code TKeyState = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
u16 code TKeyPress = {200,150,100,100, 200,150,100,100,
200,150,100,100, 200,150,100,100};
TKcnt 和 TKzero 是用于存储触摸按键的计数值和零点读数。
TKeyState 和 TKeyPress 分别是按键状态和按键按下时的变化值数组,用于判断按键是否被按下。
1.4 函数声明
c
void delayms(u8 ms); // 延时函数
u8 CheckKey(u16 j); // 按键检测函数
delayms 是一个延时函数,用于实现毫秒级的延时。
CheckKey 是按键检测函数,用于判断按键是否被按下。
2. 优化建议
2.1 头文件包含
建议在包含头文件时,确保所有必要的头文件都已包含。例如,#include和 #include可能存在缺失,应根据实际需求补充相应的头文件。
2.2 数据类型定义
建议使用stdint.h标准库中的数据类型,以提高代码的可移植性。例如:
c
include
typedef uint8t u8;
typedef uint16t u16;
typedef uint32t u32;
2.3 数组定义
TKeyState 和 TKeyPress 数组的定义可以进一步优化,使用更具描述性的名称,并添加注释说明每个元素的含义。
2.4 延时函数
delayms 函数的实现需要考虑主时钟频率,建议根据MAINFosc计算延时周期,以确保延时的准确性。
2.5 按键检测函数
CheckKey 函数的实现需要结合TKeyState和TKeyPress数组,判断按键是否被按下。建议在函数内部添加详细的注释,说明判断逻辑。
3. 总结
该代码片段展示了STC8H1K17T单片机触摸按键读取的基本框架,但在头文件包含、数据类型定义、数组命名和函数实现等方面仍有优化空间。通过上述建议,可以提高代码的可读性、可维护性和可移植性。
[本文内容由国芯人工智能辅助生成,仅供参考] rt HyunYong_7782 发表于 2025-4-15 00:17
rt
代码是用在STC9H1K17T SOP16上的,但是烧录以后
TK0 TK1没有反应,串口也检测不到读数 请直接使用例程测试:
直接烧录了第一个压缩包的例程 所有的端口都是这样的 这是正常的吗
这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=3971&pid=51046
由于 8H1K08T 的这两个触摸按键跟串口脚复用: P3.0(TK08) P3.1(TK09)
如果使用 P3.0, P3.1 做串口输出触摸值的话,TK08与TK09就不能使能触摸功能。 乘风飞扬 发表于 2025-4-15 16:27
这个帖子有 8H1K08T 使用串口绘图分析触摸值的例子可参考:
https://www.stcaimcu.com/forum.php?mod=redir ...
我这里已经用P30 31做串口输出了,我可否直接用您的代码更改一下触摸口测试呢 HyunYong_7782 发表于 2025-4-15 17:03
我这里已经用P30 31做串口输出了,我可否直接用您的代码更改一下触摸口测试呢 ...
可以的 .
页:
[1]