求救 触摸按键设置问题!
本帖最后由 zys0797 于 2024-5-12 17:26 编辑大家好,我是小白来学习。学习到触摸按键,参照这个链接立的程序实列触摸按键,3个重要视频,20-Pin触摸按键控制板,【触摸按键辅助开发软件】 - 触摸按键/80mA大电流LED数码管自动刷新显示/段码LCD/RTC实时时钟/低功耗 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com),下载了https://www.stcaimcu.com/static/image/filetype/rar.gif STC8H系列-触摸按键相关程序.rar 这个程序。只修改了测试指示LED为P3^6,编译后HEX烧录到STC8H1KO8T,使用STC按键触摸配置发现没有任何反映,如下图:
串口选择对应的COM口连接后,界面上点击获取、接受配置按钮,在输出消息栏里没有任何消息提示。但是点击设置、发送设置,在输出消息栏里有发送状态提示。触摸数据那里点击对应按键后读取也是没有任何数据。这是什么原因?
望群里的大师指点迷津!非常感谢!
顺便问下这个连接串口我使用的是这个USBliNK仿真器里的COM4口,我连接的是P3.1 和 P3.0,没有接其他外部的串口有没有什么影响?因为我感觉STC按键触摸配置这个程序选择哪个COM口不会报错。不知道是不是这个问题。
串口没连上,看下串口号和波特率选对没有 STC8H1K08T的P30,P31是TK8,TK9,使用串口工具进行配置的话需要将例程里面的TK8,TK9使能关闭,避免P30,P31被复用做其他功能导致串口通信失效。另外P30,P31的IO口模式设置为准双向模式。 乘风飞扬 发表于 2024-5-13 11:26
STC8H1K08T的P30,P31是TK8,TK9,使用串口工具进行配置的话需要将例程里面的TK8,TK9使能关闭,避免P30,P ...
你好,大师。红色是我修改的地方,其他未作修改。现在使用那个按键测试软件获取不了任何信息,不反馈。麻烦您帮我检查下到底是哪里的问题。
#define MAIN_Fosc 24000000L //定义主时钟串口波特率 300 ~ 4800
#include "stc8hxxx.h"
#include "intrins.h"
/************* 本地常量声明 **************/
sbit P_RUN_LED = P3^6; // 测试指示LED
sbit P_K0_LED= P2^5; // 按键指示LED
sbit P_K1_LED= P0^7;
sbit P_K2_LED= P4^1;
sbit P_K3_LED= P2^1;
sbit P_K4_LED= P3^7;
sbit P_K5_LED= P4^6;
sbit P_K6_LED= P2^4;
sbit P_K7_LED= P0^5;
sbit P_K8_LED= P4^2;
sbit P_K9_LED= P4^3;
sbit P_K10_LED = P2^3;
sbit P_K11_LED = P4^5;
sbit P_K12_LED = P2^0;
sbit P_K13_LED = P2^7;
sbit P_K14_LED = P2^6;
sbit P_K15_LED = P0^6;
/************* 本地变量声明 **************/
u16 xdata TK_cnt; // 按键计数值, 16位
u16 xdata TK_zero; // 按键0点值, 16位
u16 KeyState; // 按键状态, 每个bit对应一个键, 1为按下, 0为释放
u8 read_cnt; // 读次数
bit B_TK_Lowpass; // 低通允许, 1允许, 0禁止
u8 cmd; //串口命令
bit B_TX1_Busy; // 串口发送忙标志
/************* 本地函数声明 **************/
void DisplayRTC(void);
void delay_ms(u8 ms);
void UART1_config(u32 brt, u8 timer, u8 io); // brt: 通信波特率,timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,=1: 切换到P3.6 P3.7,=2: 切换到P1.6 P1.7,=3: 切换到P4.3 P4.4
void UART1_PrintString(u8 *puts);
void UART1_TxByte(u8 dat);
void ReturnValue(u8 channel, u16 value);
/****************外部函数声明和外部变量声明 *****************/
// K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14 K15
u16 code T_KeyPress={ 1300,2000,900, 800, 900, 1000, 1100, 1400,1000,1200, 900,1200,750, 900, 1300,1800}; //触摸后的变化值
u16 code T_KeyState={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000}; //16个键对应的状态, 0为未触摸,1为触摸
/********************* 主函数回调函数 *************************/
void main(void)
{
u8 i;
u16 j;
P3M0 &= ~0x03;
P3M1 &= ~0x03;
P_K0_LED = 0; P_K4_LED = 0; P_K8_LED = 0; P_K12_LED = 0; //熄灭所有LED
P_K1_LED = 0; P_K5_LED = 0; P_K9_LED = 0; P_K13_LED = 0;
P_K2_LED = 0; P_K6_LED = 0; P_K10_LED = 0; P_K14_LED = 0;
P_K3_LED = 0; P_K7_LED = 0; P_K11_LED = 0; P_K15_LED = 0;
P0n_push_pull(0xe0); //设置所有驱动LED的IO为推挽输出
P2n_push_pull(0xff);
P4n_push_pull(0x6e);
//P3n_push_pull(0x40); //P3.6设置为推挽输出
P1n_pure_input(0xff); //设置所有触摸键的O为高阻
P5n_pure_input(0x0f);
P0n_pure_input(0x0f);
P_SW2 |= 0x80; //允许访问扩展寄存器xsfr
EA = 1;
UART1_config(115200UL, 1, 0); // brt: 通信波特率,timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,=1: 切换到P3.6 P3.7,=2: 切换到P1.6 P1.7,=3: 切换到P4.3 P4.4
UART1_PrintString("STC8H系列触摸按键测试程序!\r\n");
TSCHEN1 = 0x10; //TK04
//TSCHEN2 = 0xff; //TK8~TK15
TSCFG1= (7<<4) + 6; //B6~B4:开关电容工作频率 = fosc/(2*(TSCFG1+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)
// TSCTRL = (1<<7) + (1<<6) +3; //开始扫描, B7: TSGO,B6: SINGLE,B5: TSWAIT, B4: TSWUCS, B3: TSDCEN, B2: TSWUEN, B1 B0: TSSAMP
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) +3; //开始扫描, 4次平均
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) +3; //开始扫描, 4次平均
// TSCTRL = (1<<7) + (1<<6) +1; //开始扫描, 2次平均
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) && ((TK_zero - TK_cnt) >= 300)) ShowValue(i,TK_zero - TK_cnt); //6ms有键按下则显示差值
// else ShowValue(i,TK_cnt); //无键按下则显示读数
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; //键状态: 释放
// TK_zero = TK_cnt; //快速0点回归(比如按着键上电)
// TK_zero += 50; //比较快速0点回归(比如按着键上电)
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) P_K0_LED = ~P_K0_LED;
if(B1) P_K1_LED = ~P_K1_LED;
if(B2) P_K2_LED = ~P_K2_LED;
if(B3) P_K3_LED = ~P_K3_LED;
if(B4) P_K4_LED = ~P_K4_LED;
if(B5) P_K5_LED = ~P_K5_LED;
if(B6) P_K6_LED = ~P_K6_LED;
if(B7) P_K7_LED = ~P_K7_LED;
B = (u8)(j >> 8);
if(B0) P_K8_LED= ~P_K8_LED;
if(B1) P_K9_LED= ~P_K9_LED;
if(B2) P_K10_LED = ~P_K10_LED;
if(B3) P_K11_LED = ~P_K11_LED;
if(B4) P_K12_LED = ~P_K12_LED;
if(B5) P_K13_LED = ~P_K13_LED;
if(B6) P_K14_LED = ~P_K14_LED;
if(B7) P_K15_LED = ~P_K15_LED;
}
if(cmd != 0)
{
if((cmd >= '0') && (cmd <= '9')) ReturnValue(cmd-'0', TK_cnt);
if((cmd >= 'a') && (cmd <= 'z')) cmd = cmd -'a'+'A'; //小写转大写
if((cmd >= 'A') && (cmd <= 'F')) ReturnValue(cmd-'A'+10, TK_cnt);
cmd = 0;
}
}
}
/**********************************************/
//========================================================================
// 函数: void ReturnValue(u8 channel, u16 value)
// 描述: 返回按键值函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2022-12-23
// 备注:
//========================================================================
void ReturnValue(u8 channel, u16 value)
{
// value = value / 100; //缩小为1/100, 数值小一些比较容易观察
UART1_TxByte('K');
UART1_TxByte(channel/10+'0');
UART1_TxByte(channel%10+'0');
UART1_TxByte('=');
UART1_TxByte(value / 10000 + '0');
UART1_TxByte((value % 10000)/1000 + '0');
UART1_TxByte((value % 1000)/100 + '0');
UART1_TxByte((value % 100)/10 + '0');
UART1_TxByte(value % 10 + '0');
UART1_TxByte(0x0d);
UART1_TxByte(0x0a);
}
//========================================================================
// 函数: voiddelay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
voiddelay_ms(u8 ms)
{
u16 i;
do
{
i = MAIN_Fosc / 10000;
while(--i) ;
}while(--ms);
}
/**********************************************/
u8 isr_index;
//========================================================================
// 函数: void TKSU_ISR(void) interrupt TKSU_VECTOR
// 描述: 触摸按键中断服务函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2023-10-11
// 备注:
void TKSU_ISR(void) interrupt TKSU_VECTOR
{
u8 j;
j = TSSTA2;
if(j & 0x40) //数据溢出, 错误处理(略)
{
TSSTA2 |= 0x40; //写1清零
}
if(j & 0x80) //扫描完成
{
P_RUN_LED = 1; //整个处理时间 1.1us @24MHz
j &= 0x0f;
TSSTA2 |= 0x80; //写1清零
if(!B_TK_Lowpass) TK_cnt = TSDAT; //保存某个通道的读数 1.1us @24MHz
// else TK_cnt = (u16)(((u32)TK_cnt * 3) >> 2) + (TSDAT >> 2); //保存某个通道的读数 低通滤波 8us @24MHz
// else TK_cnt = (TK_cnt >> 2) * 3 + (TSDAT >> 2); //保存某个通道的读数 低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500.
else TK_cnt = (TK_cnt >> 1) + (TSDAT >> 1); //保存某个通道的读数 1/2低通滤波 4.6us @24MHz, 低通a=0.25, 未按键读数20000, 按键读数21600, 则要11个次采样点(100Hz采样110ms)读数才到21500.
P_RUN_LED = 0;
}
}
//========================================================================
// 函数: SetTimer2Baudraye(u16 dat)
// 描述: 设置Timer2做波特率发生器。
// 参数: dat: Timer2的重装值.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void SetTimer2Baudraye(u16 dat) // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
{
AUXR &= ~(1<<4); //Timer stop
AUXR &= ~(1<<3); //Timer2 set As Timer
AUXR |=(1<<2); //Timer2 set as 1T mode
TH2 = (u8)(dat >> 8);
TL2 = (u8)dat;
IE2&= ~(1<<2); //禁止中断
AUXR |=(1<<4); //Timer run enable
}
//========================================================================
// 函数: void UART1_config(u32 brt, u8 timer, u8 io)
// 描述: UART1初始化函数。
// 参数: brt: 通信波特率.
// timer: 波特率使用的定时器, timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率.
// io: 串口1切换到的IO,io=1: 串口1切换到P3.0 P3.1,=1: 切换到P3.6 P3.7,=2: 切换到P1.6 P1.7,=3: 切换到P4.3 P4.4
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_config(u32 brt, u8 timer, u8 io) // brt: 通信波特率,timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,=1: 切换到P3.6 P3.7,=3: 切换到P4.3 P4.4
{
brt = 65536UL - (MAIN_Fosc / 4) / brt;
if(timer == 2) //波特率使用定时器2
{
AUXR |= 0x01; //S1 BRT Use Timer2;
SetTimer2Baudraye((u16)brt);
}
else //波特率使用定时器1
{
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中断
INT_CLKO &= ~0x02; // Timer1不输出高速时钟
TR1= 1; // 运行Timer1
}
if(io == 1) {S1_USE_P36P37(); P3n_standard(0xc0);} //切换到 P3.6 P3.7
else if(io == 2) {S1_USE_P16P17(); P1n_standard(0xc0);} //切换到 P1.6 P1.7
else if(io == 3) {S1_USE_P43P44(); P4n_standard(0x18);} //切换到 P4.3 P4.4
else {S1_USE_P30P31(); P3n_standard(0x03);} //切换到 P3.0 P3.1
SCON = (SCON & 0x3f) | (1<<6); // 8位数据, 1位起始位, 1位停止位, 无校验
// PS= 1; //高优先级中断
ES= 1; //允许中断
REN = 1; //允许接收
}
//========================================================================
// 函数: void UART1_TxByte(u8 dat)
// 描述: 串口1发送一个字节函数
// 参数: dat: 要发送的单字节数据.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_TxByte(u8 dat)
{
B_TX1_Busy = 1; //标志发送忙
SBUF = dat; //发一个字节
while(B_TX1_Busy); //等待发送完成
}
//========================================================================
// 函数: void UART1_PrintString(u8 *puts)
// 描述: 串口1字符串打印函数
// 参数: puts: 字符串指针.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_PrintString(u8 *puts)
{
for (; *puts != 0; puts++)
{
UART1_TxByte(*puts);
}
}
//========================================================================
// 函数: void UART1_ISR (void) interrupt UART1_VECTOR
// 描述: 串口1中断函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_ISR (void) interrupt UART1_VECTOR
{
if(RI)
{
RI = 0;
cmd = SBUF;
}
if(TI)
{
TI = 0;
B_TX1_Busy = 0;
}
}
电子DIY小家 发表于 2024-5-13 08:47
串口没连上,看下串口号和波特率选对没有
看起来像是串口没有连接上。但是检测软件不报错。 使用附件例子,参考下面帖子介绍方法试试:
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=3971&pid=51046 乘风飞扬 发表于 2024-5-13 19:03
使用附件例子,参考下面帖子介绍方法试试:
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpo ...
我使用ISPV6.94E,里面只能使用STC-USB-HID-UART1(link1)烧录下载程序,我看了示例里面可以直接使用串口烧录和通讯,但是我的根本不能选择里面的CDC1和CDC2两个串口,如果选择了CDC串口后点下载/编程就会一直提升“检测目标单片机 ... ”!就无法这个下载程序。这个需要怎么设置吗?是不是MCU需要怎么设置? zys0797 发表于 2024-5-14 10:03
我使用ISPV6.94E,里面只能使用STC-USB-HID-UART1(link1)烧录下载程序,我看了示例里面可以直接使用串口烧 ...
烧录完成后再打开CDC1串口进行通信。 乘风飞扬 发表于 2024-5-14 10:20
烧录完成后再打开CDC1串口进行通信。
我是这样操作的,收不到曲线。在ISP看那个CDC助手里那个接收缓冲区都是些这种数据。
63 23 63 23 63 23 63 24 63 24 63 1C 63 1C 63 1C
63 1B 63 1B 63 1B 63 17 63 17 63 17 63 2A 63 2A
63 2A 63 0E 63 0E 63 1F 63 1F 63 1F 63 1C 63 1C
63 1C 63 09 63 09 63 09 63 18 63 18 63 18 63 1D
63 1D 63 13 63 13 63 13 63 19 63 19 63 19 63 22
63 22 63 22 63 15 63 15 63 15 63 25 63 25 63 29
63 29 63 29 63 11 63 11 63 11 63 21 63 21 63 21
63 0E
你遇到的问题,也许与我开始弄触摸功能的时候遇到的问题相同。
最后只能直接用例程。
页:
[1]
2