一,GPIO功能描述
每个GPIO端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。根据数据手册中列出的每个I/O端口的特定硬件特征, GPIO端口的每个位可以由软件分别配置成多种模式。
STM32F10x的I/O端口位的基本结构
1.1通用功能输入输出(GPIO):
通用功能输入输出(GPIO)包括下面几种模式:
1)输入浮空:即呈现高阻态。如果端口什么都不接,复位期间和刚复位后,IO端口被默认配置成浮空输人模式。
2)输入上拉:即输人高电平。如果端口接一个上拉电阻(起保护作用),表示该端口在默认情况下输入为高电平。
3)输入下拉:即输人低电平。如果端口接一个下拉电阻(起保护作用),表示该端口在默认情况下输入为低电平。
实际应用时,I-0的JTAG引脚常被置为输入上拉或下拉模式:
PA15:JTDI置于上拉模式;PA14:JTCK置于下拉模式;PA13:JTMS 置于上拉模式 PB4:JNTRST置于上拉模式。
4)开漏输出:本身不输出电压,要想输出高电平必须接上拉电阻。
5)推挽式输出:直接输出高低电平电压。低电平时接地,高电平时输出电源电压。这种方式可以不接上拉电阻。
1.2复用功能输入输出(AFIO)
STM32F10x的AFIO包括默认复用功能和软件重新映射复用功能。
默认复用功能:
引脚的默认复用功能是固定的,有复用输入、复用输出和双向复用。复用功能输人输出(AFIO)包括下面几种模式:
1)复用输人功能:端口必须配置成输人模式(浮空、上拉或下拉)且输人引脚必须由外部驱动。
2)模拟输人:用于ADC 模拟输入。
3)推挽式复用输出功能:片内外设的功能,如FC的SCL、SDA。
4)开漏复用输出功能:片内外设的功能,如SPI的SCK、MOSIMISO。
5)双向复用功能:输出时,端口位必须配置成复用功能输出模式(推挽或开漏)。人时,输入驱动器被配置成浮空输入模式。
2.软件重新映射复用功能
为了使不同器件封装的外设1功能的数量达到最优,可以把一复用功能重新映射其他一些引脚上。
二,GPIO常用库函数
STM32标准库中提供了几乎覆盖所有GPIO操作的函数
1.函数GPIO_DeInit
函数GPIO_DeInit 的原型为void GPIO_DeInit(GPIO_TypeDef*GPIOx),使用方法为:
GPIO_DeInit();
2. 函数 GPIO_AFIODeInit
函数GPIO_AFIODeInit 的原型为void GPIO_AFIODelnit(void),使用方法为:
GPIO_AFIODeInit();
3.函数 GPIO_Init
函数GPIO_Init 原型为voidGPO_Init (GPIO_TypeDefGPIOx,GPIO_InitTypeDefGPIO_InitStruct),该结构体中包含了外设GPIO所有信息,如引脚名称、引脚传输速作引脚工作模式等,具体结构如下:
typedef struct{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
GPIO_InitTypeDef;
}
3.1 参数GPIO_Pin用来选择待设置的GPIO_Pin值。该参数可取值及含义如下:
GPIO_Pin_None/无引脚被选中/
GPIO_Pin_n n=1,2,…,15/选中引脚n/
GPIO_Pin_All /* 选中全部引脚 */
3.2 GPIO_Speed 用以设置选中引脚的率。该参数可取值及含义如下:
GPIO_Speed_10MHz/*最高输出速率10MHz /
GPIO_Speed_20MHz /最高输出速率20MHz/
GPIO_Speed_50MHz/最高输出速率50MHz/
3.3 GPIO_Mode用以设置选中引脚的工作状态。该参数可取值及含义如下:
GPIO_Mode_AIN / 模拟输入 /
GPIO_Mode_IN_FLOATING / 浮空输人 */
GPIO_Mode_IPD /*下拉输人 */
GPIO_Mode_IPU /*上拉输人 /
GPIO_Mode_Out_OD / 开漏输出 */
GPIO_Mode_Out_PP /*推挽输出 /
GPIO_Mode_AF_OD/ 复用开漏输出 /
GPIO_Mode_AF_PP / 复用推挽输出 */
该函数使用方法如下:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure. GPIO_Pin = GPIO_Pin_All;
CPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPI0_Mode = GPI_Mnde_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
4.函数GPIO_StructInit
函数GPIO_StructInit 原型为void GP_StructInit(GPIO_InitTypeDef GPIO_InitStruct), GPIO_InitStruct 各个成员的默认值为:GPIO_Pin_All、CPIO_Speed_2MHz、GPIO_Mode_IN_ FLOATING。该函数的使用方法如下:
GPIO_StruetInit(GPIOA,&GPIO_InitStcture);
5.函数 GPIO_ReadInputDataBit
函数GPIO_ReadInputDataBit 的原型为uint8_t GPIO_ReadInpuDataBit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin),该函数的使用方法如下:
//读取 PB7 的输人值
uint8_t ReadValue;
ReadValue=GPIO_ReadInputDataBit(GPIOBPIO_Pn_7);
6.函数 GPIO_ReadInputData
函数GPIO_ReadInputData 的原型为uint16_t GPIO_ReadInputData (GPIO_TypeDef* GPIOx),该函数的使用方法如下:
//读取PB 的输入值
uint16_t ReadValue;
ReadValue = GPIO_ReadInputData(GPIOB);
7. 函数 GPIO_ReadOutputDataBit
函数GPIO_ReadOutputDataBit的原型为uint8_t GPIO_ReadOutputDataBit (GPIO_Ty peDef* GPIOx,uint16_t GPIO_Pin),该函数的使用方法如下:
//读取PB7的输出值
uint8_t ReadValue;
ReadValue = GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_7);
8. 函数 GPIO_ReadOutputData
函数GPIO_ReadOutputData 的原型为uint16_t GPIO_ReadOutputDuta(GPIO_TypeDef * GPIOx),使用方法如下:
//读取 PB 的输出值
uint16_t ReadValue;
ReadValue = GPIO_ReadOutputData(GPIOB);
9. 函数 GPIO_SetBits
函数GPIO_SetBits 的原型为 void GPIO_SetBits(GPIO_TypeDef* GPIOx,uint16_ t GPIO_ Pin),使用方法如下:
//设置PA10和PA15为1
GPIO_SetBits(GPIOA,GPIO_Pin_10|GPIO_Pin_15);
10.函数GPIO_ResetBits
函数GPIO_ResetBits 的原型为void GPIO_ResetBits(GPI0_TypeDef*GPIOx,uint16_t GPIO_Pin),使用方法如下:
//设置PA10和PA15为0
GPIO_ResetBits(GPIOA,GPI0_Pin_10I GPIO_Pin_15);
11.函数 GPIO_WriteBit
函数_WriteBit 原型为voidP_WriteBit(PO_TypeDef*GPIOx,uint6__ CP _Pin,BitAction BitVal),使用方法如下:
//设置PA15 为1
GPIO_WriteBit(GPIOA,GPIO_Pin_15,Bit_SET);
12.函数 GPIO_Write
函数GPIO_Write 的原型为void GPIO_Write(GPIO_TypeDef* GPIOx,uint16_t PortVal),使用方法如下:
//设置PA为1101H
GPIO_Write(GPIOA,0x1101);
13.函数 GPIO_PinLockConfig
函数GPIO_PinlockConfig 的原型为 void GPIO_PinLockConfig(GPI_TypeDef* GPIO uint16_t GPIO_Pin),使用方法如下:
//锁定PAO 和 PA1
GPIO_PinLockConfig(GPIOA,GPIO_Pin_0|GPIO_Pin_1)
14.函数GPIO_EventOutputConfig
函数GPIO_EventOutputConfig 的原型为void GPIO_EventOutputConfig(uint8_t GPIO_PortSource,uint8_t GPIO_PinSource),使用方法如下:
//设置PA5 为事件输出引脚 5830
GPIO_EventOutputConfig(GPIO_PortSourceGPIOA,GPIO_PinSource5)
15.函数GPIO_EventOutputCmd
函数GPIO_EventOutputCmd 的原型为void GPIO_EventOutputCmd (FunctionalState New State),使用方法如下:
//使能PC6事件输出引脚
CPIO_EventOutputConfig(GPIO_PortSourceGPIOC,GPIO_PinSource6); GPIO_EventOutputCmd(ENABLE);
16. 函数GPIO_PinRemapConfig
函数GPIO_PinRemapConfig的原型为void CPIO_PinRemapConfig(uint32_t GPIO_Remap FunctionalState NewState),使用方法如下
//重映射IC_SCL为PB8,IC_SDA为PB9
CPIO_PinRemapConfig(GPIO_Remap_2C,ENABLE);
17.函数GPIO_EXTILineConfig
函数GPIO_EXTILineConfig的原型为void CPIO_EXTILineConfig(uint8_ GPIO_PortS ource,uint8_t GPIO_PinSource),使用方法如下:
//设置PB8为外部中断线
GPIO_EXTILineConfig(GPIO_PortSource GPIOB,GPIO_PinSource8);
三,GPIO使用流程
根据O 端口的特定硬件特征,10 端口的每个引脚都可以由软件配置成多种工作模式。在运行程序之前必须对每个用到的引脚功能进行配置。如果某些引脚的复用功能没有使用,可以先配置为通用输入输出 GPIO。如果功能被使用,需要对复用的端口进行配置。IO具有锁定机制,允许冻结配置。当在一个端口位上执行了锁定(LOCK)程序后,在下一次复位之前,将不能再更改端口位的配置。
普通 GPIO 配置
GPIO 是最基本的应用,其基本配置方法为:
1)配置GPIO 时钟,完成初始化。
2)利用函数GPIO_Init配置引脚,包括引脚名称、引脚传输速率、引脚工作模式。
3)完成GPIO_Init 的设置。
IO 复用功能AFIO配置
IO复用功能AFIO常对应到外设的输入输出功能。使用时,需要先配置IO 为复用功能,打开AFIO时钟,然后再根据不同的复用功能进行配置。对应外设的输入输出功能有下述三种情况:
1)外设对应的引脚为输出:需要根据外围电路的配置选择对应的引脚为复用功能的推挽输出或复用功能的开漏输出。
2)外设对应的引脚为输人:根据外围电路的配置可以选择浮空输人、带上拉输入或带下拉输人。
3)ADC对应的引脚:配置引脚为模拟输入。
四,GPIO设计实例
1.LED闪烁
LED.C
#include "LED.h"
void LED_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启LED相关的GPIO外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
LED.h
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
void LED_GPIO_Config(void);
#endif /* __LED_H */
main()
#include "LED.h"
#include "stm32f10x.h"
void Delay(uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
while (1)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_5);/* 关闭led灯 */
Delay(0x0FFFFF);
GPIO_SetBits(GPIOB, GPIO_Pin_5);/* 打开led灯*/
Delay(0x0FFFFF);
}
}
2.GPIO输入检测
按键K1连接A0,当按下时,A0被拉低,此时检测为低电平,LED关闭,相反打开LED.
KEY.c
#include "KEY.h"
// 配置按键用到的I/O口
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*开启按键端口的时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//选择按键的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
// 设置按键的引脚为浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//使用结构体初始化按键
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
KEY.h
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
void Key_GPIO_Config(void);
#endif /* __KEY_H */
main.c
#include "stm32f10x.h"
#include "LED.h"
#include "KEY.h"
int main(void)
{
/* LED端口初始化 */
LED_GPIO_Config();
/* 按键端口初始化 */
Key_GPIO_Config();
/* 轮询按键状态,若按键按下则反转LED */
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 1 )
{
GPIO_SetBits(GPIOB, GPIO_Pin_5);/* 打开led灯*/
} else{
GPIO_ResetBits(GPIOB, GPIO_Pin_5);/* 关闭led灯 */
}
}
}