基于标准库的STM32——GPIO


前言

本系列是本人基于B站up主江协科技的STM32入门教程的学习笔记

一、STM32F103C8T6系统结构

1、 AHB系统总线(先进高性能总线)用于挂载主要的外设,挂载的一般是最基本的或者性能比较高的外设。

2、AHB和APB的总线协议、总线速度、还有数据传送格式的差异 ,所以中间需要通过两个桥接来完成数据的转换和缓存。

3、性能:AHB > APB2 > APB1

系统框图:
系统框图

二、GPIO

1.GPIO基本结构

1、根据芯片的数据手册可知:GPIO挂载于APB2总线上。

2、寄存器是特殊存储器,内核可以通过APB2总线对寄存器进行读写,且寄存器为32位,只有低 16位对应有端口。

3、驱动器用来增加信号驱动能力。
GPIO基本结构

2.GPIO位结构

1、VDD接3.3V,若输入比3.3V高,则上面的二极管导通,起保护作用。

2、VSS接0V,若输入为负电压,则下面的二极管导通,端口不会从内部电路汲取电流。

3、施密特触发器(TTL)通过两个比较阈值来进行判断,对信号进行整形。

4、模拟输入,接收模拟量;复用功能输入,接收数字量

5、 位设置 / 清除寄存器可以单独操作输出寄存器的某一位,而不影响其它位。

6、若想对输出寄存器的某一位置1,对位设置寄存器的对应位写1;
若想对输出寄存器的某一位置0,对位清除寄存器的对应位写1;

GPIO位结构

3.GPIO模式

• 浮空输入 ———————GPIO_Mode_IN_FLOATING
• 上拉输入 ————————————GPIO_Mode_IPD
• 下拉输入 ————————————GPIO_Mode_IPU
• 模拟输入 ————————————GPIO_Mode_AIN
• 开漏输出 ————————————GPIO_Mode_Out_OD
• 推挽输出 ————————————GPIO_Mode_Out_PP
• 复用功能的开漏输出 ———————GPIO_Mode_AF_OD
• 复用功能的推挽输出 ———————GPIO_Mode_AF_PP

浮空 / 上拉、下拉输入

1、输入模式下,输出驱动器断开

2、输入通过施密特触发器进行波形整形

3、通过输入寄存器获取IO状态
配置为浮空输入模式时,上下拉电阻都断开;
配置为上拉模式时,上拉电阻连接;
配置为下拉模式时,下拉电阻连接。

浮空 / 上拉、下拉输入

模拟输入

1、输出断开,输入施密特触发器关闭

2、ADC模数转换器的专属配置

模拟输入

开漏 / 推挽输出

1、开漏输出的高电平呈现高阻态,无驱动能力,即只有低电平有驱动能力;
推挽输出高低电平均有驱动能力;

2、输出模式下输入模式也有效,一个端口只有一个输出,但可有多个输入

3、开漏输出模式下,P-MOS无效:
数据寄存器为1时,经过反向,N-MOS关闭,输出高阻态;
数据寄存器为0时,经过反向,N-MOS导通,输出接VSS,输出低电平;
该模式下只有低电平有驱动能力,可作为通信协议的驱动方式,在多机通信下可避免各个设备相互干扰。
在外部接5V时,数据寄存器为1时,经过反向,N-MOS关闭,输出5V。

4、推挽输出模式(强推挽输出模式):
数据寄存器为1时,经过反向,P-MOS导通,N-MOS关闭,输出接VDD,输出高电平;
数据寄存器为0时,经过反向,P-MOS关闭,N-MOS导通,输出接VSS,输出低电平;
该模式下高低电平均有较强的驱动能力。

在这里插入图片描述

复用开漏/推挽输出

1、引脚电平由片上外设控制的

在这里插入图片描述

模式总结

总结

三、GPIO应用

1.GPIO寄存器配置

首先通过RCC的一个寄存器来使能GPIOC的时钟

在这里插入图片描述

在APB2外设时钟使能寄存器RCC_APB2ENR里配置IOPCEN,IOPCEN为1,则打开GPIOC的时钟

在这里插入图片描述

再配置PC13口的模式,通过端口配置高寄存器GPIOx_CRH(灯接PC13上,低寄存器为0—7,高寄存器为8—15)

在这里插入图片描述

最后通过端口输出数据寄存器GPIOx_ODR来决定13口输出的电平

在这里插入图片描述

代码如下(示例):

#include "stm32f10x.h"                  // Device header
//若想做到只配置PC13而不影响其他位,需要 &= 和 |=
int main()
{
    RCC->APB2ENR = 0x00000010;  //使能GPIOC的时钟
    GPIOC->CRH  =  0x00300000;  //配置PC13口的模式
    GPIOC->ODR  =  0x00002000;  //输出高电平,LED灭
    GPIOC->ODR  =  0x00000000;  //输出低电平,LED亮
     while(1)
     {
            
     }
}

2.库函数

常用RCC库函数:

//参数通过跳转至函数介绍了解

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
//AHB外设时钟控制函数:使能或失能AHB外设时钟
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
//APB2外设时钟控制函数:使能或失能APB2外设时钟
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
//APB1外设时钟控制函数:使能或失能APB1外设时钟

在这里插入图片描述
常用GPIO库函数:

//参数通过跳转至函数介绍了解

void GPIO_DeInit(GPIO_TypeDef* GPIOx);
//复位所指定的GPIO外设
void GPIO_AFIODeInit(void);
//复位所指定的AFIO外设
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
//用结构体的参数来初始化GPIO口
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
//把结构体变量赋一个默认值
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//读取输入数据寄存器的指定端口的输入值
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
//读取整个输入数据寄存器的输入值
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//读取输出数据寄存器的指定端口的输出值
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
//读取整个输出数据寄存器的输出值
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//把指定端口设置为高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//把指定端口设置为低电平
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
//对指定端口进行写入操作
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
//同时对16个端口进行写入操作

在这里插入图片描述

3.GPIO输出

代码如下(示例):

#include "stm32f10x.h"                  // Device header

int main()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //给结构体取个名字(配置端口模式时需要结构体)
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE); 
    //开启时钟
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //配置PC13口的模式
    GPIO_Init (GPIOC,&GPIO_InitStructure);
    //初始化GPIO口
    GPIO_SetBits (GPIOC ,GPIO_Pin_13);          //把指定端口设置为高电平
//    GPIO_ResetBits (GPIOC ,GPIO_Pin_13);      //把指定端口设置为低电平

     while(1)
     {
            
     }
}

4.GPIO输入

接线图:
在这里插入图片描述

代码如下(示例):

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"

uint8_t KeyNum;

int main()
{
    LED_Init ();
    Key_Init ();
    while(1)
    {
        KeyNum = Key_GetNum ();
        if(KeyNum == 1)
        {
            LED1_Turn();
        }
        if(KeyNum == 2)
        {
            LED2_Turn ();
        }
    }
}

Delay.c

#include "stm32f10x.h"

/**
  * @brief  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
	SysTick->LOAD = 72 * xus;				//设置定时器重装值
	SysTick->VAL = 0x00;					//清空当前计数值
	SysTick->CTRL = 0x00000005;				//设置时钟源为HCLK,启动定时器
	while(!(SysTick->CTRL & 0x00010000));	//等待计数到0
	SysTick->CTRL = 0x00000004;				//关闭定时器
}

/**
  * @brief  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
	while(xms--)
	{
		Delay_us(1000);
	}
}
 
/**
  * @brief  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
	while(xs--)
	{
		Delay_ms(1000);
	}
} 

LED.c

#include "stm32f10x.h"                  // Device header

void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStrcture;
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA ,ENABLE );   //GPIOA时钟使能
    GPIO_InitStrcture.GPIO_Mode  = GPIO_Mode_Out_PP;          //推挽输出
    GPIO_InitStrcture.GPIO_Pin   = GPIO_Pin_1|GPIO_Pin_2  ;   //PA1&PA2
    GPIO_InitStrcture.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init (GPIOA ,&GPIO_InitStrcture);
    
    GPIO_SetBits (GPIOA ,GPIO_Pin_1 |GPIO_Pin_2 );
}

void LED1_ON(void)
{
    GPIO_ResetBits (GPIOA ,GPIO_Pin_1 );
}
void LED1_OFF(void)
{
    GPIO_SetBits (GPIOA ,GPIO_Pin_1 );
}

void LED2_ON(void)
{
    GPIO_ResetBits (GPIOA ,GPIO_Pin_2 );
}
void LED2_OFF(void)
{
    GPIO_SetBits (GPIOA ,GPIO_Pin_2 );
}

void LED1_Turn(void)
{
    //GPIO_Pin_1 = 0时灯为点亮状态,低电平点亮,led外接了高电平
    if(GPIO_ReadInputDataBit (GPIOA ,GPIO_Pin_1 ) == 0)
    {
        GPIO_SetBits (GPIOA ,GPIO_Pin_1 );
    }
    else
    {
        GPIO_ResetBits (GPIOA ,GPIO_Pin_1 );
    }
}
void LED2_Turn(void)
{
    if(GPIO_ReadInputDataBit (GPIOA ,GPIO_Pin_2 ) == 0)
    {
        LED2_OFF ();
    }
    else
    {
        LED2_ON ();
    }
}

Key.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void Key_Init(void)
{
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB  ,ENABLE );
    
    GPIO_InitTypeDef GPIO_InitStructrue;
    GPIO_InitStructrue .GPIO_Mode = GPIO_Mode_IPU ;
    GPIO_InitStructrue .GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_1 ;
    GPIO_InitStructrue .GPIO_Speed = GPIO_Speed_50MHz ;
    GPIO_Init (GPIOB ,&GPIO_InitStructrue );
}

unsigned char Key_GetNum(void)
{
    uint8_t Key_Num = 0;
    if(GPIO_ReadInputDataBit (GPIOB ,GPIO_Pin_1 ) == 0)
    {
        Delay_ms (20);
        while(GPIO_ReadInputDataBit (GPIOB ,GPIO_Pin_1 ) == 0);
        Delay_ms (20);
        Key_Num = 1;
    }
    if(GPIO_ReadInputDataBit (GPIOB ,GPIO_Pin_11 ) == 0)
    {
        Delay_ms (20);
        while(GPIO_ReadInputDataBit (GPIOB ,GPIO_Pin_11 ) == 0);
        Delay_ms (20);
        Key_Num = 2;
    }
    
    return Key_Num ;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值