OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6095|回复: 7

[miniF103] 分享:mini板串口、中断、定时器、按键做一个实验升级

[复制链接]

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
发表于 2018-7-12 20:46:52 | 显示全部楼层 |阅读模式
本帖最后由 1208 于 2019-1-21 20:21 编辑

分享一个mini板按键KEY0单击、双击、长按和串口实现灯的控制状态,按键KEY1中断,控制灯亮5秒后熄灭
本实验实现的功能mini板按键KEY0单击、双击、长按和串口实现灯的控制状态,
按键KEY1中断,控制灯亮5秒后熄灭
且通过按键KEY0单击亮红灯、双击亮绿灯、长按两灯都熄灭来实现灯的
1)首先说到按键KEY0单击、双击、长按,这个需要了解按键所处的状态
如单击完后,超过多长时间属于长按,以及双击间隔的时间多长
还有TIM3_Int_Init(99,7199);//10ms,按键扫描计时10ms
这个很关键,超过这个10ms会导致按键单击、双击、长按的失灵
下面这段程序可以通过key = key_read()调用;
[mw_shl_code=c,true]unsigned char key_driver(void)
{
    static unsigned char key_state = key_state_0, key_time = 0;
    unsigned char key_press, key_return = N_key;

    key_press = KEY0;                    // 读按键IO电平

    switch (key_state)
    {
      case key_state_0:                              // 按键初始态
        if (!key_press) key_state = key_state_1;      // 键被按下,状态转换到按键消抖和确认状态
        break;
      
      case key_state_1:                      // 按键消抖和确认状态
        if (!key_press)                      //按键仍然处于按下
        {
             key_time = 0;                     
             key_state = key_state_2;   //,消抖完成,状态转换到按下键时间的计时
        }
        else
             key_state = key_state_0;   //按键已抬起,转换到按键初始态。此处完成和实现软件消抖,此时
        break;                          //按键的按下和释放都在此消抖
      
      case key_state_2:
        if(key_press)
        {
             key_return = S_key;        // 此时按键的释放,说明是产生一次短操作,回送S_key
             key_state = key_state_0;   // 转换到按键的初始态
        }
        else if (++key_time >= 100)     // 继续按下,计时10ms
        {
             key_return = L_key;        // 按下时间>1000ms,此按键为长按操作,返回长按操作
             key_state = key_state_3;   // 转换到等待按键释放状态
        }
        break;

      case key_state_3:                 // 等待按键释放状态,此状态只返回无按键事件
        if (key_press) key_state = key_state_0; //按键已释放,已转换到按键初始态
        break;
    }
    return key_return;
}

/*=============

时间10ms
===============*/
unsigned char key_read(void)
{
          static unsigned char key_m = key_state_0, key_time_1 = 0;
    unsigned char key_return = N_key,key_temp;
    key_temp = key_driver();
     
    switch(key_m)
    {
        case key_state_0:
            if (key_temp == S_key )
            {
                 key_time_1 = 0;               // 第一次单击,不返回,到下个转态判断后面是否出现双击
                 key_m = key_state_1;
            }
            else
                 key_return = key_temp;        // 对于无键、长按,返回原事件
            break;

        case key_state_1:
            if (key_temp == S_key)             // 又一次单击(间隔时间<500ms)
            {
                 key_return = D_key;           // 返回双击键事件,回初始状态
                 key_m = key_state_0;
            }
            else                                
            {                                  // 这里500ms内肯定读到的都是无键事件,
                 if(++key_time_1 >= 50)        //因为长按>1000ms,低层返回都是无按键
                 {
                      key_return = S_key;      // 500ms内没有再次出现单键事件,返回上一次的单键
                      key_m = key_state_0;     // 返回初始状态
                 }
             }
             break;
    }
    return key_return;  
        }[/mw_shl_code]
2)KEY0控制单击、双击、长按和串口控制灯,每10ms执行一次
这里需要用一个if ( time_10_ms) 每10ms执行一次来判断检测按键用的
既可以通过按键来控制也可以通过串口来控制
[mw_shl_code=c,true]if ( time_10_ms)               //每10ms执行一次
                                {
                                        time_10_ms = 0 ;
                                        key = key_read();     
                                        if (key == S_key||USART_RX_BUF[0]=='0')
                                                {        
                                                        
                                                        LED0=0;                                                        
                                                        printf("LED0亮\n");        
                                                         delay_ms(1000);
                                                        USART_RX_BUF[0]=9;
                                                }                                                        
                                       else if(key == D_key||USART_RX_BUF[0]=='1')  
                                                {
                                                        LED1=0;
                                                        printf("LED1亮\n");
                                                        delay_ms(1000);
                                                        USART_RX_BUF[0]=9;
                                                }
                                       else if(key == L_key||USART_RX_BUF[0]=='2')
                                                {
                                                         LED0=1;
                                                         LED1=1;
                                                         printf("LED0和LED1都灭\n");        
                                                         delay_ms(1000);        
                                                         USART_RX_BUF[0]=9;                                                
                                                }
                                }        [/mw_shl_code]  

3)KEY1中断按键,红灯5秒后自动熄灭
这个就需要通过定时器的配合来实现倒计时
[mw_shl_code=c,true]           if(key1Pressed)              
                {
                     LED0 = 0 ;
                }
                if(count > 500)            
                    {
                         LED0 = 1 ;
                         count = 0 ;
                         key1Pressed = 0 ;
                    }

extern int key1Pressed ;
extern int count ;
extern int time_10_ms;
void TIM3_IRQHandler(void)   //TIM3中断
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
             time_10_ms = 1;
             if (LED0 == 0 && key1Pressed == 1 )     
             count++ ;
        }
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
        
}

[/mw_shl_code]
4)volatile int time_10_ms = 0 ;   //volatile提醒编译器它后面定义的变量随时有可能改变
volatile int count = 0 ;        //每次存储或读取变量,直接从变量地址中读取数据
volatile int key1Pressed = 0 ;
希望对初学者有所帮助,也向大神请教一下不足之处,喜欢就顶一个!

ALIENTEK MINISTM32 实验2 按键实验.zip

3.51 MB, 下载次数: 9200

业精于勤荒于嬉;行成于思毁于随!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

2183

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
14287
金钱
14287
注册时间
2018-8-3
在线时间
1147 小时
发表于 2018-8-8 14:36:54 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2018-5-3
在线时间
10 小时
发表于 2019-1-14 18:58:59 | 显示全部楼层
多谢,利用你的例子,搞定了,按键延时灭制定灯的问题。
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-14 20:56:37 | 显示全部楼层
zhangjianhu 发表于 2019-1-14 18:58
多谢,利用你的例子,搞定了,按键延时灭制定灯的问题。

那你也得分享出来我看看哈
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2018-5-3
在线时间
10 小时
发表于 2019-1-15 15:25:41 | 显示全部楼层
就是你的那个,就是改了下硬件配置。
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2019-1-15 16:29:16 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

1

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2018-8-14
在线时间
26 小时
发表于 2019-8-25 22:32:46 | 显示全部楼层
你好,大神,用你的方法我想实现3个按键的短按,长按,双击吗?
回复 支持 反对

使用道具 举报

0

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2017-11-28
在线时间
22 小时
发表于 2019-12-15 07:59:40 | 显示全部楼层
谢谢 !点赞
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 22:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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