使用寄存器控制STM32的GPIO操作

一、输出配置

前言:为什么要介绍寄存器来控制I/O口呢,我们在平常时序操作时会用到GPIO,调用库函数去控制不仅显得代码冗长且可能造成响应时间变长,所以了解一下寄存器操作IO口是有必要的。 

1.端口输出数据寄存器(GPIOx_ODR) (x=A..E)

此寄存器也可以实现对GPIO的控制,例如想控制GPIOC的13口置0(为第一行)

当然,也能实现对GPIO的读操作,第二行;

GPIOC->ODR = 0xef;
temp = GPIOC->ODR;

可以发现对于ODR寄存器操作必须以16位的形式进行。

对于ODR的读可以发现库函数对于读取输出IO口状态用到了此寄存器:

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  uint8_t bitstatus = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); 
  
  if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
  {
    bitstatus = (uint8_t)Bit_SET;
  }
  else
  {
    bitstatus = (uint8_t)Bit_RESET;
  }
  return bitstatus;
}

 2.端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E)

BSRR是一个32位的寄存器,为端口的置1或清0寄存器,低16位的作用是让指定的IO口置1;而高16位的作用是让指定的IO口置0。(置1有效)
(每个GPIO有16个口,对应寄存器的低16位和高16位)

#define LED_GPIO_PORT                GPIOC
#define LED_GPIO_PIN                 GPIO_PIN_13

#define LED(x)     LED_GPIO_PORT->BSRR = LED_GPIO_PIN << (16 * (!x))

 如果为LED(1),即将GPIOC的13口置1,等号后边运算结果就等于16位的GPIO,即向BSRR寄存器的13位写1,为低位,相应的GPIO口被拉高;反之,如果为LED(0),即将GPIOC的13口置0,等号后边运算结果就等于16位的GPIO向高位移16位,即向BSRR寄存器的29位写1,为高位,相应的GPIO口被拉低;

BSRR是使用最多的一个寄存器了,其中ODR寄存器负责直接控制端口输出电平,但是某些情况下我们需要更高效、更精准的控制电平状态,便要用到BSRR寄存器了。

3.端口位清除寄存器(GPIOx_BRR) (x=A..E) 

 

此寄存器实现功能就是将I/O口置低电平了,例如将PC13置0:

GPIOC->BRR = GPIO_Pin_13;

 为32位寄存器,高16位为保留地址,低16位相应位置1则输出低电平,与BSRR区别是只能控制I/O口为低电平;

二、输入配置

1.端口输入数据寄存器(GPIOx_IDR) (x=A..E) 

 这个寄存器可以读取I/O状态,可以宏定义一下读取也可以直接读取。例如读取GPIOC电平:

#define   DATA_GPIO_PORT                GPIOC
#define   DATA_IN                       DATA_GPIO_PORT->IDR

/*  等价于   */
uint6_t temp = GPIOC -> IDR;

可以发现读出的为16位数据,如何读一位数据呢?

uint8_t temp;
temp = (uint8_t)(GPIOC->IDR&GPIO_Pin_13);

由于IDR为32位,所以最后要强制转换为16位数据;

三、端口配置寄存器 

为什么要介绍这个寄存器,就是为了在某些时序可能会用到修改I/O模式的时候,比如IIC通信,所以了解一下还是很有必要的。 

1.端口配置低寄存器(GPIOx_CRL) (x=A..E) 

如这个寄存器名字一样,这个寄存器主要操作低八位I/O口,也就是0…7;

这是数据手册截的图,可能第一眼还看不明白,其实这是一个32位寄存器,其中每四个位控制一个I/O口,比如要控制0口:                                                                                                                              0和1位就是写引脚速度,00就是输入模式,01为输出10MHz….                                                        2和3位就是控制MODE,图中写的比较明白了,如果还不明白也没关系,我再举几个例子:

 eg:PA1配置为推挽输出,速度50MHz

GPIOA->CRL&= 0XFFFFFF0F;
GPIOA->CRL |= (u32)3<<4;

       第一条语句是将第4、5、6、7位清0(&是有0则0),此时模式为模拟输入(看上图)。第二条是将第4、5位置1(或运算有1则1);此时模式就为推挽输出,50MHz。3也就是0011,右移4位:0011 0000(当然为32位数据,高位未写出)

2.端口配置高寄存器(GPIOx_CRH) (x=A..E) 

如这个寄存器名字一样,这个寄存器主要操作高八位I/O口,也就是8…15;

 这个和上面的寄存器一样的配置方法,举个例子:

将PA12配置为输入模式:代码第一行

将PA12配置为推挽输出模式:代码第二行

//IO方向设置
#define SDA_IN()  {GPIOA->CRH &= 0XFFF0FFFF;GPIOA->CRH |= (u32)8<<16;}
#define SDA_OUT() {GPIOA->CRH &= 0XFFF0FFFF;GPIOA->CRH |= (u32)3<<16;}

当然,在某些型号的单片机你会发现没有CRH和CRL了,当然这些在F1系列是肯定用不到的,F1系列的就不用看下面介绍的了,下面细分为了下面几种寄存器

      MODER寄存器的功能就是设置输入与输出模式:

                00-输入模式

                01-通用输出模式

                02-备用功能模式

                03-模拟模式

OTYPER其16到31位必须保持复位值,也就是不能写入数据。低15位直接控制16个IO口输出类型:

                                0-推挽输出

                                1-开漏输出

        这个OSPEEDR寄存器主要控制输出速度了,00-低速、01-中速、02-高速、03-超高速

        PUPDR寄存器主要控制输出模式:

                00-无上下拉,即浮空输入;01-上拉输入;02-下拉输入;03-保留

作者:辞丶176

物联沃分享整理
物联沃-IOTWORD物联网 » 使用寄存器控制STM32的GPIO操作

发表回复