GPIO的内部结构:
在STM32中,所有的外设都是挂载在APB2外设总线上的,GPIO内包含了寄存器和驱动器,内核通过APB2总线对寄存器进行读写,寄存器的每一位对应每一个引脚。驱动器是用来增强GPIO驱动能力的
GPIO位的内部结构:
在下结构图中,信号从右边的I/0引脚输入,通过内部的上拉或下拉开关进行到TTL肖特基触发器处,模拟量信号在TTL肖特基触发器前输入到模拟输入端口处。 电压经过TTL肖特基进行整形处理(施密特触发电路是一种波形整形电路,当任何波形的信号进入电路时,输出在正、负饱和之间跳动,产生方波或脉波输出。)后送到服用功能输入或者输入信号寄存器中作为数字信号输入。
输出部分由输出数据寄存器和片上外设来控制(如果想对输出数据寄存器的某一位进行操作,可以设置“位设置/清除寄存器”),输出数据经过输出控制器外接一个P-MOS和N-MOS,通过设置将MOS管接到VDD或者VSS可以选择推挽、开漏、关闭三种输出方式。
使用方式举例:
在开漏模式下,P-MOS管关闭,输出控制器输出1,N-MOS断开,输出IO口为高阻态模式,当输出控制器输出0,N-MOS导通,输出接到VSS,输出IO口为低电平模式。开漏模式下高电平没有驱动能力,当输出高电平时由外部的上拉电阻拉高。
GPIO模式:
GPIO可以配置成以下8种模式:
GPIO寄存器:
GPIO端口寄存器,每一个端口的模式由4位进行配置,16个端口就需要64位来控制,所以配置寄存器有2个分别是端口配置低寄存器和端口配置高寄存器(每个寄存器是32位的)
端口输入数据寄存器:低16位对应16个引脚,高16位没有使用。
端口输出数据寄存器:低16位对应16个引脚,高16位没有使用。
端口位设置/清除寄存器:高16位是进行清除的,低16位是进行位设置的。
端口位清除寄存器:和端口位设置/清除寄存器的高16位功能相同,是为了方便操作而存在的。
端口配置锁定寄存器:对端口的配置进行锁定,防止意外更改
通过库函数方式实现GPIOC PIN13 LED闪烁:
新建工程模板在之前的笔记中有记录。
在新建工程的main中开始编写代码,使LED GPIOC PIN13闪烁:
#include "stm32f10x.h" //添加头文件
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //1.使用RCC开启GPIO的时钟
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //填写结构体参数
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //填写结构体参数
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //填写结构体参数
GPIO_Init(GPIOC, &GPIO_InitStructure); //2.使用GPIO_Init函数初始化GPIO
// GPIO_SetBits(GPIOC, GPIO_Pin_13); //3.使用输出或者输入函数控制GPIO
// GPIO_ResetBits(GPIOC, GPIO_Pin_13);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
while(1)
return 0;
}
在这个功能中,我们使用了RCC和GPIO两个外设,在Library库函数中可以找到stm32f10x_rcc.h和gpio这两个函数:
打开RCC.h文件,可以找到以下外设时钟控制函数:
打开gpio.h:
使用GPIO_SetBits函数来设置GPIO的状态,跳转到GPIO_SetBits函数定义中描述如下,参数1为选择GPIO口,参数2为IO口的哪一位:
如果想要设置GPIOC的13位为高,则代码为:GPIO_SetBits(GPIOC, GPIO_Pin_13);
也可以使用函数void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);来设置GPIO,在这个函数中第3个参数为BitAction,查看介绍如下:
那么设置端口为13,则编写代码如下:GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
接下来,添加延时函数(设置LED闪烁的效果):
将延时函数的文件存放目录添加到项目头文件路径下:
添加延时函数头文件:
调用延时函数实现LED灯闪烁的效果:
#include "stm32f10x.h" //添加头文件
#include "Delay.h"
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //1.使用RCC开启GPIO的时钟
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //填写结构体参数
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //填写结构体参数
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //填写结构体参数
GPIO_Init(GPIOC, &GPIO_InitStructure); //2.使用GPIO_Init函数初始化GPIO
// GPIO_SetBits(GPIOC, GPIO_Pin_13); //3.使用输出或者输入函数控制GPIO
// GPIO_ResetBits(GPIOC, GPIO_Pin_13);
// GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
while(1)
{
GPIO_SetBits(GPIOC, GPIO_Pin_13);
Delay_ms(300);
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
Delay_ms(300);
}
}
实现GPIOA PIN0-7 LED流水灯的效果:
#include "stm32f10x.h" //添加头文件
#include "Delay.h"
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //1.使用RCC开启GPIO的时钟
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,设置为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //需要设置的GPIO引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO口的翻转速度
GPIO_Init(GPIOA, &GPIO_InitStructure); //2.使用GPIO_Init函数初始化GPIO,将结构体变量传递给初始化函数
while(1)
{
/*使用GPIO_Write,同时设置GPIOA所有引脚的高低电平,实现LED流水灯*/
GPIO_Write(GPIOA,0X0001); //0x0000 0000 0000 0001 采用高电平点亮的方式 PA0引脚为高电平,其他引脚均为低电平
Delay_ms(100);
GPIO_Write(GPIOA,0X0002); //0x0000 0000 0000 0010
Delay_ms(100);
GPIO_Write(GPIOA,0X0004); //0x0000 0000 0000 0100
Delay_ms(100);
GPIO_Write(GPIOA,0X0008); //0x0000 0000 0000 1000
Delay_ms(100);
GPIO_Write(GPIOA,0X0010); //0x0000 0000 0001 0000
Delay_ms(100);
GPIO_Write(GPIOA,0X0020); //0x0000 0000 0010 0000
Delay_ms(100);
GPIO_Write(GPIOA,0X0040); //0x0000 0000 0100 0000
Delay_ms(100);
GPIO_Write(GPIOA,0X0080); //0x0000 0000 1000 0000
Delay_ms(100);
}
}