[STM32F1] STM32F103ZET6【标准库函数开发】--按键输入

[复制链接]
715|4
 楼主| 王小琪 发表于 2020-11-4 20:09 | 显示全部楼层 |阅读模式
1.硬件电路如下
767845fa29922ee074.png    310585fa298e233bcf.png
如图,因为key0,key1,key2通过开关和GND连接在一起,所以对应的PE4,PE3,PE2要设置为上拉输入;同理,WK_UP通过开关和VCC3.3连接在一起,所以对应的PA0要设置为下拉输入。想要实现的功能就是通过按键控制led亮灭。


2.知识储备:STM32有四种输出模式和四种输入模式
70295fa2997649728.png

3.代码编写
3.1宏定义
  1. //宏定义
  2. #define KEY0    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0 GPIOE.4
  3. #define KEY1    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1 GPIOE.3
  4. #define KEY2    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)//读取按键2 GPIOE.2
  5. #define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP)   GPIOA.0

  6. #define KEY0_PRES         1        //KEY0按下
  7. #define KEY1_PRES        2        //KEY1按下
  8. #define KEY2_PRES        3        //KEY2按下
  9. #define WKUP_PRES   4        //KEY_UP按下(即WK_UP/KEY_UP)

  10. void KEY_Init(void);//IO初始化
  11. u8 KEY_Scan(u8);          //按键扫描函数                                            
  12. #endif
3.2定义子函数
  1. //按键初始化函数
  2. void KEY_Init(void) //IO初始化
  3. {
  4.         GPIO_InitTypeDef GPIO_InitStructure;
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
  6.        
  7.     //初始化KEY0,KEY1,KEY2--->PE4,PE3,PE2  上拉输入       
  8.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//选择引脚
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
  10.         GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

  11.         //初始化 WK_UP-->GPIOA.0          下拉输入
  12.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;//选择引脚
  13.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉          
  14.         GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
  15. }
  1. //按键处理函数
  2. //返回按键值
  3. //mode:0,不支持连续按;1,支持连续按;
  4. //0,没有任何按键按下
  5. //1,KEY0按下
  6. //2,KEY1按下
  7. //3,KEY2按下
  8. //4,KEY3按下 WK_UP
  9. //注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
  10. u8 KEY_Scan(u8 mode)
  11. {         
  12.         static u8 key_up=1;//按键按松开标志
  13.         if(mode)key_up=1;  //支持连按                  
  14.         if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
  15.         {
  16.                 delay_ms(10);//去抖动
  17.                 key_up=0;
  18.                 if(KEY0==0)return KEY0_PRES;
  19.                 else if(KEY1==0)return KEY1_PRES;
  20.                 else if(KEY2==0)return KEY2_PRES;
  21.                 else if(WK_UP==1)return WKUP_PRES;
  22.         }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;             
  23.         return 0;// 无按键按下
  24. }
3.3主函数
  1. //主函数
  2. int main(void)
  3. {
  4.         vu8 key=0;       
  5.         delay_init();                     //延时函数初始化          
  6.         LED_Init();                             //LED端口初始化
  7.         KEY_Init();                   //初始化与按键连接的硬件接口
  8.         while(1)
  9.         {
  10.                 key=KEY_Scan(0);        //得到键值
  11.                    if(key)
  12.                 {                                                  
  13.                         switch(key)
  14.                         {                                 
  15.                                 case WKUP_PRES:        //控制LED0翻转
  16.                                         LED0=!LED0;
  17.                                         break;
  18.                                 case KEY2_PRES:        //控制LED1翻转
  19.                                         LED1=!LED1;
  20.                                         break;
  21.                                 case KEY1_PRES:        //LED0,LED1点亮         
  22.                                         LED0=0;
  23.                                         LED1=0;
  24.                                         break;
  25.                                 case KEY0_PRES:        //LED0,LED熄灭
  26.                                         LED0=1;
  27.                                         LED1=1;
  28.                                         break;
  29.                         }
  30.                 }else delay_ms(10);
  31.         }         
  32. }
PS:1.按键处理函数是正点原子历程里面的,封装的极好,可以当作一个库,直接来调用
2.这个按键处理函数是有优先级的,KEY0>KEY1>KEY2>KEY3,也就是说假如同时按下KEY0,KEY1,KEY2,KEY3,执行的谁KEY0,因为在执行判断语句的时候,KEY0在最前面。
捉虫天师 发表于 2020-11-4 21:21 | 显示全部楼层
标准库挺好用的啊
 楼主| 王小琪 发表于 2020-11-4 21:25 | 显示全部楼层

见仁见智吧,熟练度起来了用寄存器/标准库/HAL库都好用,但熟练的这个过程很痛苦。
捉虫天师 发表于 2020-11-4 21:38 | 显示全部楼层
王小琪 发表于 2020-11-4 21:25
见仁见智吧,熟练度起来了用寄存器/标准库/HAL库都好用,但熟练的这个过程很痛苦。 ...

是的,听说最新的是LL库
 楼主| 王小琪 发表于 2020-11-4 21:42 | 显示全部楼层
捉虫天师 发表于 2020-11-4 21:38
是的,听说最新的是LL库

LL库没用过,我只用过标准库,最近在学习HAL库,因为可以用CUBEMX生成,而且新的片子都不支持标准库了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

232

主题

585

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部