找回密码
 立即注册
查看: 537|回复: 6

编译通过,仿真时进不了触摸按键中断 | 已解决

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-12 10:34:29

13

主题

19

回帖

213

积分

中级会员

积分
213
发表于 2024-5-24 08:45:07 | 显示全部楼层 |阅读模式
我移植了触摸按键驱动程序,现在编译可以通过,但仿真时进入不了触摸按键的中断服务函数,请大家指点


//普通IO口控制数码管
/*******************接口说明*********************
P2.0~P2.7: 接SEG0~SEG7
P3.4~P3.7: 接COM0~COM3
P1.0-->TK0,  P1.1-->TK1, P5.4-->TK2, P1.3-->TK3
************************************************/
#define MAIN_Fosc        1200000L        //定义主时钟
#include        "STC8Hxxx.h"

u16        xdata TK_cnt[4];        // 键计数值
u16        xdata TK_zero[4];        // 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        isr_index;

u16 code T_KeyState[16]   = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
//        u16 code T_KeyPress[16]   = {400,300,200,200, 400,300,200,200, 400,300,200,200, 400,300,200,200};        //读数无平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同
u16 code T_KeyPress[16]   = {200,150,100,100, 200,150,100,100, 200,150,100,100, 200,150,100,100};        //读数有平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同

//---------------------------------------------------------------------------------------------
             //    0    1    2    3    4    5    6    7    8    9
u8 FontCode[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};  //字形码
           //  P3.4  P3.5 P3.6 P3.7
u8 Tab[] = {0x10,0x20,0x40,0x80};       //位码
u8 Dispbuf[4];   //显示缓存区
u8 Num = 0;      //显示位数计数器
//---------------------------------------------------------------------------------------------
/****************** 检测 计算键码 **************************************/
u8        CheckKey(u16 j)
{
        u8 i;
        if(j == 0)        return 0;        //无键按下
        for(i=0; i<16; i++)
        {
                if(j & 0x0001)        
                         break;
                j >>= 1;
        }
        return (i+1);        //键码1~16
}

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[j] = TSDAT/4;        //±£´æÄ³¸öͨµÀµÄ¶ÁÊý        ÎÞµÍͨÂ˲¨
                                else                                TK_cnt[j] = ((TK_cnt[j] * 3)>>2) + TSDAT/16;        //±£´æÄ³¸öͨµÀµÄ¶ÁÊý        µÍͨÂ˲¨
                                if(j == 15)        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 TM0_Isr() interrupt 1
{
//    P14 = !P14;                                 //????
    P3 = P3&0x0f;           
          P3 = P3|Tab[Num];      //高位按位数置1 低4位不变
          P2 = FontCode[Dispbuf[Num]];
          Num++;
          if(Num>3)
                         Num = 0;
}

void  delay_ms(u8 ms)
{
        u16 i;
        do
        {
                i = MAIN_Fosc / 10000;
                while(--i)        ;
        }
        while(--ms);
}

void main()
{
          u8        i;
         u16        j;

         P_SW2 |= 0x80;        //允许访问XSFR(扩展特殊功能寄存器)
        
                P0M0 = 0x00;                   //准双向口,传统8051模式         
                P0M1 = 0x00;
                P1M0 = 0x00;
                P1M1 = 0x00;
//    P2M0 = 0x00;
//    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
        
          P2n_push_pull(0xff);        //P2口数码管段码设置为推挽输出
          P3n_push_pull(0xf0);              //位码(P3.4~P3.7)线设置为推挽输出
          P1n_pure_input(0x0f);              //Touch Key设置为高阻
                P5n_pure_input(0x10);       //P5.4设置为高阻
        
          P2DR = 0x00;                      //段码线设置为强电流驱动  0 强电流驱动
          P3DR = 0x0f;                      //位码线设置为强电流驱动
               
                TSCHEN1 = 0x0f;                          //TK0~TK3 按键扫描通道
                TSCFG1  = (7<<4) + 6;        //开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+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)
          TSRT = 0x00;                //没有LED分时扫描
          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) +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<4; i++)               
           TK_zero = TK_cnt;        //保存0点
        
        B_TK_Lowpass = 1;        //允许低通
        KeyState = 0;
        read_cnt = 0;
        
        B_ReadKeyOk = 0;
        KeyValue = 10;
        KeyCode = 0;
//-----------------------------------------------------------------------------------
    TMOD = 0x00;                     //16位自动重载模式  受TR0控制 对内部震荡器计数
    TL0 = 0x66;                                 //65536-11.0592M/12/1000
    TH0 = 0xfc;
    TR0 = 1;                                    //启动定时器
    ET0 = 1;                                    //使能定时器0中断
//    EA = 1;
                 
                //P3 = P3&0x0f;         //P3.4~P3.7高4位清0  低4位不变

          Dispbuf[0] = 3;
                Dispbuf[1] = 4;
                Dispbuf[2] = 8;
                Dispbuf[3] = 9;
         
  while (1)
        {
                delay_ms(1);
               
                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;
//                        ShowValue(KeyValue);        //显示读数

                        j = KeyState;                //读入上一次键状态
                        for(i=0; i<4; 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~16
                                
                        }
                }
        }
}

下面的isr.asm文件加入到工程中了

EXTRN DATA        (isr_index)

        CSEG        AT        0103H                ;32ºÅ ²¨Ðη¢ÉúÆ÷5 ÖжÏÈë¿Ú
        MOV                isr_index, #32        ;±ê¼ÇÖжϺÅ32
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        010BH                ;33ºÅ ²¨Ðη¢ÉúÆ÷Òì³£2 ÖжÏÈë¿Ú
        MOV                isr_index, #33        ;±ê¼ÇÖжϺÅ33
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        0113H                ;34ºÅ ²¨Ðη¢ÉúÆ÷Òì³£4 ÖжÏÈë¿Ú
        MOV                isr_index, #34        ;±ê¼ÇÖжϺÅ34
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        011BH                ;35ºÅ ´¥Ãþ°´¼ü ÖжÏÈë¿Ú
        MOV                isr_index, #35        ;±ê¼ÇÖжϺÅ35
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        0123H                ;36ºÅ RTC ÖжÏÈë¿Ú
        MOV                isr_index, #36        ;±ê¼ÇÖжϺÅ36
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        012BH                ;37ºÅ P0¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #37        ;±ê¼ÇÖжϺÅ37
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿

        CSEG        AT        0133H                ;38ºÅ P1¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #38        ;±ê¼ÇÖжϺÅ38
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        013BH                ;39ºÅ P2¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #39        ;±ê¼ÇÖжϺÅ39
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        0143H                ;40ºÅ P3¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #40        ;±ê¼ÇÖжϺÅ40
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        014BH                ;41ºÅ P4¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #41        ;±ê¼ÇÖжϺÅ41
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        0153H                ;42ºÅ P5¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #42        ;±ê¼ÇÖжϺÅ42
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        015BH                ;43ºÅ P6¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #43        ;±ê¼ÇÖжϺÅ43
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        0163H                ;44ºÅ P7¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #44        ;±ê¼ÇÖжϺÅ44
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        016BH                ;45ºÅ P8¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #45        ;±ê¼ÇÖжϺÅ45
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        CSEG        AT        0173H                ;46ºÅ P9¿ÚÖжÏÈë¿Ú
        MOV                isr_index, #46        ;±ê¼ÇÖжϺÅ46
        LJMP        006BH                        ;Ìø×ªµ½ÖжϺÅ13µÄÏòÁ¿
        
        
        END

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15632
发表于 2024-5-24 13:45:02 | 显示全部楼层
触摸按键唤醒,演示程序见附件,1uA/1个键/1秒唤醒
===STC8H4K64TLCD触摸MCU, 唤醒【主时钟停振/省电模式
===STC8H4K64TL触摸MCU, 唤醒【主时钟停振/省电模式
===STC8H1K08T触摸MCU, 唤醒【主时钟停振/省电模式
触摸按键1秒唤醒一次, 1uA/一个键 + 2.4uA/32K振荡器需要电流,16个键<20uA
====增加1个键就是增加约1个uA
           1个键参与唤醒就是:      3.4uA = 2.4uA
/32K振荡器需要电流 + 1uA/一个键
           2个按键参与唤醒就是:【2.4uA+1uA * 2】= 4.4uA
           3个按键参与唤醒就是:
【2.4uA+1uA * 3】= 5.4uA
           4个按键参与唤醒就是:
【2.4uA+1uA * 4】= 6.4uA
           5个按键参与唤醒就是:
【2.4uA+1uA * 5】= 7.4uA
           ......
           16个按键参与唤醒就是:【2.4uA+1uA*16】= 18.4uA <=20uA

====如果2秒唤醒一次,电流再减半

STC的触摸按键是比较省电的,MCU进入睡眠后,主时钟关闭,自动启动内部的32KHz时钟,按设定的时间间隔扫描按键,
扫描结果自动比较阈值,超过阈值的键就会唤醒MCU。

MCU睡眠后,32KHz时钟启动,睡眠电流典型值2.4uA。例子为一秒检测一次按键。
如果允许检测16个按键,则每隔一秒自动检测一次所有16个触摸按键,任意一个触摸按键超过阈值均能唤醒MCU,
触摸的时间最长为1秒即可唤醒。

本例程序运行于24MHz,16键唤醒,睡眠时间967ms,睡眠电流为2.4uA左右@4V(一节锂电池),
检测触摸耗时16ms(每个按键1ms),电流1.1mA,则平均电流 = 2.4+1100*16/1000=20uA。
如果只允许一个按键,则检测一个按键时间为1ms,平均电流 = 2.4+1100*1/1000=3.5uA。

所以N个键唤醒,睡眠平均电流 = 2.4 + 1.1*N,单位uA。


触摸按键唤醒,1uA/1个键/1秒唤醒,STC触摸MCU, 唤醒【主时钟停振/省电模式】 - 触摸按键/80mA大电流LED数码管自动刷新显示/段码LCD/RTC实时时钟/低功耗 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:172
  • 最近打卡:2025-04-28 08:49:07
已绑定手机

90

主题

961

回帖

2318

积分

超级版主

积分
2318
QQ
发表于 2024-5-24 09:02:35 | 显示全部楼层
打包发上来
热线19952583534
www.STCAI.com
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-12 10:34:29

13

主题

19

回帖

213

积分

中级会员

积分
213
发表于 2024-5-24 10:01:04 | 显示全部楼层
附件为程序

Key-display.rar

168.95 KB, 下载次数: 54

程序

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6843

积分

论坛元老

积分
6843
发表于 2024-5-24 10:35:57 | 显示全部楼层
硬件仿真操作步骤参考演示视频:
https://www.stcaimcu.com/plugin. ... ee=1&id_7ree=63
我看你项目设置里面选择的是软件模拟仿真,没有选择硬件仿真,这样是收不到硬件中断的
截图202405241035219137.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-12 10:34:29

13

主题

19

回帖

213

积分

中级会员

积分
213
发表于 2024-5-24 11:06:03 | 显示全部楼层
乘风 你好,谢谢您的提醒。我没设置硬件仿真,现在改过来了。初始化中读零点键值成功了,但在主程序循环中进不了触摸按键中断,B_ReadKeyOk始终为0,不能进入判断键值程序。
触摸按键问题.png
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-12 10:34:29

13

主题

19

回帖

213

积分

中级会员

积分
213
发表于 2024-5-24 11:17:45 | 显示全部楼层
可以进入触摸按键中断,我用了4个按键,中断中扫描个数改成3  B_ReadKeyOk=1 就对了,能进判断键值程序了
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-3 08:12 , Processed in 0.133739 second(s), 90 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表