STM32的普通GPIO配置和库说明

本文详细介绍了STM32的GPIO功能,包括GPIO的内部结构、寄存器配置、工作模式、速度设置以及标准外设库的接口函数。通过具体的IO输出和输入实例,展示了如何初始化GPIO、配置IO模式、读写数据以及处理中断。重点提到了PA15引脚的特殊处理和位带操作在IO控制中的应用。
摘要由CSDN通过智能技术生成

GPIO功能描述

  • GPIO内部结构框图

在这里插入图片描述

  • GPIO寄存器
typedef struct
{
  __IO uint32_t CRL;	//配置寄存器
  __IO uint32_t CRH;
    
  __IO uint32_t IDR;	//数据寄存器
  __IO uint32_t ODR;
    
  __IO uint32_t BSRR;	//置为/复位寄存器
    
  __IO uint32_t BRR;	//复位寄存器
    
  __IO uint32_t LCKR;	//锁定寄存器
} GPIO_TypeDef;
//每组GPIO端口(Px)都由7个寄存器组成,负责控制该端口的16个引脚Px0~Px15
  • GPIO工作模式
typedef enum
{ 
    //四种输入
    GPIO_Mode_AIN			= 0x00,					//模拟输入
    GPIO_Mode_IN_FLOATING 	= 0x04,					//浮空输入
    GPIO_Mode_IPD 			= 0x28,					//下拉输入
    GPIO_Mode_IPU 			= 0x48,					//上拉输入
    //四种输出
    GPIO_Mode_Out_OD 		= 0x14,					//开漏输出
    GPIO_Mode_Out_PP 		= 0x10,					//推挽输出
    GPIO_Mode_AF_OD 		= 0x1C,					//复用开漏输出
    GPIO_Mode_AF_PP			= 0x18,					//复用推挽输出
}GPIOMode_TypeDef;
  • ① 作为普通GPIO输入:
    根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对应的所有复用功能模块。
    ② 作为普通GPIO输出:
    根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模块。
    ③ 作为普通模拟输入:
    配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。(A/D模拟输入)
    ④ 作为内置外设的输入:
    根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应的某个复用功能模块。
    ⑤ 作为内置外设的输出:
    根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用功能模块

  • 配置速度

    typedef enum
    { 
      GPIO_Speed_10MHz 	= 1,
      GPIO_Speed_2MHz	= 2, 
      GPIO_Speed_50MHz	= 3,
    }GPIOSpeed_TypeDef;
    
  • GPIO标准外设库接口函数

    /***初始化以及复位函数***/
    //将GPIOx外设寄存器恢复为默认复位值
    void GPIO_DeInit(GPIO_TypeDef* GPIOx);
    //取消所有的复用功能
    void GPIO_AFIODeInit(void);
    //根据GPIO初始化结构参数初始化GPIOx外设寄存器
    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
    //GPIO结构体初始化
    void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
    
    /***引脚功能操作函数***/
    //读取选定的GPIO输入端口引脚数据
    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    //读取选定的GPIO输入端口数据
    uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
    //读取选定的GPIO的输出端口引脚数据
    uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    //读取选定的GPIO的输出端口数据
    uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
    //置为选定GPIO端口引脚
    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    //复位选定GPIO端口引脚
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    //置为或复位选定的GPIO端口引脚
    void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
    //置为或复位选定的GPIO数据端口
    void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
    //将原来的端口引脚的置为设为复位,复位设为置为
    void GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t PortVal);
    
    //外部中断处理函数
    //外设端口作为中断线号输入
    void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
    //事件输出
    void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
    
    void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void GPIO_EventOutputCmd(FunctionalState NewState);
    void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
    void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);
    
    void GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t PortVal)
    {
    	GPIOx->ODR ^= PortVal;
    }
    
  • GPIO库函数简要解释:

    函数名具体功能
    GPIO_DeInit重新初始化外围设备GPIOx相关寄存器到它的默认复位值
    GPIO_AFIODeInit初始化交错功能(remap, event control和 EXTI 配置) 寄存器
    GPIO_Init根据GPIO_初始化结构指定的元素初始化外围设备GPIOx
    GPIO_StructInit填充GPIO_初始化结构(GPIO_InitStruct)内的元素为复位值
    GPIO_ReadInputDataBit读指定端口引脚输入数据
    GPIO_ReadInputData读指定端口输入数据
    GPIO_ReadOutputDataBit指定端口引脚输出数据
    GPIO_ReadOtputData读指定端口输出数据
    GPIO_SetBits置1指定的端口引脚
    GPIO_ResetBits清0指定的端口引脚
    GPIO_WriteBit设置或清除选择的数据端口引脚
    GPIO_Write写指定数据到GPIOx端口寄存器
    GPIO_PinLockConfig锁定GPIO引脚寄存器
    GPIO_EventOutputConfig选择GPIO引脚作为事件输出
    GPIO_EventOutputCmd允许或禁止事件输出
    GPIO_PinRemapConfig改变指定引脚的映射
    GPIO_EXTILineConfig设置外部中断
    GPIO_ETH_MediaInterfaceConfig配置以太网接口
    GPIO_Toggle取反置位端口引脚
  • 主流程

    >>开始
    >>开启PGIO外设时钟
    >>初始化GPIO参数
    >>使能GPIO端口
    >>若有中断,编写中断服务函数
    
  • IO输出实例演示

    #define LED PAout(12) //输出,使用的是位带操作来实现操作某个 IO 口的 1 个位
    
    void led_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;				//GPIO初始句柄
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA端口
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;			//PA.8端口设置
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//IO口的速度为50MHZ
    	
    	GPIO_Init(GPIOA,&GPIO_InitStructure);				//初始化PA
    	GPIO_SetBits(GPIOA,GPIO_Pin_12);					//PA.8输出高
    }
    
    
  • 注意点

    • 在使用PA15引脚的时候,按照正常的 IO 初始化,并且停止使用JTAG,依然不能点亮LED,因为PA15默认JTAG的一个脚,现在要变成普通IO就要使能复用时钟。

    • RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);//使能PA端口
      GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //关闭JTAG口,使PB3,PB4,PA15这几个IO作为普通IO使用
      
  • 操作 IO 口输出高低电平的三种方法

    • 位操作就是可以单独的对一个比特位读和写,这个在51单片机中非常常见。51单片机中通过关键字sbit来实现位定义,STM32F103中没有这样的关键字,而是通过访问位带别名区来实现。

    • 	a.通过位带操作 PA12 输出高低电平从而控制 LED 的方法如下:
      	#define LED PAout(15) 						//输出
      	LED=1; 										//通过位带操作控制 LED 的引脚 PA12 输出高电平
      	LED=0; 										//通过位带操作控制 LED 的引脚 PA12 输出低电平
      	
      	b.使用固件库操作和寄存器操作:
      	来实现 IO 口操作。 库函数操作方法如下:
      	GPIO_SetBits(GPIOA, GPIO_Pin_12);			 //设置 GPIOA12 输出 1,等同 LED=1;
      	GPIO_ResetBits (GPIOA, GPIO_Pin_12); 		//设置 GPIOA12 输出 0,等同 LED=0;
      	库函数操作就直接调用两个函数即可控制 IO 输出高低电平。
      	
      	c.通过直接操作寄存器:
      	BRR 和 BSRR 的方式来操作 IO 口输出高低电平,方法如下:
      	GPIOA->BRR=GPIO_Pin_12; //设置 GPIOA.12 输出 1,等同 LED=1;
      	GPIOA->BSRR=GPIO_Pin_12; //设置 GPIOA.12 输出 0,等同 LED=0;
      
  • IO输入实例演示

  • void Key_Init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能 PORTA 时钟
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PA12
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉
    	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化PA12
    	
    }
    
    void Key_Scan(void)
    {
    	if(KEY == 0)
    	{
    		delay_ms(10);
    		if(KEY == 0)
    			LED = !LED;
    	}
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值