打印

stc+adc按键+状态机,程序能运行,但按键切换时间可达40多秒,不知道哪里出错

[复制链接]
1529|31
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chen915|  楼主 | 2020-8-28 17:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
新人首帖。使用stc单片机+adc按键+状态机消抖,程序能运行,但按键切换时间可达40多秒,不知道哪里出错。请走过路过帮看下啊,不胜感激

等会附上原理图部分,以及源码。

使用特权

评论回复

相关帖子

沙发
chen915|  楼主 | 2020-8-28 17:11 | 只看该作者
本帖最后由 chen915 于 2020-8-31 16:39 编辑
#include "stc12c5630ad.h"

typedef unsigned char u8 ;
typedef unsigned int u16 ;

#define buzz                 P32
#define led                 P31
#define adc_key         P11
#define VCC                 5000

u8 aaa = 0 ;
u8 flag__key_scan ;
u8 key_number ;
u8 key_number_final ;
unsigned char flag1 , flag2 ;  //两个软定时标志位,前者为LED亮的时间段,后者为灭
unsigned int soft_timer_counter  , led_on_time , led_off_time ; //软定时自增变量,led亮时间,LED灭时间
typedef void (*VOID)(void) ;  //先定义函数指针
VOID funtion_run ;

void buzz_on(void)
{
        buzz = 1 ;
}

void buzz_off(void)
{
        buzz = 0 ;
}

void led_on(void)
{
        led = 0 ;
}

void led_off(void)
{
        led = 1 ;
}

void set_timer(u16 led_on_time_temp , u16 led_off_time_temp , VOID funtion1 , VOID funtion2)
{        //3、第一个参数为LED点亮时长,第二位灭时长,三为亮函数,四为灭函数
        led_on_time = led_on_time_temp ;
        led_off_time = led_off_time_temp ;
        
        if(flag1 == 1)
        {
                flag1 = 0 ;
                funtion_run = funtion1 ; //指针指向亮函数
                funtion_run() ;                  //并运行所指向的函数
        }
        if(flag2 == 1)
        {
                flag2 = 0 ;
                funtion_run = funtion2 ; //指针指向灭函数
                funtion_run() ;                  //并运行所指向的函数
        }
}
/*******************************************************************************************************************************/
//P1M0 , P1M1 , ADC_CONTR=[ADC_POWER][SPEED1][SPEED0][ADC_FLAG]    [ADC_START][CHS2][CHS1][CHS0]
//ADC_DATA , ADC_LOW2,AUXR=[T0x12][T1x12][UART_M0x12][EADCI][ESPI][ELVDI][-][-],IE,IP,IPH
/*******************************************************************************************************************************/
#define adc_power_on (ADC_CONTR |= 0x80)
#define adc_power_off (ADC_CONTR &= 0x7f)

#define adc_flag_set (ADC_CONTR |= 0x10)
#define adc_flag_clear (ADC_CONTR &= 0xef)

#define adc_start_on (ADC_CONTR |= 0x08)
#define adc_start_off (ADC_CONTR &= 0xf7)

enum key_number  //键值枚举声明
{
        key1 = 1 , key2 ,
        key3 , key4 ,
        key5 , key6 ,
        key7 , key8 ,
        key9 , key10  //代表未按下
} ;

enum key_statues //按键状态枚举,分别为初始状态,按下状态,确认按下状态,松手状态
{
        key_statues0 = 0 , //初始态
        key_statues1 = 1 , //按下态
        key_statues2 ,     //确认按下态
        key_statues3 ,                 //松手态
} ;
/*****************************************
*****************************************/
/*****************************************
*****************************************/
/*****************************************
*****************************************/
void adc_init(void) //ADC初始化
{
        ADC_CONTR = 0x61 ;  //0110 0001 //关adc,270个周期转换一次,关标志位,关闭启动位,选择1通道
        adc_power_on ;         //重开adc
        adc_start_on ;         //开启转换
        adc_flag_clear ; //清adc转换标志位
}

u16 adc_result()  //获取ADC值
{
        u16 result = 0 ; //32bit数据装载10bit的adc转换结果值
        u16 value = 0  ;
        adc_init() ;         

        while(!(ADC_CONTR & 0x10)) ;  //& 0001 0000,若是完成转换,则bit5为1,与上0x10,仍为1,再取反为0,则跳过改行执行下一行
        result = ADC_DATA*4 + ADC_LOW2 ; //ADC_DATA寄存器为8bit,左移两位,再加上ADC_LOW2的值,即可得到转换后完整的10bit结果
        adc_flag_clear ; //清除ADC_FLAG标志位

        return result ;
}

u16 adc_hex2dec(float value) //16进制电压值转10进制,单位为mV毫伏
{
        float value_dec ;
        value_dec = (VCC * (value))/1024 ;        
        
        return (u16)value_dec ;
}

/*****************************************
*  00 准双向io口                01 推挽输出
*  10 高阻输入                  11 开漏
*****************************************/
void gpio_init()  //gpio初始化函数
{
        P1 = 0x02 ; //0000 0010
        P1M0 = 0x02 ; //0000 0010   
        P1M1 = 0x00 ; //0000 0000  设置按键为输入
        
        P3 = 0x06 ; //0000 0110
        P3M0 = 0x00 ; //0000 0000  
        P3M1 = 0x06 ; //0000 0110  设置蜂鸣器和LED为输出
}

/*****************************************
*****************************************/
u8 adc_key_value_process(u16 adc_value)  //通过adc值定义键值并返回..........该函数有问题,需要对adc电压值进行更好的处理
{
        u16 temp_adc_value = adc_value ; //中间变量
        temp_adc_value /= 100 ; //对100求模,若是需要更高精度,可改100为更小值
        
        switch (temp_adc_value) //temp_adc_value精度存在严重问题,建议再用一个switch语句判断键值,使电压值转化为0-10的数字
        {
                case 41 :         //按键1按下电压值为4100mV左右
                        return 1 ;    //返回1
                case 35 :
                        return 2 ;
                case 30 :
                        return 3 ;
                case 25 :
                        return 4 ;
                case 21 :
                        return 5 ;
                case 15 :
                        return 6 ;
                case 10 :
                        return 7 ;
                case 5 :
                        return 8 ;
                case 0 :
                        return 9 ;
               
                default :        //未按下,返回0
                        return 0 ;
        }

/************************************************************************************************
//                adc_value = adc_hex2dec(adc_result()) ;
//                if((adc_value>=0) && (adc_value<=5000)) //若是有按键按下,则按键对号
//                {
//                        if(0 == adc_value)
//                                return 9;
//                        else if((adc_value <  723)  && (adc_value >  323))  //+-200mV
//                                return 8;
//                        else if((adc_value < 1254)  && (adc_value >  854))
//                                return 7;
//                        else if((adc_value < 1742)  && (adc_value > 1342))
//                                return 6;
//                        else if((adc_value < 2338)  && (adc_value > 1938))
//                                return 5;
//                        else if((adc_value < 2778)  && (adc_value > 2378))
//                                return 4;
//                        else if((adc_value < 3237)  && (adc_value > 2837))
//                                return 3;
//                        else if((adc_value < 3793)  && (adc_value > 3393))
//                                return 2;
//                        else if((adc_value < 4306)  && (adc_value > 3906))
//                                return 1;
////                        else if((adc_value <= 5000)  && (adc_value > 4795-244))  //无按键按下
////                                return 10;
//                }
//                else         //出错,则返回0
//                {
//                        return 0 ;
//                }
**************************************************************************************************/
}
/*****************************************
*****************************************/
u8 key_scan(void) //状态机函数,返回状态机键值
{
                static u8 key_statues = key_statues0 ; //相当于锁,函数运行前与运行完,都要置0
                static u8 adc_key_number_temp ;
                u8 key_return ;        

                adc_key_number_temp = adc_key_value_process(adc_hex2dec(adc_result())) ;//采集adc,并转化为键值
                key_number = adc_key_number_temp ;
                switch(key_statues)
                {
                        case key_statues0 : //初始态,也相当于锁
                        {
                                if(0 != key_number) //若是有按键按下,则迁移至状态1------有按键按下时,key_number不会为0
                                {
                                        key_statues = key_statues1 ;
                                }
                        }
                        break ;
                        
                        case key_statues1 : //按下态
                        {
                                if(0 == key_number)        //如果只是抖动,则返回状态0
                                {
                                        key_statues = key_statues0 ;
                                }
                                
                                else
                                {
                                        key_statues = key_statues2 ;  //若是确实有按下,则迁移到状态2
                                        key_number_final = key_number ; //如果确实有按键按下,则保存先前的key_number值
#if 0                                       
//                                        switch (key_number)        //若是按下有效,则将代码段放在此处
//                                        {
//                                                case 9 :
//                                                {
//                                                        key_return = key9 ;
//                                                }
//                                                break ;
//                                                
//                                                case 8 :
//                                                {
//                                                        key_return = key8 ;
//                                                }
//                                                break ;
//                                                
//                                                case 7 :
//                                                {
//                                                        key_return = key7 ;
//                                                }
//                                                break ;
//                                                
//                                                case 6 :
//                                                {
//                                                        key_return = key6 ;
//                                                }
//                                                break ;
//                                                
//                                                case 5 :
//                                                {
//                                                        key_return = key5 ;
//                                                }
//                                                break ;
//                                                
//                                                case 4 :
//                                                {
//                                                        key_return = key4 ;
//                                                }
//                                                break ;
//                                                
//                                                case 3 :
//                                                {
//                                                        key_return = key3 ;
//                                                }
//                                                break ;
//                                                
//                                                case 2 :
//                                                {
//                                                        key_return = key2 ;
//                                                }
//                                                break ;
//                                                
//                                                case 1 :
//                                                {
//                                                        key_return = key1 ;
//                                                }
//                                                break ;
//                                                
////                                                case 10 :        //该处移往松手态
////                                                {
////                                                        key_return = key10 ;        
////                                                }
////                                                break ;
#endif
                                }
                        }        
                        break ;
                        
                        case key_statues2 : //确认按下态,确认按下之后就应该判断是否松手,并进行消抖
                        {
                                if(0 == key_number)                //若已松手,迁移至状态3,相当于松手消抖
                                        key_statues = key_statues3 ;
                        }
                        break ;
                        
                        case key_statues3 : //松手态
                        {
                                if(0 == key_number) //确实已经松手
                                {        
                                        key_statues = key_statues0 ; //如果是确认无按键按下,则将状态迁移回状态0,即初始态。相当于自锁
//                                        key_return = key10 ;        //松手返回key10
                                        adc_key_number_temp = 0 ;
                                       
                                        switch (key_number_final)        //松手后键值有效
                                        {
                                                case 9 :
                                                        key_return = key9 ;
                                                        break ;
                                                
                                                case 8 :
                                                        key_return = key8 ;
                                                        break ;
                                                
                                                case 7 :
                                                        key_return = key7 ;
                                                        break ;
                                                
                                                case 6 :
                                                        key_return = key6 ;
                                                        break ;
                                                
                                                case 5 :
                                                        key_return = key5 ;
                                                        break ;
                                                
                                                case 4 :
                                                        key_return = key4 ;
                                                        break ;
                                                
                                                case 3 :
                                                        key_return = key3 ;
                                                        break ;
                                                
                                                case 2 :
                                                        key_return = key2 ;
                                                        break ;
                                                
                                                case 1 :
                                                        key_return = key1 ;
                                                        break ;
                                                
                                                case 0:
                                                        key_return = key10 ;
                                                        break ;
                                        }
                                }
                                else
                                {
                                        key_statues = key_statues2 ; //否则回到状态2,即再判断一次
                                }
                        }
                        break ;
                }
        
                return key_return ;
}

void key_process(u8 key_return_number)
{
//        buzz_run(key_return_number) ;
//  u8 i = 0 ;         
        switch(key_return_number)
        {
                case key1 :
                        set_timer(20 , 20 , led_on , led_off) ;
                        break ;
               
                case key2 :
                        set_timer(60 , 60 , led_on , led_off) ;
                        break ;
               
                case key3 :
                        set_timer(200 , 200  , led_on , led_off) ;
                        break ;
               
                case key4 :
                        set_timer(1000 , 1000  , led_on , led_off) ;
                        break ;
               
                case key5 :
                        set_timer(2000 , 2000  , led_on , led_off) ;
                        break ;
               
                case key6 :
                        set_timer(3000 , 3000  , led_on , led_off) ;
                        break ;
               
                case key7 :
                        set_timer(4000 , 4000  , led_on , led_off) ;
                        break ;
               
                case key8 :
                        set_timer(5000 , 5000  , led_on , led_off) ;
                        break ;
               
                case key9 :
                        set_timer(6000 , 6000  , buzz_on , buzz_off) ;
                        break ;
        }
}

/*****************************************
*****************************************/
void timer0_init(void)  //定时器0初始化
{
        TMOD = 0x01 ;
        TH0 = 0xfc ;  //1ms
        TL0 = 0x66 ;
        
        ET0 = 1 ;
        EA = 1 ;
        
        TR0 = 1 ;
}
/*****************************************
*****************************************/
void main()
{
        P31 = 1 ;
        gpio_init() ;
        timer0_init() ;
        adc_init() ;
        buzz = 0 ;
        
//        while(1)
//                set_timer(6000 , 500 , led_on , led_off) ;
        
        while(1)
        {        
                key_process(aaa) ;
        }        
}
/*****************************************
*****************************************/
void timer0_interrupt(void) interrupt 1  //定时器0中断函数,1ms中断
{
        static u16 tt = 0 ;
        
        TH0 = 0xfc ;
        TL0 = 0x66 ;
        
        tt++ ;
        soft_timer_counter++ ;
        if(tt == 10) //20ms进行一次扫描
        {
                tt = 0 ;
                flag__key_scan = 1 ;
                aaa = key_scan() ;
        }        
        if(soft_timer_counter == (led_on_time+led_off_time)) //3、(led_on_time+led_off_time)是整个中断周期的时间,led_off_time在这里才现身
                soft_timer_counter = 0 ;         //清0        
        if(soft_timer_counter < led_on_time)  //1、这两个if最为重要,若是小于,则置位flag1
                flag1 = 1 ;         
        else        //2、否则,置位flag2,通过if和else组合,将一段时间一分为2,控制LED亮灭时间//注意,在此并未设置熄灭LED的时间长度,而是通过后面的led_off_time来控制
                flag2 = 1 ;
}

使用特权

评论回复
板凳
chen915|  楼主 | 2020-8-28 17:13 | 只看该作者

使用特权

评论回复
地板
chen915|  楼主 | 2020-8-28 17:13 | 只看该作者

使用特权

评论回复
5
chen915|  楼主 | 2020-8-29 10:18 | 只看该作者
本帖最后由 chen915 于 2020-8-31 17:06 编辑
void key_process(u8 key_return_number)
{   
        switch(key_return_number)
        {
                case key1 :
                        set_timer(20 , 20 , led_on , led_off) ;
                        break ;
               
                case key2 :
                        set_timer(60 , 60 , led_on , led_off) ;
                        break ;
               
                case key3 :
                        set_timer(200 , 200  , led_on , led_off) ;
                        break ;
               
                case key4 :
                        set_timer(1000 , 1000  , led_on , led_off) ;
                        break ;
               
                case key5 :
                        set_timer(2000 , 2000  , led_on , led_off) ;
                        break ;
               
                case key6 :
                        set_timer(3000 , 3000  , led_on , led_off) ;
                        break ;
               
                case key7 :
                        set_timer(4000 , 4000  , led_on , led_off) ;
                        break ;
               
                case key8 :
                        set_timer(5000 , 5000  , led_on , led_off) ;
                        break ;
               
                case key9 :
                        set_timer(6000 , 6000  , buzz_on , buzz_off) ;
                        break ;
        }
}


这是按键处理函数。LED闪烁频率逐渐放慢。。。。。。程序是能跑起来。存在问题是,由高频向低频(比如先按key1再按key6)切换,切换得很快。但是反过来,比如先按key6再按key1,中间切换的时长40秒左右

使用特权

评论回复
6
xyz549040622| | 2020-8-29 20:51 | 只看该作者
感觉像是具体算法的问题,建议跟踪键值处理函数看看。

使用特权

评论回复
7
ayb_ice| | 2020-8-31 14:07 | 只看该作者
chen915 发表于 2020-8-29 10:18
这是按键处理函数。LED闪烁频率逐渐放慢。。。。。。程序是能跑起来。存在问题是,由高频向低频(比如先 ...

key_scan函数每次返回的不是个确切的值,这里逻辑混乱

set_timer这个函数的参数也混乱,这个函数只在有按键时调用,但传入的函数led_on , led_off运行又取决于flag1,flag2,这等于撞大运,撞到就执行,撞不到就不执行,直到下一次按键时再撞大运

使用特权

评论回复
8
chen915|  楼主 | 2020-8-31 17:08 | 只看该作者
xyz549040622 发表于 2020-8-29 20:51
感觉像是具体算法的问题,建议跟踪键值处理函数看看。

好的。多谢

使用特权

评论回复
9
chen915|  楼主 | 2020-8-31 17:14 | 只看该作者
ayb_ice 发表于 2020-8-31 14:07
key_scan函数每次返回的不是个确切的值,这里逻辑混乱

set_timer这个函数的参数也混乱,这个函数只在有 ...

会执行,就是间隔时间非常长

而且从短时到长时的切换比较即时,比如set_timer(20 , 20 , led_on , led_off) ; 切换到set_timer(4000 , 4000  , led_on , led_off) ; 就很即时

但是反过来,就是等半分钟后才执行
比如set_timer(4000 , 4000  , led_on , led_off) ; 切换为set_timer(20 , 20 , led_on , led_off) ;就非常耗时,但也还是能运行

使用特权

评论回复
10
ayb_ice| | 2020-8-31 17:15 | 只看该作者
chen915 发表于 2020-8-31 17:14
会执行,就是间隔时间非常长

而且从短时到长时的切换比较即时,比如set_timer(20 , 20 , led_on , led_o ...

函数的调用逻辑有问题

使用特权

评论回复
11
chen915|  楼主 | 2020-9-1 15:25 | 只看该作者
ayb_ice 发表于 2020-8-31 17:15
函数的调用逻辑有问题

弄了一天,搞不定,反而原本的思路都更乱了。请问该怎么做?想让按键按下,就让某个函数跑传入的时间段。就这样而已

使用特权

评论回复
12
ayb_ice| | 2020-9-1 15:31 | 只看该作者
chen915 发表于 2020-9-1 15:25
弄了一天,搞不定,反而原本的思路都更乱了。请问该怎么做?想让按键按下,就让某个函数跑传入的时间段。 ...

flag1 = 1 ; 改成开LED,
flag1 = 2 ; 改成关LED,
set_timer(6000 , 6000  , buzz_on , buzz_off) ; 改为set_timer(6000 , 6000) ; 不就可以了吗

u8 key_return ;改为 u8 key_return = 0;

使用特权

评论回复
13
chen915|  楼主 | 2020-9-1 16:18 | 只看该作者
ayb_ice 发表于 2020-9-1 15:31
flag1 = 1 ; 改成开LED,
flag1 = 2 ; 改成关LED,
set_timer(6000 , 6000  , buzz_on , buzz_off) ; 改 ...
#include "stc12c5630ad.h"

typedef unsigned char u8 ;
typedef unsigned int u16 ;

#define buzz                 P32
#define led                 P31
#define adc_key         P11
#define VCC                 5000

u8 aaa = 0 ;
u8 flag__key_scan ;
u8 key_number ;
u8 key_number_final ;
unsigned char flag1 , flag2 ;  //两个软定时标志位,前者为LED亮的时间段,后者为灭
unsigned int soft_timer_counter  , led_on_time , led_off_time ; //软定时自增变量,led亮时间,LED灭时间
typedef void (*VOID)(void) ;  //先定义函数指针
VOID funtion_run ;

//void buzz_on(void)
//{
//        buzz = 1 ;
//}

//void buzz_off(void)
//{
//        buzz = 0 ;
//}

void led_on(void)
{
        led = 0 ;
}

void led_off(void)
{
        led = 1 ;
}

void set_timer(u16 led_on_time_temp , u16 led_off_time_temp)
{        //3、第一个参数为LED点亮时长,第二位灭时长
        led_on_time = led_on_time_temp ;
        led_off_time = led_off_time_temp ;
}
/*******************************************************************************************************************************/
//P1M0 , P1M1 , ADC_CONTR=[ADC_POWER][SPEED1][SPEED0][ADC_FLAG]    [ADC_START][CHS2][CHS1][CHS0]
//ADC_DATA , ADC_LOW2,AUXR=[T0x12][T1x12][UART_M0x12][EADCI][ESPI][ELVDI][-][-],IE,IP,IPH
/*******************************************************************************************************************************/
#define adc_power_on (ADC_CONTR |= 0x80)
#define adc_power_off (ADC_CONTR &= 0x7f)

#define adc_flag_set (ADC_CONTR |= 0x10)
#define adc_flag_clear (ADC_CONTR &= 0xef)

#define adc_start_on (ADC_CONTR |= 0x08)
#define adc_start_off (ADC_CONTR &= 0xf7)

enum key_number  //键值枚举声明
{
        key1 = 1 , key2 ,
        key3 , key4 ,
        key5 , key6 ,
        key7 , key8 ,
        key9 , key10  //代表未按下
} ;

enum key_statues //按键状态枚举,分别为初始状态,按下状态,确认按下状态,松手状态
{
        key_statues0 = 0 , //初始态
        key_statues1 = 1 , //按下态
        key_statues2 ,     //确认按下态
        key_statues3 ,                 //松手态
} ;
/*****************************************
*****************************************/
void adc_init(void) //ADC初始化
{
        ADC_CONTR = 0x61 ;  //0110 0001 //关adc,270个周期转换一次,关标志位,关闭启动位,选择1通道
        adc_power_on ;         //重开adc
        adc_start_on ;         //开启转换
        adc_flag_clear ; //清adc转换标志位
}

u16 adc_result()  //获取ADC值
{
        u16 result = 0 ; //32bit数据装载10bit的adc转换结果值
        u16 value = 0  ;
        adc_init() ;         

        while(!(ADC_CONTR & 0x10)) ;  //& 0001 0000,若是完成转换,则bit5为1,与上0x10,仍为1,再取反为0,则跳过改行执行下一行
        result = ADC_DATA*4 + ADC_LOW2 ; //ADC_DATA寄存器为8bit,左移两位,再加上ADC_LOW2的值,即可得到转换后完整的10bit结果
        adc_flag_clear ; //清除ADC_FLAG标志位

        return result ;
}

u16 adc_hex2dec(float value) //16进制电压值转10进制,单位为mV毫伏
{
        float value_dec ;
        value_dec = (VCC * (value))/1024 ;        
        
        return (u16)value_dec ;
}

/*****************************************
*  00 准双向io口                01 推挽输出
*  10 高阻输入                  11 开漏
*****************************************/
void gpio_init()  //gpio初始化函数
{
        P1 = 0x02 ; //0000 0010
        P1M0 = 0x02 ; //0000 0010   
        P1M1 = 0x00 ; //0000 0000  设置按键为输入
        
        P3 = 0x06 ; //0000 0110
        P3M0 = 0x00 ; //0000 0000  
        P3M1 = 0x06 ; //0000 0110  设置蜂鸣器和LED为输出
}

/*****************************************
*****************************************/
u8 adc_key_value_process(u16 adc_value)  //通过adc值定义键值并返回..........该函数有问题,需要对adc电压值进行更好的处理
{
        u16 temp_adc_value = adc_value ; //中间变量
        temp_adc_value /= 100 ; //对100求模,若是需要更高精度,可改100为更小值
        
        switch (temp_adc_value) //temp_adc_value精度存在严重问题,建议再用一个switch语句判断键值,使电压值转化为0-10的数字
        {
                case 41 :         //按键1按下电压值为4100mV左右
                        return 1 ;    //返回1
                case 35 :
                        return 2 ;
                case 30 :
                        return 3 ;
                case 25 :
                        return 4 ;
                case 21 :
                        return 5 ;
                case 15 :
                        return 6 ;
                case 10 :
                        return 7 ;
                case 5 :
                        return 8 ;
                case 0 :
                        return 9 ;
               
                default :        //未按下,返回0
                        return 0 ;
        }
}
/*****************************************
*****************************************/
u8 key_scan(void) //状态机函数,返回状态机键值
{
                static u8 key_statues = key_statues0 ; //相当于锁,函数运行前与运行完,都要置0
                static u8 adc_key_number_temp ;
                u8 key_return = 0 ;        

                adc_key_number_temp = adc_key_value_process(adc_hex2dec(adc_result())) ;//采集adc,并转化为键值
                key_number = adc_key_number_temp ;
                switch(key_statues)
                {
                        case key_statues0 : //初始态,也相当于锁
                        {
                                if(0 != key_number) //若是有按键按下,则迁移至状态1------有按键按下时,key_number不会为0
                                {
                                        key_statues = key_statues1 ;
                                }
                        }
                        break ;
                        
                        case key_statues1 : //按下态
                        {
                                if(0 == key_number)        //如果只是抖动,则返回状态0
                                {
                                        key_statues = key_statues0 ;
                                }
                                
                                else
                                {
                                        key_statues = key_statues2 ;  //若是确实有按下,则迁移到状态2
                                        key_number_final = key_number ; //如果确实有按键按下,则保存先前的key_number值
                                }
                        }        
                        break ;
                        
                        case key_statues2 : //确认按下态,确认按下之后就应该判断是否松手,并进行消抖
                        {
                                if(0 == key_number)                //若已松手,迁移至状态3,相当于松手消抖
                                        key_statues = key_statues3 ;
                        }
                        break ;
                        
                        case key_statues3 : //松手态
                        {
                                if(0 == key_number) //确实已经松手
                                {        
                                        key_statues = key_statues0 ; //如果是确认无按键按下,则将状态迁移回状态0,即初始态。相当于自锁
                                        adc_key_number_temp = 0 ;
                                       
                                        switch (key_number_final)        //松手后键值有效
                                        {
                                                case 9 :
                                                        key_return = key9 ;
                                                        break ;
                                                
                                                case 8 :
                                                        key_return = key8 ;
                                                        break ;
                                                
                                                case 7 :
                                                        key_return = key7 ;
                                                        break ;
                                                
                                                case 6 :
                                                        key_return = key6 ;
                                                        break ;
                                                
                                                case 5 :
                                                        key_return = key5 ;
                                                        break ;
                                                
                                                case 4 :
                                                        key_return = key4 ;
                                                        break ;
                                                
                                                case 3 :
                                                        key_return = key3 ;
                                                        break ;
                                                
                                                case 2 :
                                                        key_return = key2 ;
                                                        break ;
                                                
                                                case 1 :
                                                        key_return = key1 ;
                                                        break ;
                                                
                                                case 0:
                                                        key_return = key10 ;
                                                        break ;
                                        }
                                }
                                else
                                {
                                        key_statues = key_statues2 ; //否则回到状态2,即再判断一次
                                }
                        }
                        break ;
                }
        
                return key_return ;
}

void key_process(u8 key_return_number)
{      
        switch(key_return_number)
        {
                case key1 :
//                        set_timer(20 , 20 , led_on , led_off) ;
                                                set_timer(20 , 20) ;
                        break ;
               
                case key2 :
//                        set_timer(60 , 60 , led_on , led_off) ;
                                                set_timer(60 , 60) ;
                        break ;
               
                case key3 :
//                        set_timer(200 , 200  , led_on , led_off) ;
                                        set_timer(200 , 200) ;
                        break ;
               
                case key4 :
//                        set_timer(1000 , 1000  , led_on , led_off) ;
                                                set_timer(1000 , 1000) ;
                        break ;
               
                case key5 :
//                        set_timer(2000 , 2000  , led_on , led_off) ;
                                                set_timer(2000 , 2000) ;
                        break ;
               
                case key6 :
//                        set_timer(3000 , 3000  , led_on , led_off) ;
                                                set_timer(3000 , 3000) ;
                        break ;
               
                case key7 :
//                        set_timer(4000 , 4000  , led_on , led_off) ;
                                                set_timer(4000 , 4000) ;
                        break ;
               
                case key8 :
//                        set_timer(5000 , 5000  , led_on , led_off) ;
                                                set_timer(5000 , 5000) ;
                        break ;
               
                case key9 :
//                        set_timer(6000 , 6000  , buzz_on , buzz_off) ;
                                                set_timer(6000 , 6000) ;
                        break ;
        }
}

/*****************************************
*****************************************/
void timer0_init(void)  //定时器0初始化
{
        TMOD = 0x01 ;
        TH0 = 0xfc ;  //1ms
        TL0 = 0x66 ;
        
        ET0 = 1 ;
        EA = 1 ;
        
        TR0 = 1 ;
}
/*****************************************
*****************************************/
void main()
{
        P31 = 1 ;
        gpio_init() ;
        timer0_init() ;
        adc_init() ;
        buzz = 0 ;

        while(1)
        {        
                key_process(aaa) ;
        }        
}
/*****************************************
*****************************************/
void timer0_interrupt(void) interrupt 1  //定时器0中断函数,1ms中断
{
        static u16 tt = 0 ;
        
        TH0 = 0xfc ;
        TL0 = 0x66 ;
        
        tt++ ;
        soft_timer_counter++ ;
        if(tt == 10) //10ms进行一次扫描
        {
                tt = 0 ;
                flag__key_scan = 1 ;
                aaa = key_scan() ;
        }        
        if(soft_timer_counter == (led_on_time+led_off_time))
                soft_timer_counter = 0 ;         //清0   
            if(soft_timer_counter < led_on_time)  
                {
                funtion_run = led_on ; //指针指向亮函数
                funtion_run() ;                  //并运行所指向的函数   
                }                       
        else        
        {
                                funtion_run = led_off ; //指针指向灭函数
                funtion_run() ;  //运行之
                }               

}


现在改成这样也一样,切换很耗时。按键处理感觉不存在问题啊

使用特权

评论回复
14
ayb_ice| | 2020-9-1 16:33 | 只看该作者
chen915 发表于 2020-9-1 16:18
现在改成这样也一样,切换很耗时。按键处理感觉不存在问题啊

这个地方改下
void timer0_interrupt(void) interrupt 1  //定时器0中断函数,1ms中断
{
        static u16 tt = 0 ;

        TH0 = 0xfc ;
        TL0 = 0x66 ;

        tt++ ;
        soft_timer_counter++ ;
        if(tt == 10) //10ms进行一次扫描
        {
                tt = 0 ;
                flag__key_scan = 1 ;
                aaa = key_scan() ;
        }        
        if(soft_timer_counter >= (led_on_time+led_off_time))
        {
                soft_timer_counter = 0 ;         //清0   
        }
        if(soft_timer_counter < led_on_time)  
        {
                funtion_run = led_on ; //指针指向亮函数
                funtion_run() ;                  //并运行所指向的函数   
        }                        
        else        
        {
                funtion_run = led_off ; //指针指向灭函数
                funtion_run() ;  //运行之
        }               

}

使用特权

评论回复
15
chen915|  楼主 | 2020-9-1 17:02 | 只看该作者
ayb_ice 发表于 2020-9-1 16:33
这个地方改下
void timer0_interrupt(void) interrupt 1  //定时器0中断函数,1ms中断
{

我也觉得是中断用两个变量tt和soft_timer_counter操作有问题,并且两者毫无关系,容易冲突。正在试

使用特权

评论回复
16
character| | 2020-9-2 08:25 | 只看该作者

使用特权

评论回复
17
chen915|  楼主 | 2020-9-3 11:20 | 只看该作者
chen915 发表于 2020-9-1 17:02
我也觉得是中断用两个变量tt和soft_timer_counter操作有问题,并且两者毫无关系,容易冲突。正在试 ...

还是不行。是不是状态机不好应用在adc按键上啊

使用特权

评论回复
18
ayb_ice| | 2020-9-3 11:31 | 只看该作者
chen915 发表于 2020-9-3 11:20
还是不行。是不是状态机不好应用在adc按键上啊

你这可能是按键扫描有问题,先屏蔽后测试下,一段时间后自动模拟下按键变化,测试下其它代码有问题吗

使用特权

评论回复
19
chen915|  楼主 | 2020-9-8 19:01 | 只看该作者
ayb_ice 发表于 2020-9-3 11:31
你这可能是按键扫描有问题,先屏蔽后测试下,一段时间后自动模拟下按键变化,测试下其它代码有问题吗 ...



还是不行,请问还有其他的方法消抖吗?

使用特权

评论回复
20
ayb_ice| | 2020-9-9 08:30 | 只看该作者
chen915 发表于 2020-9-8 19:01
还是不行,请问还有其他的方法消抖吗?

定时去读按键,相邻的两次有变化(不是按下就是松开)就可以了,按键对定时也不敏感10~100MS均可

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

50

帖子

0

粉丝