你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

按键消抖

[复制链接]
在路上11111111 发布时间:2016-11-1 19:32
  1. #include "stdio.h"
  2. #define _IO volatile
  3. typedef unsigned int uint32_t;
  4. typedef _IO uint32_t vu32;
  5. typedef unsigned short int uint16_t;
  6. #define GPIO_Pin_0         ((uint16_t)0x0001)
  7. #define GPIO_Pin_1         ((uint16_t)0x0002)
  8. #define GPIO_Pin_2         ((uint16_t)0x0004)
  9. #define GPIO_Pin_3         ((uint16_t)0x0008)
  10. #define GPIO_Pin_4         ((uint16_t)0x0010)
  11. #define GPIO_Pin_5         ((uint16_t)0x0020)
  12. #define GPIO_Pin_6         ((uint16_t)0x0040)
  13. #define GPIO_Pin_7         ((uint16_t)0x0080)
  14. #define GPIO_Pin_8         ((uint16_t)0x0100)
  15. #define GPIO_Pin_9         ((uint16_t)0x0200)
  16. #define GPIO_Pin_10        ((uint16_t)0x0400)
  17. #define GPIO_Pin_11        ((uint16_t)0x0800)
  18. #define GPIO_Pin_12        ((uint16_t)0x1000)
  19. #define GPIO_Pin_13        ((uint16_t)0x2000)
  20. #define GPIO_Pin_14        ((uint16_t)0x4000)
  21. #define GPIO_Pin_15        ((uint16_t)0x8000)
  22. #define GPIO_Pin_All       ((uint16_t)0xFFFF)


  23. #define   RCC_APB2Periph_AFIO      ((uint32_t)0x00000001)
  24. #define   RCC_APB2Periph_GPIOA     ((uint32_t)0x00000004)
  25. #define   RCC_APB2Periph_GPIOB     ((uint32_t)0x00000008)
  26. #define   RCC_APB2Periph_GPIOC     ((uint32_t)0x00000010)
  27. #define   RCC_APB2Periph_GPIOD     ((uint32_t)0x00000020)

  28. #define LEDON    (GPIOD->BRR = GPIO_Pin_2)
  29. #define LEDOFF   (GPIOD->BSRR = GPIO_Pin_2)


  30. #define BITBAND(addr,bitnum)  ((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF)<<5)+ (bitnum<<2))
  31. /*******这个的公式是FLASH的话,   0X4200 0000 + ((add-0x4000 0000)*8+n)*4;
  32.         其中add是你要绑定的寄存器的地址,n是你要绑定的寄存器的位,
  33.                 现在将其变成这种形式((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF)<<5 + (bitnum)<<2))
  34.                 :addr & 0xF000 0000是将其保留最高的思位比如说addr地址是0x4201 8000那么他现在是0x4000 0000
  35.                 +0x2000000变成了0x4200 0000;(addr-0x4000 0000)这其实就是保留它的后7位(在这里的改变的寄存器的地址都是
  36.                 0x4001 0000的那么就是说进一步保存的是后五位)(这里注意一点,0x2200_0000这个地址每增加1,实际上就是增加
  37.                 8个bit(一个地址对应一个字节),实际寄存器中的1个bit对应32个bit,所以就乘以4,地址本身增加1是8bit,
  38.                 8bit乘以4倍刚好是32bit。)那么现在(addr &0XFFFFF)其实就是保留后五位,<<5就是*32(2^5),<<2就是*4(2^2);
  39.                 将((A-0x4000 0000)(这个就是addr &0xFFFFF)*8+n)*4拆开就是(addr & 0XFFFFF)<<5 +(bitnum)<<2了
  40. **********/
  41. #define MEM_ADDR(addr)   *((volatile unsigned  long *)(addr))
  42. #define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr, bitnum))
  43. #define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)
  44. #define KEY1   PCin(4)

  45. typedef struct
  46. {
  47.     _IO uint32_t   CRL;
  48.         _IO uint32_t   CRH;
  49.         _IO uint32_t   IDR;
  50.         _IO uint32_t   ODR;
  51.         _IO uint32_t   BSRR;
  52.         _IO uint32_t   BRR;
  53.         _IO uint32_t   LCKR;
  54. }GPIO_TypeDef;


  55. typedef struct
  56. {
  57.     _IO uint32_t  ACR;
  58.         _IO uint32_t  KEYR;
  59.         _IO uint32_t  OPTKEYR;
  60.         _IO uint32_t  SR;
  61.         _IO uint32_t  CR;
  62.         _IO uint32_t  AR;
  63.         _IO uint32_t  OBR;
  64.         _IO uint32_t  WRPR;
  65. }FLASH_TypeDef;



  66. /************GPIOD管脚的内存对应地址********/
  67. #define PERIPH_BASE          ((uint32_t)0x40000000)
  68. #define APB2PERIPH_BASE      (PERIPH_BASE + 0x10000)
  69. #define GPIOD_BASE           (APB2PERIPH_BASE + 0x1400)
  70. #define GPIOD                     ((GPIO_TypeDef *)GPIOD_BASE)


  71. //#define PERIPH_BASE          ((uint32_t) 0x40000000)
  72. //#define APB2PERIPH_BASE      (PERIPH_BASE + 0x10000)
  73. #define GPIOC_BASE           (APB2PERIPH_BASE + 0x1000)
  74. #define GPIOC                ((GPIO_TypeDef *)GPIOC_BASE)
  75. #define GPIOC_IDR_Addr       (GPIOC_BASE+8)


  76. #define FLASH_BASE           ((uint32_t)0x40022000)
  77. #define FLASH                ((FLASH_TypeDef *)FLASH_BASE)
  78. typedef struct
  79. {
  80.    _IO uint32_t CR;
  81.    _IO uint32_t CFGR;
  82.    _IO uint32_t CIR;
  83.    _IO uint32_t APB2RSTR;
  84.    _IO uint32_t APB1RSTR;
  85.    _IO uint32_t AHBENR;
  86.    _IO uint32_t APB2ENR;
  87.    _IO uint32_t APB1ENR;
  88.    _IO uint32_t BDCR;
  89.    _IO uint32_t CSR;
  90.    _IO uint32_t AHBRSTR;
  91.    _IO uint32_t CFGR2;
  92. }RCC_TypeDef;


  93. /****************RCC时钟************/
  94. #define AHBPERIPH_BASE     (PERIPH_BASE         + 0x20000)
  95. #define RCC_BASE           (AHBPERIPH_BASE + 0x1000)
  96. #define RCC                ((RCC_TypeDef *)RCC_BASE)
  97. void RCC_init(void)
  98. {
  99.            RCC->CR|=1<<16;
  100.         while(!(RCC->CR>>17));
  101.         RCC->CFGR2|=4<<4;
  102.         RCC->CFGR2|=6<<8;
  103.         RCC->CFGR2|=1<<16;
  104.         RCC->CR|=1<<26;
  105.         while(!(RCC->CR>>27));
  106.         RCC->CFGR2|=1<<2;
  107.         RCC->CFGR|=1<<16;
  108.         RCC->CFGR|=7<<18;
  109.         FLASH->ACR|=0x32;
  110.         RCC->CR|=1<<24;
  111.         while(!(RCC->CR>>25));
  112.         //FLASH->ACR|=0x32;//
  113.         RCC->CFGR|=1<<1;
  114. }


  115. void LED_init()
  116. {
  117.    RCC->APB2ENR|=RCC_APB2Periph_GPIOD;
  118.    GPIOD->CRL&=0xFFFFF0FF;
  119.    GPIOD->CRL|=0x00000300;
  120. }
  121. void Delay(vu32 nCount)
  122. {
  123.    for(;nCount!=0;nCount--);
  124. }
  125. void Key_init()
  126. {
  127.     RCC->APB2ENR|=RCC_APB2Periph_GPIOC;//如果你写成RCC->APB2ENR=RCC_APB2Periph_GPIOC;
  128.         //就不行了,因为这样的话RCC的时钟只为GPIOC打开了,
  129.         GPIOC->CRL&=0xFFF0FFFF;
  130.         GPIOC->CRL|=0x00080000;
  131. }
  132. int main(void)
  133. {
  134.   
  135.   unsigned int key_up=1,flag;
  136.   RCC_init();
  137.   LED_init();
  138.   Key_init();
  139.   while(1)
  140.   {
  141.       if(key_up)
  142.             LEDON;
  143.           else
  144.             LEDOFF;
  145.           /************键盘消抖**********
  146.           这里,因为键盘按下的时候,会有一段波动,不稳定.所以在这里,我们需要消抖
  147.           首先,我们的按键是按下的时候是0,所以进来一个while()循环(主要是stm32的运转速率太快了)
  148.           然后在里面我们进行延时等待,为了防止按一下按键stm32跑了很多次的情况,我们设置一个标志flag
  149.           ,只让他按一下不论多长时间,LED只亮一次。*/
  150.           while(KEY1==0)//键盘消抖
  151.           {
  152.                Delay(0xfffff);
  153.                    flag++;
  154.                    if(flag==1)
  155.                    {
  156.                        key_up=!key_up;
  157.                    }
  158.           }
  159.           flag=0;
  160.   }
  161. }

  162.        
复制代码
这里有一些关于位绑定的知识大家可以去看看。http://blog.sina.com.cn/s/articlelist_1989261580_0_1.html

评分

参与人数 1 ST金币 +10 收起 理由
zero99 + 10

查看全部评分

收藏 2 评论23 发布时间:2016-11-1 19:32

举报

23个回答
在路上11111111 回答时间:2016-11-2 13:03:34
wdshuang09 发表于 2016-11-1 22:09
Delay(0xfffff);让系统一直在这等待,不明智的选择,

刚入门,还没接触STM32的定时器,只玩过51的,所以我只能先写个延时的,等学到那个地方,再回来改进
wdshuang09 回答时间:2016-11-2 19:34:44
在路上11111111 发表于 2016-11-2 13:03
刚入门,还没接触STM32的定时器,只玩过51的,所以我只能先写个延时的,等学到那个地方,再回来改进 ...

用定时器做,定期采样,
在路上11111111 回答时间:2016-11-2 13:06:27
高二毛 发表于 2016-11-2 08:39
不能这样去抖动的。楼上几位说的很好,不能这样阻塞掉。应该用中断处理。 ...

还没接触STM32的定时器,所以才采用了这个
wdshuang09 回答时间:2016-11-1 22:09:25
Delay(0xfffff);让系统一直在这等待,不明智的选择,
peter001 回答时间:2016-11-2 00:20:04
其实不需要这么复杂,利用系统毫秒滴答,定期采样即可,很稳定
zengyi703-16313 回答时间:2016-11-2 08:03:17
谢楼主分享
黑皮男 回答时间:2016-11-2 08:08:20
peter001 发表于 2016-11-2 00:20
其实不需要这么复杂,利用系统毫秒滴答,定期采样即可,很稳定

赞同,定期采样,程序不会阻塞,效率高
高二毛 回答时间:2016-11-2 08:39:48
不能这样去抖动的。楼上几位说的很好,不能这样阻塞掉。应该用中断处理。
anobodykey 回答时间:2016-11-2 09:47:24
在路上11111111 回答时间:2016-11-2 13:05:30
peter001 发表于 2016-11-2 00:20
其实不需要这么复杂,利用系统毫秒滴答,定期采样即可,很稳定

定时器吗
在路上11111111 回答时间:2016-11-2 13:05:54
黑皮男 发表于 2016-11-2 08:08
赞同,定期采样,程序不会阻塞,效率高

还没接触STM32的定时器
加拿大 回答时间:2016-11-2 15:44:29
放在中断函数定时几十毫秒扫描按键即可,不要延时
zbber 回答时间:2016-11-2 17:44:26
不能这样去抖动的
在路上11111111 回答时间:2016-11-2 19:41:47
好的,先记下了
12下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版