stm32学习笔记-GPIO

记录某大二菜入门电子之路~

包括以下几个部分

  • 功能叙述
  • 深度理解IO口的输入输出机制
  • 寄存器详解
  • 库函数分析
  • 库函数代码示例

功能叙述

在这里插入图片描述
每个GPIO有8种模式:
─ 输入浮空
─ 输入上拉
─ 输入下拉
─ 模拟输入
─ 开漏输出:不能输出高电平
─ 推挽式输出
─ 推挽式复用功能
─ 开漏复用功能
在这里插入图片描述
这里有一点要提的是:
复用输入和输入共线,所以复用输入没有独立的GPIO模式,只要在Input模式下使能复用外设的重映射即可,在复用接收数据的时候IDR依然在接受数据。
而复用输出和输出是有路线选择器(structure图上可见)的,故复用输出和输出是两个独立的模式。需要切换线路来选取其中一个。

我们可以大致了解到,除用于模拟量输入以外,施密特在所有模式下均激活,故可知Input模式应该是始终激活的,其他模式其实只是在Input模式依然存在的情况下开启其他模式。所以IDR应该是始终可以读取的。

深度理解IO口的输入输出机制

在这里插入图片描述首先是IO输入输出双用问题,一开始是做1—Wire的一个时序编程的时候突发奇想到GPIO的双向输出输入问题。因为源程序中IO口在频繁的用Init函数更改模式来起到输出和检测输入的作用。
首先我认为,IO口只要时钟使能变进入工作,Init设置为推挽模式输出高电平后并不影响输入,当IO被拉低时依然可以在IDR检测到0。但是Init设为输入输入却会关闭电流?

在1—Wire遇到一种情况:需要将端口拉高释放,然后由另一从机开漏输入,再由端口进行输入检测。很简单是不是?一开始我的步骤是:先推挽输出拉高,再

寄存器详解

在这里插入图片描述
寄存器:
GPIOx_CLR/GPIOx_CHR:CNF位和MODE位,设置模式和速度。
GPIOx_IDR\ODR:输入和输出寄存器,输出寄存器可以按端口写入。
GPIOx_BSR\BSRR:位重置和位重置/挂起寄存器,给对应的位写1可以重置/挂起某个位,即不影响其他位,也可以通过ODR的&=和|=操作做到。
GPIOx_LCKR:不作多解释,通过时序操作激活位锁定。

库函数分析

步骤:
启动APB2时钟
Init初始化
IDR读取ODR输出
调用库函数如图所示
在这里插入图片描述

/**
  * @brief  Initializes the GPIOx peripheral according to the specified
  *         parameters in the GPIO_InitStruct.
  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
  *         contains the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

需要注意的是:
这个初始化函数,GPIO_InitStruct -> GPIO_Pin是初始化这个引脚,不是赋值!!!初始化后其值依然为复位值0。

库函数代码示例

GPIOConfig.h

#ifndef __GPIO_CONFIG_H
#define __GPIO_CONFIG_H

#include "stm32f10x.h"
void GPIO_InitConfig(  GPIO_TypeDef* GPIOx  ,  uint16_t GPIO_Pin  ,  GPIOSpeed_TypeDef GPIO_Speed  ,  GPIOMode_TypeDef GPIO_Mode  );

GPIOConfig.c

#include "GPIOConfig.h"

void GPIO_InitConfig(  GPIO_TypeDef* GPIOx  ,  uint16_t GPIO_Pin  ,  GPIOSpeed_TypeDef GPIO_Speed  ,  GPIOMode_TypeDef GPIO_Mode )
{
	GPIO_InitTypeDef GPIO_InitStruct; 
	GPIO_InitStruct.GPIO_Pin  =  GPIO_Pin;
	GPIO_InitStruct.GPIO_Mode =  GPIO_Mode;
	GPIO_InitStruct.GPIO_Speed  =  GPIO_Speed;
	
	GPIO_Init(  GPIOx ,  &GPIO_InitStruct ); 
}

main.c

#include "GPIOConfig.h"
#include "stm32f10x.h"

int main()
{
	RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOA  ,  ENABLE  );
	GPIO_InitConfig(  GPIOA  ,  GPIO_Pin_0   ,  GPIO_Speed_50MHz  ,  GPIO_Mode_IN_FLOATING  );
}
//此处以A0 50MHZ 悬挂输入 作例子,这样的代码易于维护,避免重复使能,虽然繁琐一些,但是比较好维护

欢迎交流指正~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值