STM32F4 每组通用 I/O 端口包括(10个)
4 个 32 位配置寄存器(MODER、 OTYPER、 OSPEEDR, PUPDR)、
2 个 32 位数据寄存器(IDR 和 ODR)
1 个 32 位置位/复位寄存器 (BSRR)、
1 个 32 位锁定寄存器 (LCKR)
2 个 32 位复用功能选择寄存器(AFRH 和 AFRL)
1、 输入浮空
2、 输入上拉
3、 输入下拉
4、 模拟输入
5、 开漏输出
当Vin没有电流,Q5断开时,LED亮。当Vin流入电流,Q5导通时,LED灭。
相当于引脚的输出是对地加了一个电子开关。
输出高电平是开关断开,此时引脚不能提供电流输出,需要高电平要在外面加上拉电阻。
输出低电平是开关闭合,此时引脚能提供电流,使引脚的电平变低。
6、 推挽输出
(英语:Push–pull output)
即推拉,指既可以输出低电平,也可以输出高电平,可以直接驱动功耗不大的数字器件。

场效应管是电压控制型元器件,只要对栅极施加电压,DS就会导通。
类似三极管,上面NPN,下面PNP,只是输入阻抗非常大,没有电路,不会烧坏mcu
7、 推挽式复用功能
8、 开漏式复用功能
GPIOx(STM32F4 最多有 9 组 IO,分别用大写字母表示,即 x=A/B/C/D/E/F/G/H/I)
每组 IO 下有 16 个 IO 口,该寄存器共 32 位,所以每 2 个位控制 1个 IO
配置寄存器 4 个 32 位(MODER、 OTYPER、 OSPEEDR, PUPDR)
MODER
OTYPER
该寄存器低 16 位有效,每一个位控制一个 IO 口,复位后,该寄存器值均为 0
0 输出推挽
1 输出开漏
OSPEEDR
10 50MHz
11 100MHz
PUPDR
01上拉
10下拉
数据寄存器2 个 32 位(IDR 和 ODR)
ODR
设置某个 IO 输出低电平(ODRy=0)还是高电平(ODRy=1)
IDR
读取某个 IO 的电平
例子
比如,我们要设置 PORTC 的第 12 个 IO(即 PC11) 为推挽输出,速度为 100Mhz, 不带上
下拉, 并输出高电平。代码如下:
RCC->AHB1ENR|=1<<2; //使能 PORTC 时钟
GPIOC->MODER&=~(3<<(112)); //先清除 PC11 原来的设置
GPIOC->MODER|=1<<(112); //设置 PC11 为输出模式
GPIOC->OTYPER&=~(1<<11) ; //清除 PC11 原来的设置
GPIOC->OTYPER|=0<<11; //设置 PC11 为推挽输出
GPIOC-> OSPEEDR&=~(3<<(112)); //先清除 PC11 原来的设置
GPIOC-> OSPEEDR|=3<<(112); //设置 PC11 输出速度为 100Mhz
GPIOC-> PUPDR&=~(3<<(112)); //先清除 PC11 原来的设置
GPIOC-> PUPDR|=0<<(112); //设置 PC11 不带上下拉
GPIOC->ODR|=1<<11; //设置 PC11 输出 1(高电平)
又比如,我们要设置 PORTE 的第 4 个 IO(即 PE3)为带上拉的输入。代码如下:
RCC->AHB1ENR|=1<<4; //使能 PORTE 时钟
GPIOE->MODER&=~(3<<(32)); //先清除 PE3 原来的设置
GPIOE->MODER|=0<<(32); //设置 PE3 为输入模式
GPIOE-> PUPDR&=~(3<<(32)); //先清除 PE3 原来的设置
GPIOE-> PUPDR|=1<<(32); //设置 PE3 上拉
GPIO_Set函数
//GPIO 通用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0X0000~0XFFFF,位设置,每个位代表一个 IO,
//第 0 位代表 Px0,第 1 位代表 Px1,依次类推.比如 0X0101,代表同时设置 Px0 和 Px8.
//MODE:0~3;模式选择,0,输入(系统复位默认状态);1,普通输出;2,复用功能;3,模拟输入.
//OTYPE:0/1;输出类型选择,0,推挽输出;1,开漏输出.
//OSPEED:0~3;输出速度设置,0,2Mhz;1,25Mhz;2,50Mhz;3,100Mh.
//PUPD:0~3:上下拉设置,0,不带上下拉;1,上拉;2,下拉;3,保留.
//注意:在输入模式(普通输入/模拟输入)下,OTYPE 和 OSPEED 参数无效!!
RCC->AHB1ENR|=1<<2; //使能 PORTC 时钟
GPIO_Set(PORTC,1<<11,1,0,3,0); //设置 PC11 推挽输出, 100Mhz,不带上下拉
//GPIO_Set(PORTC,PIN11,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_NONE); //设置 PC11 推挽输出, 100Mhz,不带上下拉
GPIOC->ODR|=1<<11; //设置 PC11 输出 1(高电平)
复用功能选择寄存器2 个 32 位(AFRH 和 AFRL)
其中 AFRL 控制0~7 这 8 个 IO 口, AFRH 控制 8~15 这 8 个 IO 口
比如,我们要用 PC11 的复用功能为: SDIO_D3。因为 11 脚是由 AFRH[15:12]控制,且属
于 SDIO 功能复用,所以要选择 AF12。即设置 AFRH[15:12]=AF12, 代码如下:
RCC->AHB1ENR|=1<<2; //使能 PORTC 时钟
GPIO_Set(PORTC,PIN11, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_100M,
GPIO_PUPD_PU); //设置 PC11 复用输出, 100Mhz,上拉
GPIOC->AFR[1]&= ~(0X0F<<12; //清除 PC11 原来的设置
GPIOC->AFR[1]|= 12<<12; //设置 PC11 为 AF12
//在 MDK 里面, AFRL 和 AFRH 被定义成 AFR[2],其中 AFR[0]代表 AFRL, AFR[1]代表 AFRH。
GPIO_AF_Set 函数
//GPIO 复用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0~15,代表 IO 引脚编号.
//AFx:0~15,代表 AF0~AF15.
//AF0~15 设置情况(这里仅是列出常用的,详细的请见 407 数据手册,56 页 Table 7):
//AF0:MCO/SWD/ SWCLK/RTC AF1:TIM1/2; AF2:TIM3~5; AF3:TIM8~11
//AF4:I2C1~I2C3; AF5:SPI1/SPI2; AF6:SPI3; AF7:USART1~3;
//AF8:USART4~6; AF9;CAN1/2/TIM12~14 AF10:USB_OTG/USB_HS AF11:ETH
//AF12:FSMC/SDIO/OTG/HS AF13:DCIM AF14: AF15:EVENTOUT
设置 PC11 为
SDIO_D3,代码如下:
RCC->AHB1ENR|=1<<2; //使能 PORTC 时钟
GPIO_Set(PORTC,PIN11, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_100M,
GPIO_PUPD_PU); //设置 PC11 复用输出, 100Mhz,上拉
GPIO_AF_Set(GPIOC,11,AF12); //设置 PC11 为 AF12
IO 电平兼容性问题
STM32F4 的绝大部分 IO 口,都兼容 5V,至于到底哪些是兼容 5V 的,请看 STM32F40x 的数据手册(注意是数据手册,不是中文参考手册!!),见表: Table 6 STM32F40x pin and ball definitions,凡是有 FT/FTf 标志的,都是兼容 5V电平的 IO 口,可以直接接 5V 的外设(注意:如果引脚设置的是模拟输入模式,则不能接 5V! ),凡是不是 FT/FTf 标志的,大家都不要接 5V 了,可能烧坏 MCU。
RCC->AHB1ENR|=1<<5;//使能 PORTF 时钟
/* ABCDEF
012345
*/
GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,
GPIO_SPEED_100M,GPIO_PUPD_PU); //PF9,PF10 设置
#define LED0 PFout(9) // DS0
#define LED1 PFout(10) // DS1
#define LED0 (1<<9) //led0 PF9
#define LED1 (1<<10) //led1 PF10
#define LED0_SET(x) GPIOF->ODR=(GPIOF->ODR&~LED0)|(x ? LED0: 0)
#define LED1_SET(x) GPIOF->ODR=(GPIOF->ODR&~LED1)|(x ? LED1: 0)
//通过 LED0_SET(0)和 LED0_SET(1)来控制 PF9 的输出 0 和 1。
/*
//(GPIOF->ODR&~LED0) 把位9设为0,不影响其他位
// |1 把该位设为1,不影响其他位
// |0 完全不影响
if(x==1)
{
LED0
}
else
{
0
}
*/
Code:表示程序所占用 FLASH 的大小(FLASH)。
RO-data:即 Read Only-data, 表示程序定义的常量,如 const 类型(FLASH)。
RW-data:即 Read Write-data, 表示已被初始化的全局变量(SRAM)
ZI-data:即 Zero Init-data, 表示未被初始化的全局变量(SRAM)
程序的大小是FLASH的大小,即 Code 和 RO-data 之和
STLINK 进行在线调试(需
要先下载代码),单步查看代码的运行, STM32F4 的在线调试方法介绍,参见: 4.2 节。