STM32F4应用-GPIO
1.前言
学习开发板的第一个实验必定是点灯,这其实就是涉及到GPIO的应用。
以STM32F407ZGT6为例子。
2. 点灯的配置
灯能亮起来一般需要的步骤有初始化GPIO,操作IO。
2.1初始化GPIO
初始化GPIO包括使能GPIO时钟和配置IO属性,一般用下面代码。
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能IO时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9//GPIOF9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO
2.1.1 使能GPIO时钟
首先一个问题是为什么需要使能IO时钟?
从《STM32F4的基础介绍》这篇文章可知,stm32F4有多个时钟源,不同的外设对应不同的时钟(省功耗),在用外设之前需要使能时钟,否则不能使用。
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能IO时钟
上面一句话表示通用的GPIO时钟挂在AHB总线上。
2.1.2 配置IO
配置IO包括
- 选择第几个IO
- 输入输出端口模式
- 配置IO的速度
- 配置端口模式下的类型,如输出模式下的推挽模式
- 设置端口的上下拉
- 初始化IO将其赋值到GPIOA-G的某个中
2.2 操作IO
对IO进行复位和设置的操作,使得灯亮灭。
GPIO_ResetBits(GPIOF,GPIO_Pin_9); //LED0 对应引脚 GPIOF.9 拉低
GPIO_SetBits(GPIOF,GPIO_Pin_10); //LED1 对应引脚 GPIOF.10 拉高
delay_ms(500); //延时 500ms
GPIO_SetBits(GPIOF,GPIO_Pin_9); //LED0对应引脚GPIOF.0拉高,灭 等同LED0=1;
GPIO_ResetBits(GPIOF,GPIO_Pin_10); //LED1 对应引脚 GPIOF.10 拉低,亮 等同 LED1=0;
delay_ms(500); //延时 500ms
3. GPIO特性
3.1 引脚特性
STM32F407ZGT6有114个IO引脚,分为7组,A-G,另加PH0,PH1(可复用晶振输入引脚).
大部分IO有复用功能,FT表示IO口可承受5V电压。
3.2 工作方式
根据2.1.2的介绍势必会产生几个问题:端口模式有几种,涉及哪些寄存器,IO的速度有几种等,下面进行介绍。
3.2.1 配置寄存器
有4个32位配置寄存器
- GPIOx_MODER模式选择
- GPIOx_OTYPER输出类型
- GPIOx_OSPEEDR速度选择
- GPIOx_PUPDR上下拉
当然还有2个16位的数据寄存器GPIOx_IDR,GPIOx_ODR,还有一个32位置位复位寄存器BSRR.IDR和ODR可读可写.虽然都是对位操作,一般写的时候用BSRR,因为用ODR先得读再写,浪费时间。
3.2.2 工作模式
从模式寄存器的定义可知,有四种工作模式:
- 输出
- 输入
- 复用,复用其他功能如uart等
- 模拟,ADC/DAC
而在不同的模式下,引脚又有几种状态
输入模式:
- 输入浮空
- 输入上拉
- 输入下拉
输出模式:
- 开漏输出(带上拉或者下拉)
- 推挽式输出(带上拉或者下拉)
复用功能:
- 推挽式复用功能(带上拉或者下拉)
- 开漏式复用功能(带上拉或者下拉)
模拟功能
寄存器的配置可以总结如下表
3.2.2 工作速度
GPIO输出输出速度有以下几种,通过设置GPIOx_OSPEEDR:
- 2MHZ
- 25MHz
- 50MHz
- 100MHz(30pF)/80MHz(15pF)
这里只对输出有用,这里的速度指的是GPIO输出电平翻转的速度。
4.增加功能函数
4.1 在main里增加
要实现什么功能,可以直接在main里增加,在while1里增加功能语句。不过在此之前需要对函数进行声明。
void LED_Init(void);//声明
int main(void)
{
LED_Init(); //初始化 LED 端口
while (1)
{
GPIO_ResetBits(GPIOF,GPIO_Pin_9); //LED0 对应引脚 delay_ms(500); //延时 500ms
}
}
//定义
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF 时钟
//GPIOF9,F10 初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0 和 LED1 对应 IO 口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO
//GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10 设置高,灯灭
GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);
}
4.2 新建函数
增加新函数,如LED.c,以及对应得头文件,放在之前建立的文件夹里,如app。
.c文件一般放的是函数定义,.h文件是声明。
.c参考内容如下,先包含头文件名,再定义函数。
#include"LED.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF 时钟
//GPIOF9,F10 初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0 和 LED1 对应 IO 口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO
//GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10 设置高,灯灭
GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);
}
.h参考内容如下,先定义头文件名,再声明函数。
#ifndef __LED_H
#define __LED_H
#include "stm32f4xx.h"
void LED_Init(void);
#endif
然后再在main函数中使用,只用加入对头文件的引用,加入#include"LED.h"就行。
参考文献
《STM32F4开发指南-库函数版本-V1.2》
《STM32F4xx中文参考手册》