STM32&入门GPIO

        如果你接触过STC89C51,那么你大概率会觉得IO口根本不是一个需要学习的东西。但事实上并不是这样。在51里,所有的IO口的内存地址可以被直接映射在变量上。能出现sbit一个引脚直接赋值这样的便捷操作。但在32中不同,对于IO口由于有各种对应的外设驱动,所以很多地方的设计和51是大不相同的,这也是为什么要把GPIO当作一个外设来学习的原因。
 

目录

GPIO的工作模式

GPIO寄存器

GPIO的常用库函数

一个让你入门的项目


GPIO的工作模式

从大类来讲,分为输入和输出两种大类。输入模式就是使得外接的其他设备将对应的电平输入进来,输出则是通过寄存器向外界输出电平。
        其中输入有:
        上拉输入        下拉输入
        模拟输入        浮空输入

其中上拉下拉很好理解,就是在默认没有电平输入的情况下,上拉会保持在高电平下拉则保持在低电平。
        输出有:
        开漏输出        推挽输出
        复用推挽输出        复用开漏输出

这里区别比较大,推挽输出是最普通最常用的输出模式。开漏输出则只能输出低电平
复用推挽输出比较重要,是指:此时IO口的电平完全受外部设施的控制,即外部可以任意操纵电平高低。这里就反推出了另一个事情:IO口平常是受ODR控制的。

GPIO的构造:

GPIO寄存器

先预览以下:
端口配置低寄存器(GPIOx_CRL) (x=A..E) 
端口配置高寄存器(GPIOx_CRH) (x=A..E)
端口输入数据寄存器(GPIOx_IDR) (x=A..E)
端口输出数据寄存器(GPIOx_ODR) (x=A..E)
端口位清除寄存器(GPIOx_BRR) (x=A..E)
复用功能I/O和调试配置(AFIO)

其实这些寄存器的功能也很直白,由于一部分人学习的是寄存器式的32配置模式,所以我这里也尽可能的详细一些。


端口配置低寄存器(GPIOx_CRL) (x=A..E) &端口配置高寄存器(GPIOx_CRH) (x=A..E)
先看图:

如果你图也懒得看,那么知道这一句话就行:CNFx位用于控制该IO口的工作魔术(包括输入输出所有模式)MODx位用于控制其对应的HZ。那为什么分低位和高位?一般来说一组GPIO是16个,这里一共32位,四位配置一个IO口,所以一个寄存器只能控制8个IO口。自然就需要分低位和高位两个控制。


端口输入数据寄存器(GPIOx_IDR) (x=A..E)端口输出数据寄存器(GPIOx_ODR) (x=A..E)
图都不用看,一组用来读取IO口电平,一组用来输入。非常直白,比你和女主播聊天还直白。
算啦,还是给你上个图吧:


端口位清除寄存器(GPIOx_BRR) (x=A..E)
这个寄存器就有点特殊了,乍一看感觉p用都没有,但实际上当你的项目到达一定的规模,想要保证你的项目正常运行,使用这个可以说是必不可少的。
它是什么用呢?首先,它的功能很直白,就是将对应的位RESET回0。你肯定要问了:
                那我直接用输入寄存器写0不行?   哎,还真不行。

为什么捏?因为当我们要写入的时候,是这样的一个步骤:

1.读取寄存器数据---2.改变某位数据---3.输入数据

看上去没有任何破绽,但如果你有基础,你就之到在读取后输入前的任意时间段假设来了一个中断将寄存器中的某一位改变了,然而你这时的主线程并不知道,最终会将该位置上改变前的数值赋值回去。此时你爹程序一定会出错。

那为啥用这个就没事儿捏?
因为这个寄存器它不是读一整个寄存器的值,而是单单读取你要改变的那一位。


复用功能I/O和调试配置(AFIO)

这个是用来重映射引脚功能的。
 

GPIO的常用库函数

注意:这里的信息对应的是HAL库版本的API
一般对于初学者来说,GPIO常用的函数有这些:

它们对应的函数功能也非常直白:
void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init):初始化GPIO口
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin):读取GPIO口的电平数值
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin):反转当前GPIO口的对应电平。
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState):对当前GPIO口进行电平写入。
 

一个让你入门的项目

什么项目呢?很简单,做一个按键控制小灯亮灭的项目:
其中核心代码必然会涉及到这上面的常用API

步骤也很简单,创建一个key.c和led.c,对于两个要控制的GPIO口进行初始化,然后再mian中不断检测按键是否被按下即可。若按下则亮,否则灭。
key.c:

#include "key.h"
#include "delay.h"
#include "sys.h"

void key_init(void){
	GPIO_InitTypeDef gpio_init;
	
	gpio_init.Mode = GPIO_MODE_INPUT;
	gpio_init.Pin = GPIO_PIN_0|GPIO_PIN_1;
	gpio_init.Pull = GPIO_PULLUP;
	gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
	
	__HAL_RCC_GPIOA_CLK_ENABLE();
	HAL_GPIO_Init(GPIOA, &gpio_init);
	
	
}

uint8_t key_scan0(void){
	
	if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){
		delay_ms(10);
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){
			while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET);
			return 1;
		}
	}
	return 0;
	    
}

led.c:

void led_init(){
	GPIO_InitTypeDef gpio_init;
	
	gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
	gpio_init.Pin = GPIO_PIN_8;
	gpio_init.Pull = GPIO_PULLUP;
	gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
	
	__HAL_RCC_GPIOB_CLK_ENABLE();
	HAL_GPIO_Init(GPIOB, &gpio_init);
		
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
}

void led_on(){
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);

}

void led_off(){
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);

}

void led_Toggle()
{
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
}

主函数部分太简单了就是在while里循环检测就我就不赘述了。
认真敲玩这个项目,可以最快最有效的让你记住这些个API有啥用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值