1 GPIO功能模式  

GPIO有八种工作模式


 1、输入浮空  -该模式可以用于按键检测等场景。

2、输入上拉  -上拉电阻导通,施密特触发器打开,输出被禁止。使用内部电阻(内部电阻较大)为“弱上拉”不适合做电流型驱动空闲时,IO呈现高电平

3、输入下拉  -下拉电阻导通,施密特触发器打开,输出被禁止。使用内部电阻(内部电阻较大)为“弱下拉”不适合做电流型驱动空闲时,IO呈现低电平

4、模拟功能  -上下拉电阻断开,施密特触发器关闭,双 MOS管也关闭。上下拉电阻断开,施密特触发器关闭,双 MOS管也关闭。

特点:专门用于模拟信号输入或输出,如:ADC和DAC

5、开漏输出  -STM32的开漏输出模式是数字电路输出的一种,从结果上看它只能输出低电平 Vss或者高阻态,常用于 IIC通讯(IIC_SDA)或其它需要进行电平转换的场景。 

特点:不能输出高电平, 必须有外部(或内部)上拉才能输出高电平(F1)

6、推挽输出  -STM32的开漏输出模式是数字电路输出的一种,从结果上看它只能输出低电平 Vss或者高阻态,常用于 IIC通讯(IIC_SDA)或其它需要进行电平转换的场景。

特点:可输出高低电平,  驱动能力强

7、开漏式复用功能  -STM32的开漏输出模式是数字电路输出的一种,从结果上看它只能输出低电平 Vss或者高阻态,常用于 IIC通讯(IIC_SDA)或其它需要进行电平转换的场景。特点:

1、不能输出高电平,必须有外部(或内部)上拉才能输出高电平

2、由其他外设控制输出

8、推挽式复用功能 -复用功能介绍请查看开漏式复用功能,结构分析请参考推挽输出模式(SPI的SCK)

特点:

1、可输出高低电平, 驱动能力强

2、由其他外设控制输出

图13.1.2.1详细查STM32F103开发指南

GPIO功能模式介绍_#include


1,STM32工作电压范围?

2 V ≤ VDD ≤ 3.6 V

2,GPIO识别电压范围?

COMS端口:-0.3V ≤ VIL ≤ 1.164V

                  1.833V ≤ VIH ≤ 3.6V

3,GPIO输出电流?

单个IO,最大25mA

TTL触发器(整型为方波)

GPIO功能模式介绍_寄存器_02

P-MOS&N-MOS管

GPIO功能模式介绍_#include_03

G:栅极:G=1,N-MOS导通;G=0,P-MOS导通

D:漏极

P:Vgs<0,导通

N:Vgs>0,导通

总结:F4/F7/H7系列和F1系列的GPIO差异点?

1,F1在输出模式,禁止使用内部上下拉,F4/F7/H7在输出模式,可以使用内部上下拉;

2,不同系列IO翻转速度可能不同;

2.GPIO寄存器介绍

F1系列)GPIO通用寄存器GPIOX_yyy

CRL

CRH

IDR

ODR

BSRR

BRR

LCKR

配置工作模式,输出速度



输入数据

输出数据

设置ODR寄存器的值

F4之后没有这个寄存器,考虑代码兼容性的话不建议使用

配置锁定,用得不多

F4/F7/H7系列)GPIO通用寄存器GPIOX_yyy


MODER

OTYPER

OSPEEDR

PUPDR

IDR

ODR

BSRR

LCKR


设置模式

设置输出

类型

设置输出

速度

设置上下拉电阻

输入数据

输出数据

设置ODR寄存器值

配置锁定,用得不多


命名注:(F1系列)GPIO通用寄存器GPIOX_yyy              A端口类

                   (F4/F7/H7系列)GPIO通用寄存器GPIOX_yyy   B端口类

A端口配置寄存器(GPIOx_CRL 和 GPIO_x_CRH)

这两个寄存器都是 GPIO口配置寄存器,不过 CRL控制端口的低八位(Px0-Px7的IO口),CRH控制端口的 高八位(Px8-Px15的IO口)。

GPIO功能模式介绍_#include_04


GPIO功能模式介绍_寄存器_05

A8种工作模式对应的配置

2个配置寄存器就是用来配置 GPIO的相关工作模式和工作速度,它们通过不同的配置组合方法,就决定我们所说的 8种工作模式。

GPIO功能模式介绍_寄存器_06

输入上拉/下拉电阻通过ODR寄存器来设置

A端口输出入数据寄存器(IDR)

GPIO功能模式介绍_初始化_07

用于判断IO引脚的电平

A端口输出数据寄存器(ODR)

该寄存器用于控制 GPIOx的输出高电平或者低电平,寄存器描述如图 13.1.3.3所示。

GPIO功能模式介绍_初始化_08

用于设置IO引脚输出的电平

A端口置位/复位寄存器(BSRR)

该寄存器也用于控制 GPIOx的输出高电平或者低电平,寄存器描述如图 13.1.3.4所示

GPIO功能模式介绍_初始化_09

用于设置ODR寄存器

B端口模式寄存器(MODER)

GPIO功能模式介绍_#include_10

用于设置模式

B端口输出类型寄存器(OTYPER)

GPIO功能模式介绍_#include_11

用于设置输出类型

B端口输出速度寄存器(OSPEEDR)

GPIO功能模式介绍_#include_12

用于设置IO的输出速度

B端口上拉/下拉寄存器(PUPDR)

GPIO功能模式介绍_寄存器_13

用于设置上拉/下拉电阻

B8种工作模式对应的配置

GPIO功能模式介绍_初始化_14


  • B端口输入数据寄存器(IDR)

GPIO功能模式介绍_寄存器_15

用于读取IO引脚的电平

B端口输出数据寄存器(ODR)

GPIO功能模式介绍_寄存器_16

用于设置IO引脚输出的电平

B端口置位/复位寄存器(BSRR)

GPIO功能模式介绍_寄存器_17

用于设置ODR寄存器

思考

ODR和BSRR寄存器控制输出有什么区别?

GPIOB->ODR|= 1 << 3;                   /* PB3= 1 */
GPIOB->BSRR= 0x00000008; /* PB3 = 1 */
ODR修改:读à改à写
BSRR修改:


ST官方给的答案:使用ODR,在读和修改访问之间产生中断时,可能会发生风险;BSRR则无风险

总的来说,建议大家使用BSRR寄存器控制输出!


通用外设驱动模型(四步法)(掌握)

初始化

时钟设置,参数设置,OI设置,中断设置(开中断,设NVIC)

读函数(可选)

从外设读取数据

写函数(可选)

往外设写入数据

中断服务函数(可选)

根据中断标志,处理外设各种中断事务(可选)

  • 时钟设置    __HAL_RCC_GPIOx_CLK_ENABLE()
  • 设置工作模式   HAL_GPIO_Init()
  • 设置输出状态(可选) HAL_GPIO_WritePin HAL_GPIO_TogglePin()
  • 读取输入状态(可选) HAL_GPIO_ReadPin()

HAL库驱动函数

主要寄存器

功能

__HAL_RCC_GPIOx_CLK_ENABLE()


F1RCC_APB2ENR

F4RCC_AHB1ENR

F7RCC_AHB1ENR

H7RCC_AHB4ENR

开启GPIO时钟

HAL_GPIO_Init(...)

F1CRLCRHODR

F4/F7/H7MODEROTYPER

                 OSPEEDRPUPDR

初始化GPIO

HAL_GPIO_WritePin(...)

BSRR

控制IO输出高/低电平

HAL_GPIO_TogglePin(...)

BSRR

每次调用IO输出电平翻转一次

HAL_GPIO_ReadPin(...)

IDR

读取IO电平



3.点亮一个LED灯

0805贴片发光二极管参考:

红色:压降范围1.82~1.88V

             电流范围5~8mA

绿色:压降范围1.75~1.82V

             电流范围3~5mA

蓝色:压降范围1.8~2.2V

             电流范围8~10mA

GPIO功能模式介绍_寄存器_18

不算LED内阻,电流I=(VCC-压降)/R电阻=(3.3-1.82)/510 =2.9mA

电流微低影响的是亮度

点亮LED灯代码模块

/*----------点亮LED灯代码模块(led.c)--------*/
/*----------------------------------------*/
#include "./BSP/LED/led.h"
void led_init(void)
{
GPIO_InitTypeDef gpio_init_struct;

__HAL_RCC_GPIOB_CLK_ENABLE();

gpio_init_struct.Pin = GPIO_PIN_5;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &gpio_init_struct);

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
}
/*----------点亮LED灯代码模块(led.h)--------*/
/******************************************/
#ifndef __LED_H
#define __LED_H

#include "./SYSTEM/sys/sys.h"

void led_init(void);

#endif
/*----------点亮LED灯代码模块(main.c)--------*/
/*******************************************/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"


int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
while(1)
{
/******************方法一*******************/
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); /* PB5置1 */
// delay_ms(200);
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); /* PB5置0 */
// delay_ms(200);
/******************方法二*******************/
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);//每次调用IO输出电平翻转一次
delay_ms(200);
}
}

按键控制LED灯模块
/*----------按键控制LED灯代码模块(main.c)--------*/
/********************************** *********/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LED/key.h"

int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
key_init(); /* KEY初始化 */
while(1)
{
delay_ms(200); //消抖
if(key_scan())
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
}
else
{
delay_ms(10);
}
}
}
/*----------按键控制LED灯代码模块(key.c)--------*/
/**********************************************/
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"

void key_init(void)//按键初始化函数
{
GPIO_InitTypeDef gpio_init_struct; //

__HAL_RCC_GPIOE_CLK_ENABLE();

gpio_init_struct.Pin = GPIO_PIN_2;
gpio_init_struct.Mode = GPIO_MODE_INPUT;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);

}
uint8_t key_scan(void)//按键扫描函数
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5)==0) //读取按键电平
{
delay_ms(10); //消抖
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5)==0)//等待按键松开
{
return 1; //返回值1
}
}
return 0; //返回值0
}


/*----------按键控制LED灯代码模块(key.h)--------*/
/**********************************************/
#ifndef __KEY_H
#define __KEY_H

#include "./SYSTEM/sys/sys.h"

void key_init(void);
uint8_t key_scan(void);

#endif

按键的LED初始化同“点亮一个LED灯”!!!




















//初始化PB1为输出.并使能时钟       
//LED IO初始化
/*下面主函数是使用HAL库函数实现控制IO口输出*/
#include "led.h"
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
delay_init(72); //初始化延时函数
LED_Init(); //初始化LED

while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); //LED0对应引脚PB5拉低,亮,等同于LED0(0)
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //LED1对应引脚PE5拉高,灭,等同于LED1(1)
delay_ms(500); //延时500ms
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //LED0对应引脚PB5拉高,灭,等同于LED0(1)
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); //LED1对应引脚PE5拉低,亮,等同于LED1(0)
delay_ms(500); //延时500ms
}
}



#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
/*下面主函数是使用HAL库函数实现控制IO口输出*/

int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
delay_init(72); //初始化延时函数
LED_Init(); //初始化LED

while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); //LED0对应引脚PB5拉低,亮,等同于LED0(0)
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //LED1对应引脚PE5拉高,灭,等同于LED1(1)
delay_ms(500); //延时500ms
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //LED0对应引脚PB5拉高,灭,等同于LED0(1)
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); //LED1对应引脚PE5拉低,亮,等同于LED1(0)
delay_ms(500); //延时500ms
}
}