- 打卡等级:偶尔看看II
- 打卡总天数:20
- 最近打卡:2025-09-02 10:48:00
已绑定手机
注册会员
- 积分
- 196
|
// 头文件
#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 的触摸按键程序
这样配置没问题么 为什么在实际使用的过程中触摸按键不是很灵敏
|
|