GPIO
前言
STM32上的144个引脚分为:
GPIO(General Purpose Input Output)通用输入输出IO口,112个
PA 16个
PB 16个
PC 16个
PD 16个
PE 16个
PF 16个
PG 16个
电源引脚,27个
VDD 11个 :GND
VSS 11个 :3.3V
Vref+ 1个 :开发板模拟部分(ADC/DAC)的参考电压(Vref+和 Vref-)
Vref- 1个 :开发板模拟部分(ADC/DAC)的参考电压(Vref+和 Vref-)
VDDA 1个: Vref+的输入 范围为:2.4~VDDA
VSSA 1个 : Vref-必须和 VSSA 连接在一起
VBAT 1个 :后备区域供电脚,采用纽扣电池和 VCC3.3 混合供电的方式VBAT 总是有电的,以保证 RTC 的走时以及后备寄存器的内容不丢失
BOOT引脚 BOOT0 1个
复位引脚 NRST 1个,不做其它功能使用
晶振引脚OSC_IN 1个 :输入引脚 I
晶振引脚OSC_OUT 1个:输出引脚 O
106号引脚NC 1个:NO Connect NC引脚悬空或者接地都可以,NC引脚预留是后面H7系列产品升级会在部分NC引脚中做其他功能。
寄存器: 寄存器就是一段特殊的存储器,内核可以通过APB2总线对寄存器进行读写,这样就可以完成输出电平和读取电平的功能了
GPIO的介绍
GPIO(General Purpose Input Output)通用输入输出IO口,是由芯片直接可控制的引脚。GPIO的引脚通过与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。
GPIO的基本结构
位带区域 :在STM32中专门分配有一段地址区域,这段地址映射了RAM和外设寄存器所有的位,读写这段地址中的数据,就相当于读写所映射位置的某一位,相当于51中的位寻址操作
开漏模式 :可用作通信协议的驱动方式,eg:I2C;在多极通信的情况下,可避免各个设备的相互干扰,还可用于输出5V的电平信号:在I/O口外接一个上拉电阻(弱上拉),在高阻态(开漏)模式下,可输出5V,在低电平时输出低电平。(开漏模式下低电平有驱动能力,高电平没有驱动能力)
STM32片上外设举例:
通用输入/输出(GPIO):用于数字输入输出的引脚。
串行通信接口(SPI):用于与其他设备进行高速异步串行通信。
串行同步接口(I2C):用于与其他设备进行串行同步通信。
通用异步接收器/发送器(USART):用于异步串行数据通信。
通用串行总线(USB):用于USB连接和通信。
通用定时器/计数器(TIM):用于定时和计数操作。
通用同步异步收发器(USART):用于串行通信和数据传输。
多媒体卡接口(SDIO):用于与SD存储卡进行通信。
同步异步接收器/发送器(UART):用于异步串行通信。
时序控制器(RTC):用于实时时钟和日历功能。
脉冲宽度调制器(PWM):用于产生可调节脉冲宽度的信号。
模拟到数字转换器(ADC):用于将模拟信号转换为数字信号。
数字到模拟转换器(DAC):用于将数字信号转换为模拟信号。
以太网控制器(ETH):用于以太网连接和通信。
控制器区域网络(CAN):用于CAN总线通信。
GPIO的工作模式
输入模式:
浮空输入(数字输入):可读取引脚电平,若引脚悬空,则电平不确定
上拉输入(数字输入):可读取引脚电平,内部连接上拉电阻,悬空时默认高电平
下拉输入(数字输入):可读取引脚电平,内部连接下拉电阻,悬空时默认低电平
模拟输入(模拟输入):GPIO无效(下图中的左侧的所有寄存器),引脚直接接入内部ADC
输出模式(数字输出):
开漏输出:可输出引脚电平,高电平为高阻态,低电平接VSS
推挽输出:可输出引脚电平,高电平接VDD,低电平接VSS
复用开漏输出:由片上外设控制,高电平为高阻态,低电平接VSS
复用推挽输出:由片上外设控制,高电平接VDD,低电平接VSS
GPIO的使用方法
STM32 的每个 IO 端口都有 7 个寄存器来控制,常用的 IO 端口寄存器只有 4 个CRL、CRH、IDR、ODR
:
端口配置寄存器:配置寄存器使用来设置GPIO端口和此端口的应用模式
端口配置低寄存器(GPIOx_CRL)(x=A..E):
STM32 的 CRL
控制着PA~PG的低 8 位(IO0~IO7)的模式。 每个 IO 端口使用 CRL
的 4 个位,高两位为 CNF
,低两位为 MODE
GPIOA -> CRL &= ~ ( 0xf << 4 ); //PA1-->端口配置低寄存器清0
GPIOA -> CRL |= ( 0x3 << 4 ); //PA1-->端口配置低寄存器设置为:输出模式,最大速度50MHz,通用开漏输出模式
GPIOA -> CRL &= ~ ( 0xf << 4 ); //PA1-->端口配置低寄存器清0
GPIOA -> CRL |= ( 0x8 << 4 ); //PA1-->端口配置低寄存器设置为:输入模式,上拉/下拉输入模式
GPIOC -> ODR = ( 0X1 << 1 ); //设置成上拉输入。这里为什么是ODR 是因为手册上有说明 虽然在设置IO输入后,输出是断开的,但是不影响ODR数据寄存器的使用 可以设置其为上下拉输入 见端口位配置表
常用的配置:
0X0 表示模拟输入模式 ( ADC 用 )
0X3 表示推挽输出模式 ( 做输出口用 , 50 M 速率 )
0X8 表示上 / 下拉输入模式 ( 做输入口用 )
0XB 表示复用输出 ( 使用 IO 口的第二 功能 , 50 M 速率 )
端口配置高寄存器(GPIOx_CRH)(x=A..E):
STM32 的 CRH
控制着PA~PG的低 8 位(IO8~IO15)的模式。 每个 IO 端口使用 CRH
的 4 个位,高两位为 CNF
,低两位为 MODE
由于和CRL使用一样就不再赘述
端口数据寄存器:我自己的理解就是可以通过对以下的寄存器的配置就可以使IO口读取或者输出数据(0或1)
端口输入数据寄存器(GPIOx_IDR)(x=A..E):
IDR
是一个端口输入数据寄存器,只用了低 16 位。该寄存器为只读寄存器,并且只能以 16 位的形式读出
#define KEY1 (GPIOA->IDR & (0x1<<0)) //GPIOA->IDR输入数据 读取PA0的状态 和1相与
//①按键按下低电平 有效--> KEY1==0;②按键按下高电平 有效-->KEY1==1;
GPIOA -> CRL &= ~ ( 0xf << 0 ); //PA0-->端口配置低寄存器清0
GPIOA -> CRL |= ( 0x4 << 0 ); //PA0-->端口配置低寄存器设置为:浮空输入模式
端口输出数据寄存器(GPIOx_ODR)(x=A..E):
ODR
是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口 的输出电平。
GPIOA -> CRL &= ~ ( 0xf << 4 ); //PA1-->端口配置低寄存器清0
GPIOA -> CRL |= ( 0x3 << 4 ); //PA1-->端口配置低寄存器设置为:输出模式,最大速度50MHz,通用开漏输出模式
//初始化后 默认的输出值为0
GPIOA -> ODR |= 0X1 << 4 ; //使其输出1
端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E)
端口位清除寄存器(GPIOx_BRR) (x=A..E)
端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)
GPIO的实战应用
学习了以上知识,就可以使用STM32来开始我们的实战演练了
跑马灯(点灯大师第一步)(GPIO输出)
使用寄存器来点亮LED
此点灯过程中默认LED灯正极是插在3.3V下的,也就是IO输出低电平点亮
高阶玩法:
使用宏定义带参数
//写在led.h头文件中
/*
x==1 灯亮
x==0 灯灭
宏定义带参数,采用三目运算法
*/
#define LED0(x) (x)?(GPIOA->ODR &= ~(0x1<<0)):(GPIOE->ODR |= (0x1<<0)) //PA0
#define LED1(x) (x)?(GPIOA->ODR &= ~(0x1<<1)):(GPIOE->ODR |= (0x1<<1)) //PA1
#define LED2(x) (x)?(GPIOA->ODR &= ~(0x1<<2)):(GPIOE->ODR |= (0x1<<2)) //PA2
#define LED3(x) (x)?(GPIOA->ODR &= ~(0x1<<3)):(GPIOE->ODR |= (0x1<<3)) //PA3
//在主函数直接使用LED1(1) 就可以将 PA0处的小灯点亮
/*
使用 异或 来控制LED灯的亮灭
相同为0,不同为1
与0异或,为其本身
与1异或,0,1互换
xxxx xxxx xxxx x1xx
^
0000 0000 0000 0100
xxxx xxxx xxxx x0xx
*/
#define LED0TURN GPIOA->ODR ^= (0x1<<0) //PA0
#define LED1TURN GPIOA->ODR ^= (0x1<<1) //PA1
#define LED2TURN GPIOA->ODR ^= (0x1<<2) //PA2
#define LED3TURN GPIOA->ODR ^= (0x1<<3) //PA3
//在主函数main.c的while(1)直接使用LED1TURN和延时函数可以实现LED闪烁
delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include "stdint.h" //加上就是可以让编译器找到uint32_t 这个关键字
void Delay_us ( uint32_t us );
void Delay_ms ( uint32_t ms );
void Delay_s ( uint32_t s );
#endif
delay.c
#include "stm32f10x.h"
#include "Delay.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us ( uint32_t xus )
{
SysTick -> LOAD = 72 * xus ; //设置定时器重装值
SysTick -> VAL = 0x00 ; //清空当前计数值
SysTick -> CTRL = 0x00000005 ; //设置时钟源为HCLK,启动定时器
while ( ! ( SysTick -> CTRL & 0x00010000 )); //等待计数到0
SysTick -> CTRL = 0x00000004 ; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms ( uint32_t xms )
{
while ( xms -- )
{
Delay_us ( 1000 );
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s ( uint32_t xs )
{
while ( xs -- )
{
Delay_ms ( 1000 );
}
}
使用位带操作
未待完续
使用库函数来点亮LED
此点灯过程中默认LED灯正极是插在3.3V下的,也就是IO输出低电平点亮
main.c led.h led.c
#include "stm32f10x.h" // Device header
#include "led.h"
int main ( void )
{
Led_Init ();
//GPIO_ResetBits(GPIOA, GPIO_Pin_0);//重新初始化PA0--IO,初始化后值为0,点亮
GPIO_WriteBit ( GPIOA , GPIO_Pin_0 , Bit_SET ); //第三项可直接赋值:枚举、Bit_SET--高电平熄灭/Bit_RESET--低电平点亮
while ( 1 )
{
//以下就可以使PA0--LED进行闪烁
GPIO_ResetBits ( GPIOA , GPIO_Pin_0 ); //输出低电平 点亮LED
Delay_ms ( 500 );
GPIO_SetBits ( GPIOA , GPIO_Pin_0 ); //输出高电平,点灭LED
Delay_ms ( 500 );
GPIO_WriteBit ( GPIOA , GPIO_Pin_0 , Bit_RESET ); //输出低电平 点亮LED
Delay_ms ( 500 );
GPIO_WriteBit ( GPIOA , GPIO_Pin_0 , Bit_SET ); //输出高电平,点灭LED
Delay_ms ( 500 );
GPIO_WriteBit ( GPIOA , GPIO_Pin_0 ,( BitAction ) 0 ); //输出高电平,点灭LED,0前面要加上强制类型转换 转换成枚举类型
Delay_ms ( 500 );
GPIO_WriteBit ( GPIOA , GPIO_Pin_0 ,( BitAction ) 1 ); //输出高电平,点灭LED,1前面要加上强制类型转换 转换成枚举类型
Delay_ms ( 500 );
}
}
#ifndef __LED_H__
#define __LED_H__
#include "stm32f10x.h"
void Led_Init ( void );
#endif
#include "led.h"
void Led_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE ); //使能时钟A
//为初始化函数做准备
GPIO_InitTypeDef GPIO_InitStructure ; //定义结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_0 ; //设置PA1引脚
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_Out_PP ; //设置输出模式为推挽输出
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ; //设置输出速度为50MHZ
//初始化函数↓
GPIO_Init ( GPIOA , & GPIO_InitStructure ); //初始化
GPIO_SetBits ( GPIOA , GPIO_Pin_0 ); //初始化时默认低电平,我们主动设置输出高电平,点灭LED
}
在推挽输出的模式下,此时可以将LED灯正极接到IO口,负极接到GND,发现LED会继续闪烁,证实了推挽输出高低电平都具有驱动能力,如果此时再将输出模式改为开漏模式,LED将不再闪烁,证实了开漏模式在IO输出高电平时为高阻态
流水灯
PA0-->PA7的流水灯
main.c led.h led.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"
int main ( void )
{
Led_Init ();
unsigned int i = 0 ;
while ( 1 )
{
GPIO_Write ( GPIOA , ~ 0x0001 ); //0000 0000 0000 0001 <--二进制 GPIO_Write第二个参数必须是16进制 注释只是形象解释
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0002 ); //0000 0000 0000 0010
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0004 ); //0000 0000 0000 0100
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0008 ); //0000 0000 0000 1000
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0010 ); //0000 0000 0001 0000
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0020 ); //0000 0000 0010 0000
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0040 ); //0000 0000 0100 0000
Delay_ms ( 500 );
GPIO_Write ( GPIOA , ~ 0x0080 ); //0000 0000 1000 0000
Delay_ms ( 500 );
//下面这个是上面的简易写法 同样实现PA0-->PA7的流水灯的效果
/*
for(i=0;i<8;i++)
{
GPIO_Write(GPIOA,~(0x1<<i));
Delay_ms(500);
}
*/
}
}
#ifndef __LED_H__
#define __LED_H__
#include "stm32f10x.h"
void Led_Init ( void );
#endif
#include "led.h"
void Led_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE ); //使能时钟A
//为初始化函数做准备
GPIO_InitTypeDef GPIO_InitStructure ; //定义结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_ALL ; //设置PA1引脚
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_Out_PP ; //设置输出模式为推挽输出
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ; //设置输出速度为50MHZ
//初始化函数↓
GPIO_Init ( GPIOA , & GPIO_InitStructure ); //初始化
GPIO_SetBits ( GPIOA , GPIO_Pin_ALL ); //初始化时默认低电平,我们主动设置输出高电平,点灭LED
}
蜂鸣器(GPIO输出)
有源蜂鸣器是有正负引脚的和IO口引脚的,在IO引脚加上电压信号就会发声,发出的声音音调单一、频率固定,本次使用的蜂鸣器是低电平触发
按键(GPIO输入)
在GPIO的工作模式中我们知道,GPIO输入模式下有四种方式:浮空输入,上拉输入,下拉输入和模拟输入,前三种都属于数字输入,也是此章节所学习和使用的模式,模拟输入是在ADC章节中所学习使用,在后面的学习过程中介绍。
何时使用那种输入方式,其实是看所使用的场景和硬件设计要求
下图中,按键按下低电平有效 ---->我们就要使GPIO的输入模式默认为上拉输入,也就是在空闲状态下默认高电平,此时不能使用浮空输入是因为 引脚悬空会造成电平不确定,而下拉更不能使用,因为下拉默认低电平,就会造成按键无用
下图中,按键按下低电平有效 ---->此时因为有个上拉电阻R1的存在,PA0默认高电平,所以此时我们可以使GPIO的输入模式使用上拉输入或者浮空输入都可以
下图中,按键按下高电平有效 ---->我们就要使GPIO的输入模式默认为下拉输入,也就是在空闲状态下默认低电平,此时不能使用浮空输入是因为 引脚悬空会造成电平不确定,而上拉更不能使用,因为上拉默认高电平,就会造成按键无用
下图中,按键按下高电平有效 ---->此时因为有个下拉电阻R1的存在,PA0默认低电平,所以此时我们可以使GPIO的输入模式使用下拉输入或者浮空输入都可以
按键的介绍:
使用寄存器按键来控制LED
以下示例是按键按下时低电平触发,IO引脚空闲状态为高电平,上拉输入
main.c led.h led.c key.h key.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"
#include "Beep.h"
#include "Key.h"
int main ( void )
{
uint8_t keyflag = 0 ; //按键标志位
Led_Init ();
Key_Init ();
while ( 1 )
{
keyflag = Key_GetNum ();
switch ( keyflag )
{
case 1 :
LED1_Turn (); break ;
case 2 :
LED2_Turn (); break ;
case 3 : break ;
case 4 : break ;
}
}
}
#ifndef __LED_H__
#define __LED_H__
#include "stm32f10x.h"
void Led_Init ( void );
void LED1_ON ( void );
void LED2_ON ( void );
void LED1_OFF ( void );
void LED2_OFF ( void );
void LED1_Turn ( void );
void LED2_Turn ( void );
#endif
#include "led.h"
void Led_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE ); //使能时钟A
//为初始化函数做准备
GPIO_InitTypeDef GPIO_InitStructure ; //定义结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 ; //设置PA1,PA2引脚
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_Out_PP ; //设置输出模式为推挽输出
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ; //设置输出速度为50MHZ
//初始化函数↓
GPIO_Init ( GPIOA , & GPIO_InitStructure ); //初始化
GPIO_Write ( GPIOA ,( 0X6 )); //初始化时默认低电平,我们主动设置输出高电平,点灭LED
//GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2); //使用上面或者下面这种方式都可以将其设置为高电平
}
void LED1_ON ( void )
{
GPIO_ResetBits ( GPIOA , GPIO_Pin_1 );
}
void LED1_OFF ( void )
{
GPIO_SetBits ( GPIOA , GPIO_Pin_1 );
}
void LED1_Turn ( void ) //PA1状态翻转
{
if ( GPIO_ReadOutputDataBit ( GPIOA , GPIO_Pin_1 ) == 0 ) //这个函数就是用来检测端口输出状态的函数,当检测输出端口为0时,将PA1置1
{
GPIO_SetBits ( GPIOA , GPIO_Pin_1 );
}
else
{
GPIO_ResetBits ( GPIOA , GPIO_Pin_1 ); //当检测输出端口为1时,将PA1置0
}
}
void LED2_ON ( void )
{
GPIO_ResetBits ( GPIOA , GPIO_Pin_2 );
}
void LED2_OFF ( void )
{
GPIO_SetBits ( GPIOA , GPIO_Pin_2 );
}
void LED2_Turn ( void ) //PA2状态翻转
{
if ( GPIO_ReadOutputDataBit ( GPIOA , GPIO_Pin_2 ) == 0 ) //这个函数就是用来检测端口输出状态的函数,当检测输出端口为0时,将PA1置1
{
GPIO_SetBits ( GPIOA , GPIO_Pin_2 );
}
else
{
GPIO_ResetBits ( GPIOA , GPIO_Pin_2 ); //当检测输出端口为1时,将PA1置0
}
}
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32f10x.h"
#include "Delay.h"
void Key_Init ( void );
uint8_t Key_GetNum ( void );
#define KEY1 (GPIOB->IDR & (0x1<<1)) //GPIOB->IDR输入数据 读取PB1的状态 和1相与
#define KEY2 (GPIOB->IDR & (0x1<<11)) //GPIOB->IDR输入数据 读取PB11的状态 和1相与
#endif
#include "Key.h"
void Key_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOB , ENABLE ); //使能时钟B
//为初始化函数做准备
GPIO_InitTypeDef GPIO_InitStructure ; //定义结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_1 ; //设置PB的1号和11号引脚
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_IPU ; //设置输出模式为上拉输入
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ; //设置输出速度为50MHZ,GPIO输入时此参数无效 但一般还是设置上
//初始化函数↓
GPIO_Init ( GPIOB , & GPIO_InitStructure ); //初始化
}
uint8_t Key_GetNum ( void )
{
if ( ! KEY1 ) //与0x01相与后为0 --> 按键按下
{
Delay_ms ( 15 ); //延时消抖
if ( ! KEY1 )
{
while ( ! KEY1 ) //等待按键抬起
{
}
Delay_ms ( 15 ); //延时消抖
return 1 ;
}
}
if ( ! KEY2 ) //与0x01相与后为0 --> 按键按下
{
Delay_ms ( 15 ); //延时消抖
if ( ! KEY2 )
{
while ( ! KEY2 ) //等待按键抬起
{
}
Delay_ms ( 15 ); //延时消抖
return 2 ;
}
}
return 0 ;
}
使用库函数按键来控制LED
以下示例是按键按下时低电平触发,IO引脚空闲状态为高电平,上拉输入
main.c
,led.c
和led.h
都与使用寄存器按键来控制LED 章节一致
使用光敏传感器来控制蜂鸣器(库函数)
光源充足的时候蜂鸣器不鸣叫,光源较暗时蜂鸣器鸣叫
main.c LightSensor.h LightSensor.c Beep.h Beep.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"
#include "Beep.h"
#include "Key.h"
#include "LightSensor.h"
int main ( void )
{
Beep_Init ();
LightSen_Init ();
while ( 1 )
{
if ( Lightsen_Get () == 1 ) //光线较暗时,蜂鸣器鸣叫,Lightsen_Get()返回的值是默认的上拉模式高电平
{
Beep_ON ();
}
else
{
Beep_OFF ();
}
}
}
#ifndef __LIGHTSENSOR_H__
#define __LIGHTSENSOR_H__
#include "stm32f10x.h"
void LightSen_Init ( void );
uint8_t Lightsen_Get ( void );
#endif
#include "LightSensor.h"
void LightSen_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOB , ENABLE ); //使能时钟B
//为初始化函数做准备
GPIO_InitTypeDef GPIO_InitStructure ; //定义结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_13 ; //设置PB的12引脚
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_IPU ; //设置上拉模式
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ; //设置输出速度为50MHZ,在输入模式下无效
//初始化函数↓
GPIO_Init ( GPIOB , & GPIO_InitStructure ); //初始化
}
uint8_t Lightsen_Get ( void )
{
return GPIO_ReadInputDataBit ( GPIOB , GPIO_Pin_13 );
}
#ifndef __BEEP_H__
#define __BEEP_H__
#include "stm32f10x.h"
void Beep_Init ( void );
void Beep_ON ( void );
void Beep_OFF ( void );
void Beep_Turn ( void );
#endif
#include "Beep.h"
void Beep_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOB , ENABLE ); //使能时钟B
//为初始化函数做准备
GPIO_InitTypeDef GPIO_InitStructure ; //定义结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_12 ; //设置PB的12引脚
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_Out_PP ; //设置输出模式为推挽输出
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ; //设置输出速度为50MHZ
//初始化函数↓
GPIO_Init ( GPIOB , & GPIO_InitStructure ); //初始化
GPIO_SetBits ( GPIOB , GPIO_Pin_12 ); //初始化时默认低电平,我们主动设置输出高电平,使蜂鸣器不响
}
void Beep_ON ( void )
{
GPIO_ResetBits ( GPIOB , GPIO_Pin_12 );
}
void Beep_OFF ( void )
{
GPIO_SetBits ( GPIOB , GPIO_Pin_12 );
}
void Beep_Turn ( void )
{
if ( GPIO_ReadOutputDataBit ( GPIOB , GPIO_Pin_12 ) == 0 ) //这个函数就是用来检测端口输出状态的函数,当检测输出端口为0时,将PB12置1
{
GPIO_SetBits ( GPIOB , GPIO_Pin_12 );
}
else
{
GPIO_ResetBits ( GPIOB , GPIO_Pin_12 ); //当检测输出端口为1时,将PA1置0
}
}
GPIO的库函数
Table 1. GPIO 库函数
函数名
描述
GPIO_DeInit
将外设 GPIOx 寄存器重设为缺省值
GPIO_AFIODeInit
将复用功能(重映射事件控制和 EXTI 设置)重设为缺省值
GPIO_Init
根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器
GPIO_StructInit
把 GPIO_InitStruct 中的每一个参数按缺省值填入
GPIO_ReadInputDataBit
读取指定端口管脚的输入
GPIO_ReadInputData
读取指定的 GPIO 端口输入
GPIO_ReadOutputDataBit
读取指定端口管脚的输出
GPIO_ReadOutputData
读取指定的 GPIO 端口输出
GPIO_SetBits
设置指定的数据端口位
GPIO_ResetBits
清除指定的数据端口位
GPIO_WriteBit
设置或者清除指定的数据端口位
GPIO_Write
向指定 GPIO 数据端口写入数据
GPIO_PinLockConfig
锁定 GPIO 管脚设置寄存器
GPIO_EventOutputConfig
选择 GPIO 管脚用作事件输出
GPIO_EventOutputCmd
使能或者失能事件输出
GPIO_PinRemapConfig
改变指定管脚的映射
GPIO_EXTILineConfig
选择 GPIO 管脚用作外部中断线路
GPIO_Init 函数
Table 2. 函数 GPIO_Init
函数名
GPIO_Init
函数原形
void GPIO_Init(GPIO_TypeDef GPIOx, GPIO_InitTypeDef GPIO_InitStruct)
功能描述
根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
GPIO_InitStruct:指向结构 GPIO_InitTypeDef 的指针,包含了外设 GPIO 的配置信息参阅 Section: GPIO_InitTypeDef 查阅更多该参数允许取值范围
输出参数
无
返回值
无
先决条件
无
被调用函数
无
GPIO_InitTypeDef structure结构体: /*
GPIO_InitTypeDef 定义于文件"stm32f10x_gpio.h":
*/
typedef struct {
u16 GPIO_Pin ;
GPIOSpeed_TypeDef GPIO_Speed ;
GPIOMode_TypeDef GPIO_Mode ;
} GPIO_InitTypeDef ;
GPIO_Pin
GPIO_Pin 该参数选择待设置的 GPIO 管脚,使用操作符“|”可以一次选中多个管脚。可以使用下表中的任意组合。
Table 3. GPIO_Pin 值
GPIO_Pin
选中引脚
描述
GPIO_Pin_None
无管脚被选中
GPIO_Pin_0
选中管脚 0
GPIO_Pin_1
选中管脚 1
GPIO_Pin_2
选中管脚 2
GPIO_Pin_3
选中管脚 3
GPIO_Pin_4
选中管脚 4
GPIO_Pin_5
选中管脚 5
GPIO_Pin_6
选中管脚 6
GPIO_Pin_7
选中管脚 7
GPIO_Pin_8
选中管脚 8
GPIO_Pin_9
选中管脚 9
GPIO_Pin_10
选中管脚 10
GPIO_Pin_11
选中管脚 11
GPIO_Pin_12
选中管脚 12
GPIO_Pin_13
选中管脚 13
GPIO_Pin_14
选中管脚 14
GPIO_Pin_15
选中管脚 15
GPIO_Pin_All
选中全部管脚
GPIO_Speed
GPIO_Speed 用以设置选中管脚的速率。Table 184. 给出了该参数可取的值
Table 4. GPIO_Speed 值
GPIO_Speed
描述
GPIO_Speed_10MHz
高输出速率 10MHz
GPIO_Speed_2MHz
高输出速率 2MHz
GPIO_Speed_50MHz
高输出速率 50MHz
GPIO_Mode
GPIO_Mode 用以设置选中管脚的工作状态。Table 185. 给出了该参数可取的值
Table 5. GPIO_Mode 值
GPIO_Speed
解释
描述
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
复用推挽输出
注意:
Table 6. GPIO_Mode 的索引和编码
GPIO 方向
索引
模式
设置
模式代码
GPIO Input
0x00
GPIO_Mode_AIN
0x00
0x00
GPIO_Mode_IN_FLOATING
0x04
0x04
GPIO_Mode_IPD
0x08
0x28
GPIO_Mode_IPU
0x08
0x48
GPIO Output
0x01
GPIO_Mode_Out_OD
0x04
0x14
GPIO_Mode_Out_PP
0x00
0x10
GPIO_Mode_AF_OD
0x0C
0x1C
GPIO_Mode_AF_PP
0x08
0x18
例 /* Configure all the GPIOA in Input Floating mode */
GPIO_InitTypeDef GPIO_InitStructure ; //初始化结构体
GPIO_InitStructure . GPIO_Pin = GPIO_Pin_All ; //定义GPIO口
GPIO_InitStructure . GPIO_Speed = GPIO_Speed_10MHz ; //设置输出速度??
GPIO_InitStructure . GPIO_Mode = GPIO_Mode_IN_FLOATING ; //设置浮空输入
GPIO_Init ( GPIOA , & GPIO_InitStructure ); //初始化函数
Table 7. 函数 GPIO_ReadInputDataBit
函数名
GPIO_ReadInputDataBit
函数原形
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
功能描述
读取 指定端口管脚的输入
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
GPIO_Pin:待读取的端口位 参阅 Section:GPIO_Pin 查阅更多该参数允许取值范围
输出参数
无
返回值
输入端口管脚值
先决条件
无
被调用函数
无
例 /* Reads the seventh pin of the GPIOB and store it in ReadValue variable */ u8 ReadValue ;
ReadValue = GPIO_ReadInputDataBit ( GPIOB , GPIO_Pin_7 );
Table 8. 函数 GPIO_ReadInputData
函数名
GPIO_ReadInputData
函数原形
u16 GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
功能描述
读取 指定的 GPIO 端口输入
输入参数
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输出参数
无
返回值
GPIO 输入数据端口值
先决条件
无
被调用函数
无
例 /*Read the GPIOC input data port and store it in ReadValue variable*/ u16 ReadValue ;
ReadValue = GPIO_ReadInputData ( GPIOC );
GPIO_ReadOutputDataBit
Table 9. 函数 GPIO_ReadOutputDataBit
函数名
GPIO_ReadOutputDataBit
函数原形
u8 GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
功能描述
读取 指定端口管脚的输出
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
GPIO_Pin:待读取的端口位 参阅 Section:GPIO_Pin 查阅更多该参数允许取值范围
输出参数
无
返回值
输出端口管脚值
先决条件
无
被调用函数
无
例 /* Reads the seventh pin of the GPIOB and store it in ReadValue variable */ u8 ReadValue ;
ReadValue = GPIO_ReadOutputDataBit ( GPIOB , GPIO_Pin_7 );
GPIO_ReadOutputData 函数
Table 10. 函数 GPIO_ReadOutputData
函数名
GPIO_ReadOutputData
函数原形
u16 GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
功能描述
读取 指定的 GPIO 端口输出
输入参数
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输出参数
无
返回值
GPIO 输出数据端口值
先决条件
无
被调用函数
无
例 /* Read the GPIOC output data port and store it in ReadValue variable */ u16 ReadValue ;
ReadValue = GPIO_ReadOutputData ( GPIOC );
GPIO_SetBits 函数
Table 11. 函数 GPIO_SetBits
函数名
GPIO_SetBits
函数原形
void GPIO_SetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
功能描述
设置指定的数据端口位
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
GPIO_Pin:待设置的端口位该参数可以取 GPIO_Pin_x(x 可以是 0-15)的任意组合参阅 Section:GPIO_Pin 查阅更多该参数允许取值范围
输出参数
无
返回值
无
先决条件
无
被调用函数
无
例 /* Set the GPIOA port pin 10 and pin 15 */
GPIO_SetBits ( GPIOA , GPIO_Pin_10 | GPIO_Pin_15 );
GPIO_ResetBits
Table 12. GPIO_ResetBits
函数名
GPIO_ResetBits
函数原形
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
功能描述
清除指定的数据端口位
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
GPIO_Pin:待清除的端口位该参数可以取 GPIO_Pin_x(x 可以是 0-15)的任意组合参阅 Section:GPIO_Pin 查阅更多该参数允许取值范围
输出参数
无
返回值
无
先决条件
无
被调用函数
无
例 /* Clears the GPIOA port pin 10 and pin 15 */
GPIO_ResetBits ( GPIOA , GPIO_Pin_10 | GPIO_Pin_15 );
GPIO_WriteBit 函数
Table 13. 函数 GPIO_WriteBit
函数名
GPIO_WriteBit
函数原形
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, u16 GPIO_Pin, BitAction BitVal)
功能描述
设置或者清除指定的数据端口位
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
GPIO_Pin:待设置或者清除指的端口位该参数可以取 GPIO_Pin_x(x 可以是 0-15)的任意组合参阅 Section:GPIO_Pin 查阅更多该参数允许取值范围
输入参数 3
BitVal: 该参数指定了待写入的值该参数必须取枚举 BitAction 的其中一个值 Bit_RESET: 清除数据端口位 Bit_SET: 设置数据端口位
输出参数
无
返回值
无
先决条件
无
被调用函数
无
例 /* Set the GPIOA port pin 15 */
GPIO_WriteBit ( GPIOA , GPIO_Pin_15 , Bit_SET );
GPIO_Write 函数
Table 14. GPIO_Write
函数名
GPIO_Write
函数原形
void GPIO_Write(GPIO_TypeDef* GPIOx, u16 PortVal)
功能描述
向指定 GPIO 数据端口写入数据
输入参数 1
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2
PortVal: 待写入端口数据寄存器的值
输出参数
无
返回值
无
先决条件
无
被调用函数
无
例 /* Write data to GPIOA data port */
GPIO_Write ( GPIOA , 0x1101 );
最后更新:
September 27, 2023
创建日期:
August 3, 2023