嵌入式学习日志————STM32之按键控制LED(一)

 前言

该学习日志是我在观看江科大的视频以后的总结归纳,如果有任何疑问都可以去哔哩哔哩看原视频来解答,欢迎大家提出问题或者建议。 

正文

一、GPIO基本知识

GPIO就是从芯片内部引出来一根功能复用的口线(电线)
功能复用是指:GPIO的引脚可以由CPU配置成不同的功能 
比如:输入功能 输出功能 模拟功能 复用功能等等

1.基本结构

e0ad5408ee9b4c1a85a2ca537ec2fc81.png

(1)所有的GPIO都是挂载在APB2外设总线上的。

(2)寄存器是32位的,但IO口只有16个,所以只有低16位有对应端口,高16位没有用到。只负责存储数据。

2.位结构

875bc9875c3043ceb59d6d8e2b6df6b0.png

  •  TTL施密特触发器:如果输入电压大于某一阀值,输出瞬间升为高电平;如果输入电压小于某一阀值,输出瞬间升为低电平(避免因信号波动造成输出抖动现象)。2162a929ecd24d3491236a9c281de22d.jpeg
  • MOS管:一种电子开关,信号来控制开关的导通和关闭,而开关负责IO口接到VDD或者VSS。
  • 3.GPIO的模式

    c1821929df4244d08265e59934b1bd37.png

     522ddfaf52fd4e40a534c1b01e90041f.png

  • 推挽输出模式:STM32对IO口有绝对的控制权,高低电平都有STM32决定。这种模式下,高低电平都有较强的驱动能力,所以,推挽输出又叫强推输出模式;
  • 开漏输出模式:P-MOS是无效的,只有N-MOS在工作。所以当数据寄存器为1时,下管断开了,相当于输出断开了——高阻模式;数据寄存器为0是则输出低电平。在多机通信的情况下,可以避免各个设备的相互干扰——————可作为通信协议的驱动方式,可以用于输出5V的点电平信号。f1ff3994091d40e2ae7402303603cd55.jpeg
  • 二、实验

    1.接线图1472cb867f2d4d85b8ff22f29b09ce10.jpeg

    注:该图源于江科大(接线采用低电平点亮方式——LED灯正极接VCC,负极接引脚)

    2.LED灯

    3a6b56c4b62c402db7c0637f24286517.png3.电路

    1)按键接法

    bc5ecc2a576a498eb70968f21b875717.png

    下接按键(常用)

  • 图一:按键按下,PA0口电压为低电平,按键松手PA0悬空,所以在此接法下要求PA0是上拉输入的模式。

  • 图二:按键按下,PA0口电压为低电平,按键松手PA0为高电平,所以此时,PA0可以是上拉输入或者浮空输入。

  • 上拉按键

  • 图三:按键按下,PA0口电压为高电平,按键松手PA0为低电平,所以此时,PA0可以是下拉输入或者浮空输入。

  • 图四: 按键按下,PA0口电压为高电平,按键松手PA0悬空,所以在此接法下要求PA0是下拉输入的模式。

  • 2)特别说明

    我所记录的这个实验采用的是下拉按键来实现控制LED灯的亮灭。所以在接下来的代码中,当读取到按键对应IO口电平为低电平时说明按键按下。

    4.原理说明

    利用读取按键对应端口的输入电平来控制LED灯的亮灭。按键按下与松开时对KeyNum赋不同的值,在通过对KeyNum值的判断,来设置LED灯对应端口的电平值,以此控制LED的亮灭。

    5.代码

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "LED.h"
    #include "Key.h"
    
    uint8_t KeyNum;
    
    int main(void)
    {
    	LED_Init();
    	Key_Init();
    	
    	while (1)
    	{
    		KeyNum = Key_GetNum();
    		if (KeyNum == 1)
    		{
    			LED1_Turn();
    		}
    		if (KeyNum == 2)
    		{
    			LED2_Turn();
    		}
    	}
    }
    

    2)led.c

    #include "stm32f10x.h"                  // Device header
    
    
    void LED_Init(void)
    {
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA的时钟
    	
    	/*GPIO初始化*/
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);				//将PA1和PA2引脚初始化为推挽输出
    	
    	/*设置GPIO初始化后的默认电平*/
    	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);				//设置PA1和PA2引脚为高电平
    }
    
    
    /*LED1亮*/
    void LED1_ON(void)
    {
    	GPIO_ResetBits(GPIOA, GPIO_Pin_1);		//设置PA1引脚为低电平
    }
    
    
    /*LED1灭*/
    void LED1_OFF(void)
    {
    	GPIO_SetBits(GPIOA, GPIO_Pin_1);		//设置PA1引脚为高电平
    }
    
    
    /*LED1状态翻转*/
    void LED1_Turn(void)
    {
    	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)	//判断此时LED的状态
    	{
    		GPIO_SetBits(GPIOA, GPIO_Pin_1);				
    	}
    	else												
    	{
    		GPIO_ResetBits(GPIOA, GPIO_Pin_1);				
    	}
    }
    
    
      /*LED2亮*/
    void LED2_ON(void)
    {
    	GPIO_ResetBits(GPIOA, GPIO_Pin_2);		//设置PA2引脚为低电平
    }
    
    
     /*LED2灭*/
    void LED2_OFF(void)
    {
    	GPIO_SetBits(GPIOA, GPIO_Pin_2);		//设置PA2引脚为高电平
    }
    
    
    
    /*LED2状态翻转*/
    void LED2_Turn(void)
    {
    	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)		
    	{                                                  
    		GPIO_SetBits(GPIOA, GPIO_Pin_2);               		
    	}                                                  
    	else                                               		
    	{                                                  
    		GPIO_ResetBits(GPIOA, GPIO_Pin_2);             		
    }
    

    3)key.c

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    
    void Key_Init(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStructure);
    }
    
    uint8_t Key_GetNum(void)
    {
    	uint8_t KeyNum = 0;
    	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) //判断按键是否按下
    	{
    		Delay_ms(20);    //消抖
    		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
    		Delay_ms(20);
    		KeyNum = 1;
    	}
    	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)
    	{
    		Delay_ms(20);
    		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);
    		Delay_ms(20);
    		KeyNum = 2;
    	}
    	
    	return KeyNum;
    }
    

     

    作者:sunflower_2024

    物联沃分享整理
    物联沃-IOTWORD物联网 » 嵌入式学习日志————STM32之按键控制LED(一)

    发表回复