点亮LED灯(GPIO外设初步)

本文用于本人快速回忆起学后遗忘的内容,可能不适合初学。参考学习视频:铁头山羊stm32 入门教程

1 GPIO属性

1.1 八种工作模式

芯片功能多,需要适应不同工作场景,因此需要不用工作方式,八种模式如下图所示,复位后IO引脚默认处于输入浮空模式。八种模式详细介绍可参考【STM32】GPIO工作原理(八种工作方式超详细分析,附电路图)_芯片管脚 gpic-CSDN博客
在这里插入图片描述

1.1.1 按输入输出分

输出是多对一,要分直接和复用,不然两者就会在引脚冲突;输入是一对多,可以是将信号传到片上外设,也可以传到CPU
在这里插入图片描述

1.1.2 推挽开漏(输出)

推挽模式ODR寄存器写0输出0,写1输出1
开漏模式PMOS始终是断开的。ODR寄存器写0输出低电平,写1输出高阻
推挽和开漏的MOS管前都有反相器会将输入信号反相,所以会有以上逻辑
在这里插入图片描述

1.1.3 上拉下拉与浮空(输入)

当引脚接收信号,要判断高低,我们知道电压表并联测试电阻两端电压要求电压表内阻无穷大,实际上IO引脚在接收外部信号判断高低时也要看成输入阻抗无穷大,将其等效成下图。
在这里插入图片描述

若输入为高电平或低电平,无影响;若输入脚悬空,IO引脚就相当于天线,接收外接杂波,影响有用信号,故引入下图的上拉和下拉电阻
当上拉接入,下拉断开,由串联分压原理可知IO口在悬空时接近3.3V,正常输入无影响;当上拉断开,下拉接入,IO口悬空时略小于参考地,正常输入无影响
在这里插入图片描述

1.2 IO最大输出速度

IO最大输出速度指的是IO允许输出电平的最大切换频率。stm32的IO引脚最大输出速度:上沿+高电平+下沿,stm32f1系列可选最大IO输出速度有以下三种
在这里插入图片描述

2 GPIO寄存器

读寄存器的值,知道模块当前状态,写入寄存器值可以控制寄存器做相应任务,GPIO寄存器组用于实现GPIO的模式配置和对GPIO操作。下图是GPIO外设的部分常用寄存器
在这里插入图片描述

2.1 寄存器和寄存器编程

就GPIO这个外设来说,读寄存器的值(输入IDR),知道模块当前状态,写入(输出ODR)寄存器值可以控制寄存器对外做相应任务
在这里插入图片描述

如GPIO寄存器组(包括输入寄存器,输出寄存器,配置寄存器等),可以管理芯片周围的管脚
高16位保留,时钟为0。低16位对应16个引脚,对应其管理的16个GPIO.IDR读取连接到IO引脚上的外部输入信号时高电平还是低电平
因为GPIO被分为了3个组(GPIOA、GPIOB、GPIOC),所以虽然有37个引脚,但每个组内的引脚数都不超过16个,所以寄存器用16位就可以了

2.2 配置寄存器

用于配置IO引脚的参数,如表中每格用于设置单个引脚的参数,CR0用于设置Px0的参数,一次类推。
每个引脚需要4位CR位进行配置,如Px0的属性由CNF1[1:0]、MODE1[1:0]、CNF0[1:0]、MODE0[1:0]八位的取值决定;Px1的属性由CNF3[1:0]、MODE3[1:0]、CNF2[1:0]、MODE2[1:0]八位的取值决定。以此类推,具体见stm32f10x参考手册

2.3 输入数据寄存器

用于读取寄存器某位的值,如IDR0读取Px0引脚的电平

2.4 输出数据寄存器

用于向寄存器某位写入值,如ODR0写入0,引脚Px0就输出低电平

3 项目分析

3.1 硬件连接

推挽接法:向ODR写1输出1,写0输出0
开漏接法:PMOS源极断开,向ODR写1输出高阻,向ODR写0输出0(由于内部电路原因,写0时,NMOS栅极为高电平,管子导通)
在这里插入图片描述

3.2 点亮方法

  • LED1为电源指示灯,上电就亮
  • LED2连接到PC13脚,当我们将对应引脚配置为低电平时,单片机引脚低电平输出(0V),此时有电压差,有电流流过,LED灯被点亮
  • 限流电阻用于防止LED灯烧坏
    在这里插入图片描述

4 配置流程

对GPIO的配置包含时钟的使能和对应GPIO外设的初始化,后者是对GPIO模式的配置

4.1 时钟使能

位于stm32f10x_rcc.c(或查询固件库15.2.22使用说明),该编程接口有RCC_APB2Periph和NewState两个变量,可填参数如下
在这里插入图片描述

使用RCC片上外设模块开启/关闭APB2总线上的片上外设的时钟,第二个参数为ENALE或者DISABLE(上图翻译大小写没注意)

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

4.2 GPIO配置

固件库10.2描述了操作GPIO的编程接口,查看GPIO_Init的介绍,参数如下,一个是确定GPIO所在分组,另一个以结构体的形式配置相关参数
在这里插入图片描述
参数一填GPIOC,参数二为结构体,其成员如下
在这里插入图片描述

库函数定义了结构体GPIO_InitTypeDef,例化时将例化模块命名为GPIOInitStruct(猜测,后面再求证)

  1. IO引脚选择:用于选择待设置的管脚。这里为PC13,所以该参数为GPIO_PIN_13;如果无管脚被选中,则为GPIO_PIN_None

  2. 设置选中管脚的速度,LED闪烁不要求管脚输出速率很快,使用最低速率以降低功耗
    在这里插入图片描述

  3. 引脚输入输出模式,由于硬件连接方式,设为输出开漏模式
    在这里插入图片描述
    配置代码如下

GPIO_InitTypeDef GPIOInitStruct;  //定义IO口初始化要用到的结构体
   GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;   //结构体成员赋值
   GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
   GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;

GPIO_Init(GPIOC,&GPIOInitStruct);    //GPIO初始化

4.3 对GPIO操作(点亮LED)

要使LED亮起来,需向管脚输出低电平,即向ODR寄存器写0点亮LED,直接对GPIO操作的编程接口如下
在这里插入图片描述

由于是开漏接法,所以向GPIOC_13脚对应ODR寄存器位写0(此时NMOS处栅极为高电平,导通),以使管脚输出0,发光二极管导通,查看上图写ODR编程接口

  • GPIO_SetBits:将某几个端口置一,比如置一GPIOA_10和GPIOA_15

    GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);

  • GPIO_ResetBits:将某几个端口清零,比如清零GPIOA_10和GPIOA_15

    GPIO_ResetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);

  • GPIO_WriteBit:通过参数BitVal将GPIO_SetBits和GPIO_ResetBits的功能合为一体,为Bit_RESET时写0,为Bit_SET时写1,比如

    GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);

  • GPIO_Write:直接向一个GPIO寄存器组写入数据,比如

    GPIO_Write(GPIOA, 0x2000);

4.4 对GPIO操作(LED闪烁)

使LED闪烁有如下两种实现逻辑
在这里插入图片描述

对与方案1,要用到写ODR的函数和延迟函数,延迟在后期不推荐用,标准库里没有,所以可以自己封装一个延迟函数或者使用别人写好的

while(1)
{
	GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
  	PAL_Delay(100);
  	GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
  	PAL_Delay(100);
}

对于方案2,主要是怎样实现翻转逻辑。通过读取ODR寄存器的值进行判断

GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);  
while(1)
{
	PAL_Delay(100);

	if(GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET)   //读对应ODR位,如果为0,向对应ODR位写1
	{
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
	}
	else                                                       //否则,向对应位写0
	{
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
	}
}

5 完整代码

#include "stm32f10x.h"
#include "stm32f10x_pal.h"

int main(void)
{
	GPIO_InitTypeDef GPIOInitStruct; //例化结构体
	PAL_Init();                      //初始化PAL库,别人的库
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);  //打开GPIOC的时钟

	GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;
	GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_Init(GPIOC, &GPIOInitStruct); //初始化GPIO
/*几种写ODR的方法,

    //给指定GPIOC某脚对应ODR位写单0或1
	GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);// 开漏,1 - 熄灭 , 0- 点亮 Bit_SET
	GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
    //给整个GPIOC对应ODR寄存器写1或0
	GPIO_Write(GPIOC, 0x2000); // 1 - 熄灭
	GPIO_Write(GPIOC, 0); // 点亮
	//给指定GPIOC某脚对应ODR位写单0或1
	GPIO_SetBits(GPIOC, GPIO_Pin_13);
	GPIO_ResetBits(GPIOC, GPIO_Pin_13);

*/

    GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);  
	while(1)
	{
		PAL_Delay(100);

		if(GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET)   //读对应ODR位,如果为0,向对应ODR位写1
		{
			GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
		}
		else                                                       //否则,向对应位写0
		{
			GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
		}
  
        //方法一实现闪烁,前面为方法二实现闪烁
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
  		PAL_Delay(100);
  		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
  		PAL_Delay(100);
	}
}

6 整体实现逻辑

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值