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

按键消抖

[复制链接]
在路上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个回答
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:03:34
wdshuang09 发表于 2016-11-1 22:09
Delay(0xfffff);让系统一直在这等待,不明智的选择,

刚入门,还没接触STM32的定时器,只玩过51的,所以我只能先写个延时的,等学到那个地方,再回来改进
在路上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的定时器
123下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

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