【STM32基础学习】--GPIO原理

一.GPIO入门知识

全称:  general purpose intput outpot(通用输入输出端口)。

可以做输入也可以做输出。STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯,控制以及数据采集的功能。

二 .GPIO的八种工作模式

1.4种输入模式(可以读取端口的高低电平或者电压,用于读取按键输入,外接模块,电平信号输入,ADC电压采集,模拟通信协议接收数据(SPI,I2C))

输入浮空:可读取引脚电平,若引脚悬空,则电平不稳定。

输入上拉:可读取引脚电平,内部连接上拉电阻,悬空时默认高电平

输入下拉:可读取引脚电平,内部连接下拉电阻,悬空时默认低电平

模拟输入:GPIO无效,引脚直接接入内部ADC。

2.4种输出模式(带上下拉)--(可以控制端口输出高低电平,可用于驱动LED,控制蜂鸣器,模拟通信协议输出时序)

开漏输出:可输出引脚电平,高电平为高阻态,低电平接VSS

开漏复用输出:由片上外设控制,高电平为高阻态,低电平接VSS

推挽输出:可输出引脚电平,高电平接VDD,低电平接VSS

推挽复用输出:由片上外设控制,高电平接VDD,低电平接VSS

3.4种最大输出速度

2MHZ(低速)

25MHZ(高速)

50MHZ(快速)

100MHZ(高速)

4.上电复位后IO口的状态

上电复位后,GPIO默认为浮空状态,部分特殊功能引脚为特定状态。

复位后,调试引脚处于复用功能上拉/下拉状态。

PA15:JTDI处于上拉状态

PA14:JTCK/SWCLK处于下拉状态

PA13:JTMS/SWDAT处于下拉状态

PB4:NJTRS处于下拉状态

PB 3:JTDO处于浮空状态。

三. GPIO寄存器

每一组IO口都包含10个寄存器,

其中有4个32为配置寄存器

       模式寄存器 GPIOx_MODER

        00:输入模式(复位状态)      01:通用输出模式

        10:复用功能模式                     11:模拟模式

        输出类型寄存器GPIOx_OTYPER

        

        0:推挽输出(复位状态)     1:开漏输出

        输出速度寄存器GPIOx_OSPEEDR

        00:低速          01:中速

        10:快速          11:高速

       上拉下拉寄存器 GPIOx_PUPDR

        00:无上拉或者下拉          01:上拉

        10:下拉                            11:保留

2个32位的数据寄存器

        输入数据寄存器GPIOx_IDR

        1:高电平     0:低电平

        输出数据寄存器GPIOx_ODR

        1:高电平       0:低电平

1个32位置位/复位寄存器

        置位/复位寄存器GPIOx_BSRR

        控制输出的电平状态,

        低16位端口置位  1:高电平      0:不影响

        高16位端口复位  1:复位,输出0    0:不影响

1个32位的锁存寄存器

       配置锁存寄存器 GPIOx_LCKR

2个32位复用功能共寄存器

        复用功能寄存器(低位GPIOx_AFRL&高GPIO_AFRH)

四. 跑马灯实验

1.寄存器

led.h

#ifndef __LED_H_
#define __LED_H_

#include "sys.h"

//LED 端口定义
#define LED0 PBout(1)	// DS0
#define LED1 PBout(0)	// DS1	

void LED_Init(void);

#endif

led.c

#include "LED.h"

void LED_Init(void)
{    	 
	RCC->AHB1ENR|=1<<1;//使能PORTB时钟 
	GPIO_Set(GPIOB,PIN0|PIN1,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PB0,PB1设置
	LED0=1;//LED0关闭
	LED1=1;//LED1关闭
}

main

#include "sys.h" 
#include "usart.h" 
#include "delay.h" 
#include "LED.h"


int main(void)
{ 
	Stm32_Clock_Init(360,25,2,8);
	delay_init(180);
	LED_Init();
	while(1)
	{
		LED0=0;  //DS0亮
		LED1=1;  //DS1灭
		delay_ms(500);
		LED1=0;  //DS0灭
		LED0=1;  //DS1亮
		delay_ms(500);
	}
}

2.HAL库版本

led.h

#ifndef _LED_H
#define _LED_H
#include "sys.h"

#define LED0 PBout(1)   //LED0
#define LED1 PBout(0)   //LED1

void LED_Init(void);
#endif

led.c

#include "led.h"

//初始化PB1为输出.并使能时钟	    
//LED IO初始化
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOB_CLK_ENABLE();           //开启GPIOB时钟
	
    GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1,0
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);
	
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);	//PB0置1,默认初始化后灯灭
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);	//PB1置1,默认初始化后灯灭
}

main

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

 
int main(void)
{
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    LED_Init();                     //初始化LED  
    while(1)
    {
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); //LED0对应引脚PB1拉低,亮,等同于LED0(0)
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);   //LED1对应引脚PB0拉高,灭,等同于LED1(1)
        delay_ms(500);										//延时500ms
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);   //LED0对应引脚PB1拉高,灭,等同于LED0(1)
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //LED1对应引脚PB0拉低,亮,等同于LED1(0)
        delay_ms(500);                                      //延时500ms 
    }
}
 

五.按键控制LED

KEY.h

#ifndef _KEY_H
#define _KEY_H
#include "sys.h"

#define KEY0        HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3)  //KEY0按键PH3
#define KEY1        HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2)  //KEY1按键PH2
#define KEY2        HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2按键PC13
#define WK_UP       HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)  //WKUP按键PA0

#define KEY0_PRES 	    1
#define KEY1_PRES		2
#define KEY2_PRES		3
#define WKUP_PRES       4

void KEY_Init(void);
u8 KEY_Scan(u8 mode);
#endif

KEY.c

#include "key.h"
#include "delay.h"
							  
//

//按键初始化函数
void KEY_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();           //开启GPIOC时钟
    __HAL_RCC_GPIOH_CLK_ENABLE();           //开启GPIOH时钟
    
    GPIO_Initure.Pin=GPIO_PIN_0;            //PA0
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLDOWN;        //下拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_13;           //PC13
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
    HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}

//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,WKUP按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
u8 KEY_Scan(u8 mode)
{
    static u8 key_up=1;     //按键松开标志
    if(mode==1)key_up=1;    //支持连按
    if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
    {
        delay_ms(10);
        key_up=0;
        if(KEY0==0)       return KEY0_PRES;
        else if(KEY1==0)  return KEY1_PRES;
        else if(KEY2==0)  return KEY2_PRES;
        else if(WK_UP==1) return WKUP_PRES;          
    }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
    return 0;   //无按键按下
}

main

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"

{
    u8 key;
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();                     //初始化LED 
    KEY_Init();                     //初始化按键
	
    while(1)
    {
        key=KEY_Scan(0);            //按键扫描
				switch(key)
				{				 
					case  WKUP_PRES:	//控制LED0,LED1互斥点亮
								LED1=!LED1;
								LED0=!LED1;
								break;
					case  KEY2_PRES:	//控制LED0翻转
								LED0=!LED0;
								break;
					case  KEY1_PRES:	//控制LED1翻转	 
								LED1=!LED1;
								break;
					case  KEY0_PRES:	//同时控制LED0,LED1翻转 
								LED0=!LED0;
								LED1=!LED1;
								break;
			}
        delay_ms(10);
    }
}

  • 29
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值