OpenEdv-开源电子网

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

原子自带的程序,关于按键不支持连按的程序,我看了有些费劲,想了半天,写了个程序,也能运行得到想要的结果,求帮忙找bug

[复制链接]

8

主题

47

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2015-12-23
在线时间
63 小时
发表于 2016-1-4 21:36:16 | 显示全部楼层 |阅读模式
#include "sys.h"
#include "usart.h"               
#include "delay.h"
#include "stm32f10x.h"

int main()
{
        Stm32_Clock_Init(9);
        delay_init(72);
        uart_init(72,9600);
       
  RCC->APB2ENR|=1<<2|1<<4|1<<5;
       
  GPIOA->CRL&=0XFFFFFFF0;
  GPIOA->CRH&=0X0FFFFFF0;
  GPIOC->CRL&=0XFF0FFFFF;
  GPIOD->CRL&=0XFFFFF0FF;
  GPIOA->CRL|=0X00000008;
  GPIOA->CRH|=0X80000003;
  GPIOC->CRL|=0X00800000;
  GPIOD->CRL|=0X00000300;
  GPIOA->ODR|=1<<15;
  GPIOC->ODR|=1<<5;
  GPIOA->ODR|=1<<8;
  GPIOD->ODR|=1<<2;
       
while(1)
{        

    if(PAin(0)==1)
      {
         delay_ms(100);
         if(PAin(0)==1)
           {
                PAout(8)=~PAout(8);
                PDout(2)=~PDout(2);
                while(PAin(0)==1);
           }
      }
                               
    if(PAin(15)==0)
      {
         delay_ms(100);
         if(PAin(15)==0)
           {
                 PDout(2)=~PDout(2);
                 while(PAin(15)==0);
           }
       }

     if(PCin(5)==0)
      {
         delay_ms(100);
         if(PCin(5)==0)
         {
                PAout(8)=~PAout(8);
                while(PCin(5)==0);
         }
}
}       


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5781
金钱
5781
注册时间
2013-11-22
在线时间
1212 小时
发表于 2016-1-4 22:52:10 | 显示全部楼层
虽然可以用,但实用性并不强
回复 支持 1 反对 0

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-1-4 23:06:12 | 显示全部楼层
多测试下
回复 支持 反对

使用道具 举报

1

主题

84

帖子

0

精华

高级会员

Rank: 4

积分
529
金钱
529
注册时间
2015-7-21
在线时间
47 小时
发表于 2016-1-5 08:18:07 | 显示全部楼层
2楼说的对,能够实现功能是一回事,真正的实际运用又是一会事,特别是LZ程序中出现的while死等的语句,如果你的项目里不只是按键的话,还有其他操作,这样的死等会很降低效率,其实可以通过标志位和定时器查询结合的方法来实现连续按键的处理
一名合格的工程师一定要做到,代码虐我千百遍依然待她如初恋!
回复 支持 反对

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-1-5 08:31:52 | 显示全部楼层
还是原子哥的那个程序思路好一些,不会阻塞程序的运行。
回复 支持 反对

使用道具 举报

14

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
398
金钱
398
注册时间
2012-5-3
在线时间
80 小时
发表于 2016-1-5 08:43:57 | 显示全部楼层
这样的程序在工作中是不能用的。不然别人说你是新手。
回复 支持 反对

使用道具 举报

8

主题

47

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2015-12-23
在线时间
63 小时
 楼主| 发表于 2016-1-5 08:52:56 | 显示全部楼层
bs1234 发表于 2016-1-5 08:43
这样的程序在工作中是不能用的。不然别人说你是新手。

我确实是个新手
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1839
金钱
1839
注册时间
2014-6-27
在线时间
982 小时
发表于 2016-1-5 09:00:31 | 显示全部楼层

只要是你自己写的就好,学习总有个过程,多写多练多借鉴就会写得越来越好。
回复 支持 反对

使用道具 举报

8

主题

47

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2015-12-23
在线时间
63 小时
 楼主| 发表于 2016-1-5 09:39:29 | 显示全部楼层
#include "sys.h"
#include "usart.h"               
#include "delay.h"
#include "stm32f10x.h"

int main()
{  
        u8 flag=1;
        Stm32_Clock_Init(9);
        delay_init(72);
        uart_init(72,9600);
       
        RCC->APB2ENR|=1<<2|1<<4|1<<5;
       
        GPIOA->CRL&=0XFFFFFFF0;
  GPIOA->CRH&=0X0FFFFFF0;
  GPIOC->CRL&=0XFF0FFFFF;
  GPIOD->CRL&=0XFFFFF0FF;
  GPIOA->CRL|=0X00000008;
  GPIOA->CRH|=0X80000003;
  GPIOC->CRL|=0X00800000;
  GPIOD->CRL|=0X00000300;
  GPIOA->ODR|=1<<15;
  GPIOC->ODR|=1<<5;
        GPIOA->ODR|=1<<8;
        GPIOD->ODR|=1<<2;
       


while(1)
        {        
                if(PAin(0)==1&&flag)
                                {
                                                        delay_ms(20);
                                                        if(PAin(0)==1)
                                                        {
                                                                PAout(8)=~PAout(8);
                                                                PDout(2)=~PDout(2);
                                                                flag=0;
                                                        }
                                }
                               
                               
       
                if(PAin(15)==0&&flag)
                                {
                                                        delay_ms(20);
                                                        if(PAin(15)==0)
                                                         {
                                                                 PDout(2)=~PDout(2);
                                                                 flag=0;
                                                         }
                                 }

                                 
                 
                 if(PCin(5)==0&&flag)
                 {
                                                 delay_ms(20);
                                                 if(PCin(5)==0)
                                                 {
                                                                PAout(8)=~PAout(8);
                                                          flag=0;
                                                 }
                 }
                 
     if(PAin(0)==0&&PAin(15)==1&&PCin(5)==1) flag=1;
  }       
}
回复 支持 反对

使用道具 举报

14

主题

82

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
375
金钱
375
注册时间
2014-12-11
在线时间
64 小时
发表于 2016-1-5 09:51:21 | 显示全部楼层
[mw_shl_code=c,true]#include "key.h"
u8 key_current=0,key_old=0,key_down=0,key_press=0,key_up=0,key_change=0;

void KEY_Init(void)
{
        RCC->APB2ENR|=RCC_APB2ENR_IOPEEN|RCC_APB2ENR_IOPAEN;
        GPIOE->CRL&=~0XFFF00;
        GPIOE->CRL|=0x888<<8;
        GPIOE->ODR|=7<<2;
        GPIOA->CRL&=~0XF;
        GPIOA->CRL|=8;
        GPIOA->ODR&=~1;
}
void KEY_Scan(void)
{
        key_current=0;
        key_change=0;
        if(!KEY0)
                key_current|=1;
        if(!KEY1)
                key_current|=2;
        if(!KEY2)
                key_current|=4;
        if(WK_UP)
                key_current|=8;
        if(key_current==key_old)
        {
                key_press=key_current;
                key_down=0;
                key_up=0;
        }
        else
        {
                key_change=1;
                key_down=(~key_old)&(key_current^key_old);
                key_press=key_current&key_old;
                key_up=key_old&(key_current^key_old);
                key_old=key_current;
        }
       
}
[/mw_shl_code]
[mw_shl_code=c,true]#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#define KEY0 PEin(4)
#define KEY1 PEin(3)
#define KEY2 PEin(2)
#define WK_UP PAin(0)
#define KEY0_FILTER 1
#define KEY1_FILTER 2
#define KEY2_FILTER 4
#define WKUP_FILTER 8
extern u8 key_down,key_press,key_up,key_change;
void KEY_Init(void);
void KEY_Scan(void);
#endif
[/mw_shl_code]
回复 支持 反对

使用道具 举报

13

主题

225

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
289
金钱
289
注册时间
2013-11-12
在线时间
29 小时
发表于 2016-1-5 10:27:16 | 显示全部楼层
只能说完成了功能
回复 支持 反对

使用道具 举报

14

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
398
金钱
398
注册时间
2012-5-3
在线时间
80 小时
发表于 2016-1-5 21:25:34 | 显示全部楼层
按键要用状态机,不要用死延时,而是用定时方式扫描。
回复 支持 反对

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
发表于 2016-1-6 12:56:26 | 显示全部楼层
本帖最后由 solo 于 2016-1-6 12:58 编辑

[mw_shl_code=c,true]//按键处理函数
//返回按键值
//        UNDO = 0,//松开有效
//        PRESS,//按下有效
//        UNDO_CONT,//松开有效,且支持连按
//        PRESS_CONT//按下有效,且支持连按
u8 KEY_Scan(KEY_MODE mode)
{        
        static u8 key_up = 1;//按键标志,0:按下,1:松开
        static u8 key_cnt = 0;
        static u8 key_value = 0;
        static u8 fun_value = 0;

        vTaskDelay(5/portTICK_RATE_MS);//延时5ms
        
        if(key_up == 1)//检测状态,按键值清空
        {
                key_value = 0;//键值清空
        }
        
    if(KEY6 == 0)//以KEY6为基础的组合键
    {
        if(KEY1 == 0) {fun_value = 1;key_value = 7;goto END;}//返回值
        if(KEY2 == 0) {fun_value = 1;key_value = 8;goto END;}//返回值
        if(KEY3 == 0) {fun_value = 1;key_value = 9;goto END;}//返回值
        if(KEY4 == 0) {fun_value = 1;key_value = 10;goto END;}//返回值
    }
   
    if(KEY5 == 0)//以KEY5为基础的组合键
    {
        if(KEY1 == 0) {fun_value = 1;key_value = 11;goto END;}//返回值
    }
        
        if(mode == PRESS_CONT)//支持连按
        {
                if(key_cnt++ >= 50)
                {
                        key_up = 1;//每次立即返回,用于支持连按
                        key_cnt = 50;//超时计数
                }
        }
        else if(mode == UNDO_CONT)//支持连按
        {
                if(key_cnt++ >= 50)
                {
                        vTaskDelay(5/portTICK_RATE_MS);//去抖动
                        key_cnt = 50;//超时计数
                }
        }
        
        if(key_up && (KEY1==0 || KEY2==0 || KEY3==0 || KEY4==0 || KEY5==0 || KEY6==0))//按下
        {
                vTaskDelay(5/portTICK_RATE_MS);//去抖动,延时5ms
               
                if((mode == PRESS) || (mode == PRESS_CONT))//按下有效
                {
                        key_up = 0;
                        
                        if     (KEY1 == 0) return 1;
                        else if(KEY2 == 0) return 2;
                        else if(KEY3 == 0) return 3;
                        else if(KEY4 == 0) return 4;
//                        else if(KEY5 == 0) return 5;
                        else if((mode == PRESS) && (KEY5 == 0)) return 5;//返回键不支持连按
                        else if((mode == PRESS_CONT) && (KEY5 == 0)) key_value = 5;//连按状态只标记不返回,等待按键释放
                        else if((mode == PRESS) && (KEY6 == 0)) return 6;//返回键不支持连按
                        else if((mode == PRESS_CONT) && (KEY6 == 0)) key_value = 6;//连按状态只标记不返回,等待按键释放
                }
                else if((mode == UNDO) || (mode == UNDO_CONT))//释放有效
                {
                        key_up = 0;

                        if     (KEY1 == 0) key_value = 1;
                        else if(KEY2 == 0) key_value = 2;
                        else if(KEY3 == 0) key_value = 3;
                        else if(KEY4 == 0) key_value = 4;
                        else if(KEY5 == 0) key_value = 5;
                        else if(KEY6 == 0) key_value = 6;
                }                        
        }
        else if((KEY1 == 1) && (KEY2 == 1) && (KEY3 == 1) && (KEY4 == 1) && (KEY5 == 1) && (KEY6 == 1))//松开
        {
                if(fun_value == 1)//当使用的是组合键时,松开后功能键的操作无效
                {
                        fun_value = 0;
                        key_up = 1;
                        return 0;
                }

                key_up = 1;
                key_cnt = 0;

                return key_value;
        }
        else if((mode == UNDO_CONT) && (key_cnt >= 50))//松开有效,支持连按
        {
                if((key_value != 5) && (key_value != 6))//确认键、返回键不支持连按
                {
                        return key_value;
                }
        }
        
        while(0)//只有组合键才能执行
        {
                END:
                vTaskDelay(100/portTICK_RATE_MS);//因为是按下有效且立即返回,延时需要大一些
                key_up = 1;
                return key_value;
        }
        
        return 0;// 无按键按下
}[/mw_shl_code]

支持单按和连按,支持松开有效和按下有效,也支持组合键。参照原子哥的程序,可以继续优化。。。
回复 支持 反对

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-1-6 13:55:25 | 显示全部楼层
你大几的?
回复 支持 反对

使用道具 举报

8

主题

47

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2015-12-23
在线时间
63 小时
 楼主| 发表于 2016-1-6 15:14:58 | 显示全部楼层

啥事??
回复 支持 反对

使用道具 举报

48

主题

537

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
1369
金钱
1369
注册时间
2014-2-13
在线时间
169 小时
发表于 2016-1-7 15:22:36 | 显示全部楼层
本帖最后由 solo 于 2016-3-7 15:49 编辑
bug版本删了吧
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-22 04:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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