xxkj2010 发表于 2023-12-31 15:25:43

使用触控的同时,可以开启ADC中断吗?(已解决)

本帖最后由 xxkj2010 于 2023-12-31 15:47 编辑

单片机用STC8H1K17T,使用触控功能后开启ADC中断,则发现触摸失效,不知道触控中断是否与ADC中断是否冲突?

神农鼎 发表于 2023-12-31 15:29:03

ADC 和 触摸 是各自独立的

xxkj2010 发表于 2023-12-31 15:34:14

/*
单片机:STC8H1K17T
使用触摸引脚:TK3、TK6、TK7
*/

#include        "STC8Hxxx.h"
#include <intrins.h>
#include <stdio.h>

/*************        功能说明        *************
读取16个触摸按键
触摸按键的读数本来是16位的, 由于使用了滤波算法, 滤波后数据为14位的.
参考电容的选取, 未按键时读数是满量程的1/3~1/2比较好, 兼顾灵敏度, 量产时又允许一定的平偏差.
程序会做缓慢的0点跟踪, 所以本例不合适长按处理, 长按处理还要有别的算法.
P1.0-->TK0,P1.1-->TK1, P5.4-->TK2, P1.3-->TK3, P1.4-->TK4,P1.5-->TK5, P1.6-->TK6, P1.7-->TK7,
P5.0-->TK8,P5.1-->TK9, P5.2-->TK1, P5.3-->TK1, P0.0-->TK1,P0.1-->TK1, P0.2-->TK1, P0.3-->TK1,
******************************************/

/*************        本地常量声明        **************/
#define        DIS_BLACK        0x1A
#define        DIS_                0x1B
#define LED P54            //LED
#define ws2812b_IO    P35      //WS2812信号输入口
#define MAIN_Fosc          24000000L        //定义主时钟 11059200
#define BAUD      (65536 - MAIN_Fosc/4/115200)   //定义串口波特率重装值
bit fBusy;                                     //串口发送忙标志
u16 AUXR_ISR_YN=0;
/*************        本地变量声明        **************/
u16        xdata TK_cnt;        // 键计数值
u16        xdata TK_zero;        // 0点读数
u16        KeyState;                //键状态
u8        KeyCode;                //键码 1~16
bit        B_TK_Lowpass;        //允许低通
bit        B_ReadKeyOk;        //标志已转换完成16个键
u8        TrigLimit;                //触发转换限时
u8        KeyValue;                //显示参数的键号, 0~15
u8        read_cnt;
u8 ADCval;                                    //ADC测量结果

/*************        本地函数声明        **************/
voiddelay_ms(u8 ms);
u8                CheckKey(u16 j);
/****************外部函数声明和外部变量声明 *****************/
        u16 code T_KeyState   = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
//        u16 code T_KeyPress   = {400,300,200,200, 400,300,200,200, 400,300,200,200, 400,300,200,200};        //读数无平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同
        u16 code T_KeyPress   = {200,150,100,100, 200,150,100,100, 200,150,100,100, 200,150,100,100};        //读数有平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同

/**********************************************/
void main(void)
{
        u8        i;
        u16        j;
                fBusy = 0;
        P_SW2 |= 0x80;        //允许访问XSFR(扩展特殊功能寄存器)
//        XOSCCR = 0xc0;         //启动外部晶振
//        while (!(XOSCCR & 1));   //等待时钟稳定
//        CLKDIV = 0x00;         //时钟不分频
//        CKSEL = 0x01;            //选择外部晶振

        P0M0 = 0x00;        P0M1 = 0x00;
//        P1M0 = 0x00;        P1M1 = 0x00;
//        P3M0 = 0x00; P3M1 = 0x00;
        P5M0 = 0x10; P5M1 = 0x00;        
    P3M0 = 0x00; P3M1 = 0x08;                  //设置P33为ADC输入口

    ADCTIM = 0x3f;                              //设置ADC内部时序
    P_SW2 &= 0x7f;
    ADCCFG = 0x0f;                              //设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x8B;                      //开启ADC电源,选择第11通道ADC
    EADC = 1;                                 //使能ADC中断
//    EA = 1;
    ADC_CONTR |= 0x40;                        //启动AD转换
               
               
    AUXR = 0x40;                              //使用定时器1作为串口波特率发生器
    TMOD = 0x00;
    TL1 = BAUD;
    TH1 = BAUD >> 8;
    TR1 = 1;
    SCON = 0x50;
    ES = 1;
       
        P1n_pure_input(0xff);        //Touch Key设置为高阻

//        TSCHEN = 0xffff;        //TK0~TK15
        TSCHEN1 = 0xff;                //TK0~TK7
//        TSCHEN2 = 0xff;                //TK8~TK15
        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)
//        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;                //允许触摸按键中断
        EA = 1;

        delay_ms(50);
//        B_TK_Lowpass = 0;        //禁止低通滤波
        B_TK_Lowpass = 1;        //允许低通滤波
        for(read_cnt=0; read_cnt<40; read_cnt++)                //读40次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
        {
        //        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, 4次平均, 读数大约为无平均的一半
                TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
        //        TSCTRL = (1<<7) + (1<<6);                //开始扫描, 只转换1次, 无平均
                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");
        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) +3;        //开始扫描, 4次平均, 读数大约为无平均的一半
                        TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
                //        TSCTRL = (1<<7) + (1<<6);                //开始扫描, 只转换1次, 无平均
                }
               
                if(B_ReadKeyOk)                        // 16个键都转换完毕
                {
                        B_ReadKeyOk = 0;
                        TrigLimit = 100;
                        //printf("B_ReadKeyOk!\r\n");

                        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 == 4)
                                {
                                        LED=!LED;
                                        printf("ADC:0x%x\r\n",(u16)ADCval);
                                }
                        }
                }
        }
}
/**********************************************/

voiddelay_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
}


u8        isr_index;

void        AUXR_ISR(void) interrupt 13
{
        u8        j;
       
        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;
//      CheckCustomCmd(SBUF);                   //检测命令序列
    }
}

void ADC_Isr() interrupt 5
{
    ADC_CONTR &= ~0x20;                         //清中断标志
    ADCval = ADC_RES;                               //读取ADC结果       
    ADC_CONTR |= 0x40;                        //继续AD转换
}

char putchar(char dat)                        //重定义putchar系统函数
{
    while (fBusy);
    fBusy = 1;
    SBUF = dat;   
    return dat;
}


xxkj2010 发表于 2023-12-31 15:46:42

本帖最后由 xxkj2010 于 2023-12-31 15:47 编辑

哦,找到问题所在了。
是因为没有注释掉ADC例程中的P_SW2 &= 0x7f;


lovelong 发表于 2024-7-2 16:18:08

xxkj2010 发表于 2023-12-31 15:46
哦,找到问题所在了。
是因为没有注释掉ADC例程中的P_SW2 &= 0x7f;

有没有修改好的程序,固件,发一下,我也是测试触摸键失败

xxkj2010 发表于 2024-7-2 19:15:36

lovelong 发表于 2024-7-2 16:18
有没有修改好的程序,固件,发一下,我也是测试触摸键失败

这个试试,我是亲测过好用的。

xxkj2010 发表于 2024-7-2 19:16:38

lovelong 发表于 2024-7-2 16:18
有没有修改好的程序,固件,发一下,我也是测试触摸键失败
经过测试对比,STC的触摸功能是最容易用的。

lovelong 发表于 2024-7-3 08:06:19

xxkj2010 发表于 2024-7-2 19:15
这个试试,我是亲测过好用的。

谢谢大神

lovelong 发表于 2024-7-3 08:09:46

本帖最后由 lovelong 于 2024-7-3 08:46 编辑


[*]单片机:STC8H1K17T
把程序刷进去,测试,都没有反应{:4_168:}
使用P5.4===TK2,,,P3.3---TK11这两个端口做为触摸键。。。

xxkj2010 发表于 2024-7-3 11:21:49

本帖最后由 xxkj2010 于 2024-7-3 11:24 编辑

lovelong 发表于 2024-7-3 08:09单片机:STC8H1K17T
把程序刷进去,测试,都没有反应
使用P5.4===TK2,,,P3.3---TK11这两个端口做为触摸 ...
你的PCB设计有问题吗?
有关PCB设计,我当前也请教了论坛大神
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=5778

页: [1] 2 3
查看完整版本: 使用触控的同时,可以开启ADC中断吗?(已解决)