STM32自学笔记(一)GPIO配置与使用

        由于是stm32学习的第一个章节,会啰嗦一些,旨在帮助和我一样刚接触stm32时一头雾水的朋友,更好地理解、学会它。

        很多学过51,刚开始学stm32的朋友可能会和我一样十分不适应,在我看来,stm32与51代码最大的区别在于,stm32几乎所有外设都要进行配置过后才能使用,比如说你想操作一个IO口,那么首先要对这个IO口所挂载的时钟进行使能,再对此IO口进行配置、使能。这也是为什么51点亮一个LED只需要一行代码,你找到的stm32的代码却看着都让人头大的原因。

        为什么要进行初始化(配置)?就GPIO来说,51的IO口很简单,能且只能实现高低电平的输入输出;而stm32可以在此基础上,指定GPIO输入输出的类型,速率等一系列参数,正因为stm32可以实现更多的功能,因此要进行初始化,指定GPIO的参数。实际上配置完成后,就使用上来说是不会比51复杂到哪去的。因此,先耐着性子学会GPIO的配置吧。

认识GPIO初始化

        首先要适应这种stm32的代码风格:对每个模块都写一个xxx_Init()函数进行初始化(配置)。至于这个函数里要写些什么,视这个模块用到哪些功能而定。比如说我想写一个程序控制LED的亮灭,需要用到GPIO,所以要做以下的事情:对GPIO的时钟进行使能、对GPIO进行初始化。把这两个过程写在一个名为LED_Init()的函数中,这样只需要在main()中调用一下LED_Init()就可以实现LED模块的初始化了。

        本章仅讲解GPIO的初始化,其他功能怎么初始化在以后的章节中会进行讲解。

        首先,我们要认识下面这个结构体:GPIO_InitTypeDef

typedef struct 
{  
    uint16_t GPIO_Pin;     
    GPIOSpeed_TypeDef GPIO_Speed;    
    GPIOMode_TypeDef GPIO_Mode;  
}GPIO_InitTypeDef; 

        它具有三个成员变量:GPIO_Pin,  GPIO_Speed,  GPIO_Mode

        对于GPIO的配置其实就是指定这三个参数的值。接下来通过一个实例讲解这三个变量的含义。

GPIO_InitTypeDef  GPIO_InitStructure; 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  //LED0-->PB.5 端口配置 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz 
GPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数配置 GPIO 

       这便是GPIO初始化的常用格式(事实上stm32任何外设的初始化都可以参照这种格式)

       1.首先,要实例化一个GPIO_InitTypeDef对象,名为GPIO_InitStructure

       2.接下来对它的三个成员变量进行配置。其中GPIO_Pin用来设置是要初始化哪个或者哪些IO口(这里要注意,决定的不是A、B、C...,而是GPIOx后面的数字,也就是16个引脚中的哪一个); GPIO_Mode 是用来设置输出输入模式(GPIO共有8种模式,这里用到的是推挽输出);GPIO_Speed 是IO口速度设置,有2M、10M、50M三个可选值。

       3.最后,调用一下GPIO_Init()函数,GPIO的初始化就完成了。GPIO_Init()第一个参数填GPIOx,也就是确定A、B、C...,结合前面设置的GPIO_Pin,就确定了具体是哪一个IO口;第二个参数填 &GPIO_InitStructure,将我们之前设置好的参数通过GPIO_InitStructure这个对象输入进去,实现GPIO的初始化。

完整的GPIO初始化流程

接下来给出一个完整的GPIO初始化实例,用了两个IO口(PB5、PE5)分别控制两个LED。

void LED_Init(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;			
                        //GPIO_InitTypeDef结构体用于配置GPIO,首先实例化一个它的对象
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB、PE端口的时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);				//根据设定的参数初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);						 //PB.5 输出高电平

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	    		 //LED1-->PE.5 端口配置
 GPIO_Init(GPIOE, &GPIO_InitStructure);	  				//推挽输出,IO口速度为50MHz
    //这里虽然配置的是另一个IO口PE.5,但仍旧使用了上面配置PB.5时的对象,是因为两个IO参数一样,若出现参数不一样的情况,要重新实例化一个对象(或者更改之前对象的参数)
 GPIO_SetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出高电平
}

       认真理解这段代码。其中有两句代码是之前没有提到过的,分别是时钟的使能与GPIO_SetBits() 这个函数。

       GPIO 是挂载在 APB2 总线上的外设,在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的,至于其他情况下时钟使能是什么函数,在以后的章节中会提到。

        至于GPIO_SetBits() 在下文进行讲解。

IO口操作

        GPIO配置完成后,就可以对IO口进行操作了。常用两种方式进行操作,效果是一样的。

寄存器版

        在sys.h中有以下定义

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 
......
//这里由于篇幅关系仅给出GPIOB的定义,其余GPIO端口都有类似定义

       这使IO口的操作变得和51一样简单

#define LED PBout(5)		//define下提高程序可读性
...
LED = 1;					//输出高电平
LED = 0;					//输出低电平
LED_in = PBin(5);			//读取PB.5电平

      可以直接用PBout(5)=1进行GPIOB.5的高电平输出,也可以像51一样先宏定义改个名称,增强可读性。

库函数版

//输出
GPIO_SetBits(GPIOB,GPIO_Pin_8); 		//PB.8输出高电平
GPIO_ResetBits(GPIOB,GPIO_Pin_8);		//PB.8输出低电平
//输入
GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) //读取PE.2电平

Tips:操作IO口前,必须先进行对应的GPIO初始化

  • 16
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值