sunsili 发表于 2021-11-8 23:57:37

STM32F103RCT6开发板M3单片机教程04--按键检测

本帖最后由 sunsili 于 2023-12-11 21:33 编辑

STM32F103RCT6开发板M3单片机教程04--按键检测


原理图讲解
本教程使用是(光明谷SUN_STM32mini开发板)

首先了硬件连接原理,STM32F103RCT6开发板是mini最小系统板,板子在没并有按键。需要自行用面包板搭建。

硬件连接:

PC10 -> KEY1 (MCU内部上拉) --> GND   (低电平有效)

PC11 -> KEY2(MCU内部上拉) --> GMD    (低电平有效)

程序设计
有两种方法:

方法1、不断检测引脚(PC10, PC11)电平, 当检测到引脚(PC10, PC11)为低电平时,则有按键按下;
方法2、中断检测,设置引脚(PC10, PC11)下降沿触中断,在中断函数里,判断是哪个引脚发生的中断。

编写程序

现在我们用方法1,编写代码。下集我们用中断方法。


[*]复制上节工程文件夹打开(这个方法比较方便)
[*]新建源文件key.c,添加key.c到BSP(Grounp),并编辑
/**********************************************************************************
* 文件名:key.c
* 描述    :按键扫描(系统滴答时钟SysTick实现扫描延时)
* 实验平台:Sun_STM32Min系统板
* 硬件连接:PC10 -> KEY1--> GND   
*             PC11 -> KEY2 --> GMD      
* 库版本:ST_v3.5

* Version    Date       Auther      Reversed History
----------------------------------------------------------------------------
V1.0.0    2021-11-07Lojam FanFisrt Created

* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com
**********************************************************************************/

#include "key.h"
#include "SysTick.h"

/*******************************************************************************
* 函数名: Key_GPIO_Config
* 描述    : KEY IO配置
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : KEY(1~2)的IO口分别是:PC10,PC11
*******************************************************************************/
void Key_GPIO_Config(void)
{
      GPIO_InitTypeDefGPIO_InitStructure;                              //定义一个GPIO_InitTypeDef类型的GPIO初始化结构体
      
      RCC_APB2PeriphClockCmd(KEY_RCC, ENABLE);                        //使能GPIOA的外设时钟      
      
      GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2;                        //选择要初始化的GPIOA引脚(PA15,PA14)
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                //设置引脚工作模式为上拉输入               
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //设置引脚输出最大速率为50MHz
      GPIO_Init(KEY_PORT, &GPIO_InitStructure);                        //调用库函数中的GPIO初始化函数,初始化GPIOA中的PA15,PA14引脚
}

/*******************************************************************************
* 函数名: Key_Detection
* 描述    : 按键按下检测
* 输入    : GPIOx:按键对应的GPIO,GPIO_Pin:对应按键端口
* 输出    : 无
* 返回    : KEY_DOWN(0):对应按键按下,KEY_UP(1):对应按键没按下
* 说明    : KEY(1~2)的IO口分别是:PC10,PC11
*******************************************************************************/
u8 Key_Down_Detection(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
{                        
      if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_DOWN)      //检测是否有按键按下
      {         
                Delay_nMs(10);      //延时消抖               
                if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_DOWN)      //检测是否有按键按下   
                {         
                        while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_DOWN);      //等待按键释放
                        return KEY_DOWN;         
                }
                else
                {
                        return KEY_UP;
                }
      }
      else
      {
                return KEY_UP;
      }
}

/*******************************************************************************
* 函数名: Key_Down_Scan
* 描述    : 按键按下扫描
* 输入    : 无
* 输出    : 0:没有按键按下,1:按键按下
* 返回    : 无
* 说明    : KEY(1~2)的IO口分别是:PC10,PC11
*******************************************************************************/
u8 Key_Down_Scan(void)
{
      u16 downflag=0;
      u8 value=0;

          downflag=GPIO_ReadInputData(KEY_PORT);
      if((downflag & 0x0c00) != 0x0c00)      //检测是否有按键按下
      {         
                Delay_nMs(10);      //延时消抖      
                downflag = GPIO_ReadInputData(KEY_PORT) & 0x0c00;      
                if(downflag != 0x0c00 )      //检测是否有按键按下   
                {         
                        if((downflag & 0x0400) == 0) value |= 0x01;
                        if((downflag & 0x0800) == 0) value |= 0x02;         
                }               
      }      

      return value;
}


/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
********************      END OF FILE key.c      *******************/

[*]新建源文件key.h,并编辑
/**********************************************************************************
* 文件名:led.c
* 描述    :led 应用函数库         
* 实验平台:Sun_STM32Min系统板
* 硬件连接:PA5 -> LED1    板子上没有 要用杜绑线外接
*             PA6 -> LED2   板子上没有 要用杜绑线外接
*             PA7 -> LED3   板子上没有 要用杜绑线外接
*             PA8 -> LED4   板子有直接观察
* GPIO置低电平亮LED

* 库版本:ST_v3.5

* Version    Date       Auther      Reversed History
----------------------------------------------------------------------------
V1.0.0    2021-11-07Lojam FanFisrt Created

* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com
**********************************************************************************/

#include "Led.h"
         
/*******************************************************************************
* 函数名: LED_GPIO_Config
* 描述    : LED IO配置
* 输入    : 无
* 输出    : 无
* 返回    : 无
* 说明    : LED(1~4)的IO口分别是:PB5,PB6,PB7,PB8
*******************************************************************************/
void LED_GPIO_Config(void)
{
      GPIO_InitTypeDefGPIO_InitStructure;                              //定义一个GPIO_InitTypeDef类型的GPIO初始化结构体
      
      RCC_APB2PeriphClockCmd(LED_RCC, ENABLE);                        //使能GPIOB的外设时钟      
      
      GPIO_InitStructure.GPIO_Pin = LED_ALL;                              //选择要初始化的GPIOB引脚(PB5,PB6,PB7,PB8)
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //设置引脚工作模式为通用推挽输出               
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //设置引脚输出最大速率为50MHz
      GPIO_Init(LED_PORT, &GPIO_InitStructure);                        //调用库函数中的GPIO初始化函数,初始化GPIOB中的PB5,PB6,PB7,PB8引脚

      LED_ALL_OFF();                                                                              //关闭ALL_LED                                          
}

/*点亮LED1.PA5*/
void LED1_ON(void)
{
      GPIO_ResetBits(LED_PORT,LED1);
}

/*关闭LED1.PA5*/
void LED1_OFF(void)
{
      GPIO_SetBits(LED_PORT,LED1);
}

/*点亮LED2.PA6*/
void LED2_ON(void)
{
      GPIO_ResetBits(LED_PORT,LED2);
}

/*关闭LED2.PA6*/
void LED2_OFF(void)
{
      GPIO_SetBits(LED_PORT,LED2);
}

/*点亮LED3.PA7*/
void LED3_ON(void)   
{
      GPIO_ResetBits(LED_PORT,LED3);
}

/*关闭LED3.PA7*/
void LED3_OFF(void)
{
      GPIO_SetBits(LED_PORT,LED3);
}

/*点亮LED4.PA8*/
void LED4_ON(void)
{
      GPIO_ResetBits(LED_PORT,LED4);
}

/*关闭LED4.PA8*/
void LED4_OFF(void)
{
      GPIO_SetBits(LED_PORT,LED4);
}

/*点亮ALL_LED*/
void LED_ALL_ON(void)
{
      GPIO_ResetBits(LED_PORT,LED_ALL);
}
/*关闭ALL_LED*/
void LED_ALL_OFF(void)
{
      GPIO_SetBits(LED_PORT,LED_ALL);
}



/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
********************      END OF FILE led.c      *******************/
[*]编辑main.c
/**********************************************************************************
* Sun STM32 mini Demo

*   Description
   
    Uart Demo

   
* Version    Date       Auther      Reversed History
----------------------------------------------------------------------------
V1.0.0    2021-11-07Lojam FanFisrt Created

* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com

**********************************************************************************/

#include "stm32f10x.h"
#include "usart.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include <stdio.h>


extern vu8 Usart1_R_Buff;      //串口1数据接收缓冲区
extern vu8 Usart1_R_State;                                                //串口1接收状态
extern vu16 Usart1_R_Count;                                                //当前接收数据的字节数         


/*******************************************************************************
* 函数名: main
* 描述    : 主函数,用户程序从main函数开始运行
* 输入    : 无
* 输出    : 无
* 返回值: int:返回值为一个16位整形数
* 说明    : 无
*******************************************************************************/
int main(void)
{
    u8 keyVal;
    SysTick_Init_Config();
      USART1_Init_Config(115200);//USART1初始化配置
    LED_GPIO_Config();
    Key_GPIO_Config();
    printf ("*===================================================*\n");
    printf ("**Name: Sun STM32 mini Demo Code.    *************\n");
    printf ("** (C) Sunshine Silicon Corporation    *************\n");
    printf ("**Website: http://www.sunsili.com    *************\n");
    printf ("**   E-Mail : fan@sunsili.com          *************\n");
    printf ("*===================================================*\n");
    printf ("* Sun STM32 mini Key Demo code .*\n");
   
      while (1)
      {
      keyVal = Key_Down_Scan();
                if(Usart1_R_State == 1)//一帧数据接收完成
                {
                        USART1_SendData((u8 *)Usart1_R_Buff, Usart1_R_Count);   //USART1发送数据缓冲区数据(发送刚接收完成的一帧数据)
                        Usart1_R_State =0;
                        Usart1_R_Count =0;
                }
      if(keyVal)
      {
            printf("KeyVal:%d\r", keyVal);
            if(keyVal & 0x01) LED3_ON();            
            else if(keyVal & 0x02) LED4_ON();            
      }
      else LED_ALL_OFF();
      }
}



/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
********************      END OF FILE main.c      *******************/
[*]编译调试
   方法不再重复,经过前两节练习,大家应该是会了.
   连接串口打印,输出按键值。按下按键对应灯会亮。

工程源码
**** Hidden Message *****


h_K11t1 发表于 2024-1-24 13:59:01

1111111111111111
页: [1]
查看完整版本: STM32F103RCT6开发板M3单片机教程04--按键检测