小言_互联网的博客

MCU学习笔记_GPIO工作原理

320人阅读  评论(0)

MCU学习笔记

STM32时钟

1. STM32 GPIO基础知识
2. STM32 GPIO工作模式
3. STM32 GPIO寄存器
4. 配置寄存器操作IO口
5. 配置HAL库函数操作IO口

1. STM32 GPIO基础知识

  • GPIO, General purpose input output, 通用输入输出端,可通过程序软件配置成输入或者输出端。

  • 引脚与GPIO的区别和联系

    STM32的引脚中,有部分是做GPIO使用,其他部分是电源引脚/复位引脚/启动模式引脚/晶振引脚/调试下载等功能的引脚。
    例如:STM32FXXXIGT6:140个IO口 = 8组(PA-PH) *16个(PX0-PX15)+12个(PI0-PI11)

  • 引脚复用

    STM32的大部分引脚除了当GPIO使用外,还可以复用为外设功能引脚(如串口等)。

    复用原理

    可以通过AFRL寄存器,配置引脚的功能。
    优点:大大节省IO引脚的资源


2. STM32 GPIO工作模式

  • 8种工作模式

    • 4种输入模式

      1. 输入浮空:上拉下拉不被设置,IO口的电平,直接通过施密特触发器,到大输入数据寄存器,CPU可以通过输入数据寄存器,读取状态.

      2. 输入上拉:上拉起作用,下拉没有连接;IO口引脚的电平数据经过施密特触发器,进入输入数据寄存器,CPU可以通过输入数据寄存器,读取状态.

      3. 输入下拉:下拉起作用,连接VSS,上拉没有连接;IO口引脚的电平数据经过施密特触发器,进入输入数据寄存器,CPU可以通过输入数据寄存器,读取状态.

      4. 模拟输入:上拉,下拉都不起作用,施密特触发器关闭,输入模拟信号,通过ADC,转换成数字信号,CPU可以读取ADC的相关寄存器。

      • 4种输出模式
      1. 开漏输出(带上拉或者下拉): 当写入1,3处的P-MOS管无效,N-MOS管截止,IO端口的输出电平由上拉电阻决定; 当写入0,3处的P-MOS管无效,N-MOS管导通,IO端口的输出低电平;

      2. 开漏复用功能(带上拉或者下拉) :输入为偏上外设模块,当写入1,3处的P-MOS管无效,N-MOS管截止,IO端口的输出电平由上拉电阻决定; 当写入0,3处的P-MOS管无效,N-MOS管导通,IO端口的输出低电平;

      3. 推挽式输出(带上拉或者下拉) :设置输入为1,IO口输出为低电平;设置输入为0,IO口输出为高电平;

      4. 推挽式复用功能(带上拉或者下拉):由片上外设输入,设置输入为1,IO口输出为低电平;设置输入为0,IO口输出为高电平;
        注意:
        推挽输出:可以输出强高低电平,连接数字器件
        开漏输出:只可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻。适合于做电流型的驱动,其吸收电流的能力相对强.

    • 4种最大输出速度(F429)

    1. 2MHz 低速
    2. 25MHz 中速
    3. 50MHz 快速
    4. 100MHz 高速

上电复位后,GPIO默认为输入浮空状态,部分特殊功能引脚为特定状态;
复位后,调试引脚处于复用功能上拉/下拉状态:

  • PA15: JTDI处于上拉状态
  • PA14: JTCK/SWCLK处于下拉状态
  • PA13: JTMS/SWDAT处于下拉状态
  • PB4: NJTRS处于上拉状态
  • PB3: JTDO处于浮空状态

3. STM32 GPIO寄存器

  • 每组IO口由10个局存起组成,如果芯片有GPIOA- GPIOI 9个组,那么一共有9*10个寄存器
  • 如果配置一个IO口需要2个位,那么刚好32位寄存器配置一组IO口16个IO口
  • 如果配置一个IO口只需要1个位,一般高16位保留
  • BSRR寄存器32位分为低16位BSRRL和高16位BSRRH,BSRRL配置一组IO口的16个IO口的置位状态(1),BSRRH配置复位状态(0)。

每组GPIO端口的寄存器包括:

  • 4个32位配置寄存器
    一个端口模式寄存器(GPIO_MODER)
    一个端口输出类型寄存器(GPIOx_OTYPER)
    一个端口输出速度寄存器(GPIOx_OSPEEDR)
    一个端口上拉下拉寄存器(GPIOx_PUPDR)

  • 2个32位数据寄存器
    一个端口输入数据寄存器(GPIOx_IDR)
    一个端口输出数据寄存器(GPIOx_ODR)

  • 1个32位位置位/复位寄存器 (GPIOx_BSRR)

  • 1个32位配置锁存寄存器(GPIOx_LCKR)

  • 2和32位复用功能共寄存器(低位GPIOx_AFRL&GPIOx_AFRH)


4. 配置寄存器操作IO口

  • 一般步骤:
    1. 初始化HAL库:HAL_Init();
    2. 初始化系统时钟
    3. 使能IO口时钟。配置IO口时钟使能寄存器:RCC -> AHBIENR
    4. 初始化IO口模式。配置四个配置寄存器;(GPIO_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR, GPIOx_PUPDR)
    5. 操作IO口,输出高低电平。
      配置寄存器GPIO_ODR,或者GPIOx_BSRR
  • STM32 配置寄存器代码
#include "sys.h"
#include "delay.h"
#include "uart.h"

int main(void)
{
   
	//初始化HAL库
	HAL_Init();
	
	//初始化系统时钟
	Stm32_Clock_Init(360,25,2,8);

	//延时初始化
	delay_init(180);
	
	//配置IO口时钟使能寄存器,使能AHB1寄存器
	RCC->AHB1ENR |= 1<<1; 
	
	//初始化IO口模式。配置四个配置寄存器——通用推挽输出带上拉
	GPIOB->MODER = 0X00000005;//初始化IO口模式。配置MODER寄存器
	GPIOB->OTYPER = 0X00000000;//初始化IO口模式。配置OTYPER寄存器
	GPIOB->OSPEEDR = 0X0000000F;//初始化IO口模式。配置OSPEEDR寄存器
	GPIOB->PUPDR = 0X00000005;//初始化IO口模式。配置PUPDR寄存器
	//操作IO口
	while(1)
	{
   
		GPIOBx->BSRR = 0x00000003; //操作IO口,输出高电平
		delay_ms(500);
		GPIOBx->BSRR = 0x00030000; //操作IO口,输出低电平
		delay_ms(500);
	}
}

5. 配置库函数操作IO口

  • 可用函数
  1. 初始化函数:
    初始化一个或者多个IO口的工作模式,输出类型,速度以及上拉/下拉方式。也就是一组IO口的4个配置寄存器。
//(GPIO_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR, GPIOx_PUPDR)
void HAL_GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef *GPIO_Init);
  1. 读取输入电平函数
    读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器
//GPIOx_IDR寄存器
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);
  1. 设置引脚输出电平函数
//GPIO_ODR,或者GPIOx_BSRR
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin, GPIO_PinState PinState);
  1. 输出电平翻转函数

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
  • 操作步骤

    1. 初始化HAL库:HAL_Init();
    2. 初始化系统时钟
    3. 使能IO口时钟。_HAL_RCC_GPPIOB_CLK_ENABLE();
    4. 初始化IO口模式。HAL_GPIO_Init();
    5. 操作IO口,输出高低电平。HAL_GPIO_WritePin();
  • HAL库函数操作IO口代码

#include "sys.h"
#include "delay.h"
#include "uart.h"

int main(void)
{
   
	GPIO_InitTypeDef GPIO_InitStructure;
	//初始化HAL库
	HAL_Init();
	
	//初始化系统时钟
	Stm32_Clock_Init(360,25,2,8);

	//延时初始化
	delay_init(180);
	
	//使能IO口时钟	 
	__HAL_RCC_GPPIOB_CLK_ENABLE();

   //初始化IO口模式
	GPIO_InitStructure.Mode= GPIO_Mode_OUTPUT_PP;//推挽输出
	GPIO_InitStructure.Pin= GPIO_PIN0;//PIN0
	GPIO_InitStructure.Pull= GPIO_PULLUP;//上拉
	GPIO_InitStructure.Speed= GPIO_SPEED_FREEQ_VERY_HIGH;//速度,高速
	
	HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
	while(1)
	{
   
		//操作IO口,输出高低电平。
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);	//PB0=0
		delay_ms(500);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0,GPIO_PIN_SET);	//PB0=1
		delay_ms(500);
	}
}

参考资料:正点原子视频 Thanks^^

【注】:个人学习笔记,如有错误,望不吝赐教,这厢有礼了~~~



转载:https://blog.csdn.net/weixin_50722839/article/details/115908694
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场