OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32/FPGA开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...
查看: 1074|回复: 5

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

[复制链接]

40

主题

733

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
1846
金钱
1846
注册时间
2018-6-30
在线时间
353 小时
发表于 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()调用;
[C] 纯文本查看 复制代码
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;  
        }

2)KEY0控制单击、双击、长按和串口控制灯,每10ms执行一次
这里需要用一个if ( time_10_ms) 每10ms执行一次来判断检测按键用的
既可以通过按键来控制也可以通过串口来控制
[C] 纯文本查看 复制代码
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;                                                
                                                }
                                }        
  

3)KEY1中断按键,红灯5秒后自动熄灭
这个就需要通过定时器的配合来实现倒计时
[C] 纯文本查看 复制代码
           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 中断源 
        
}


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

ALIENTEK MINISTM32 实验2 按键实验.zip

3.51 MB, 下载次数: 8939

等阳光,等彩虹,等你!
回复

使用道具 举报

4

主题

192

帖子

0

精华

资深版主

Rank: 8Rank: 8

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

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

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

使用道具 举报

40

主题

733

帖子

3

精华

资深版主

Rank: 8Rank: 8

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

那你也得分享出来我看看哈
等阳光,等彩虹,等你!
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

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

使用道具 举报

15

主题

600

帖子

0

精华

高级会员

Rank: 4

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

使用道具 举报

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

本版积分规则




关闭

正点原子STM32/FPGA资料免费下载上一条 /1 下一条

正点原子公众号

QQ|联系我们|手机版|官方淘宝店|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2019-2-18 00:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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