历史上的今天
返回首页

历史上的今天

今天是:2024年08月28日(星期三)

正在发生

2020年08月28日 | STM32——GPIO设置:快速点亮第一个LED灯

2020-08-28 来源:eefocus

简介

不同的开发板的原理图结构也不尽相同,笔者在这里使用野火的MINI-V3(F103VET6)简易开发板对GPIO口的设置做一个简单的介绍,并实现按键控制LED灯的亮灭。方便读者可以快速熟悉并灵活应用。


原理图分析

首先我们来看一下发光二极管部分和按键部分的原理图。

LED原理图

下面是按键的原理图部分:

button

在这里,我们将使用KEY1(PA0)来控制红灯PB5的亮灭。由原理图可知,其控制LED灯的PB5引脚为低电平时,灯亮。当KEY1按下时,PA0引脚由之前的低电平转为高电平(3V3)。明确了目的之后我们就可以分析GPIO口并进行设置了。


GPIO设置

经过上述的功能明确之后,我们将其分为两大类,分别是输入类(如按键)和输出类(LED灯)。


STM32系列单片机的引脚有着丰富的功能,在这里将其芯片的GPIO口部分的结构图放出,有兴趣的朋友可自行研究或在评论区留言讨论。在这里笔者将不再讲解时钟树的相关内容,以免对初学者造成较大压力,有兴趣的朋友可自行参考官方文档。

GPIO结构图

输入输出模式

GPIO的输入、输出种类详见下表。

功能名称简述
输入上拉输入(GPIO_Mode_IPU)默认状态下(引脚无输入),读得的数据为1,高电平
输入下拉输入(GPIO_Mode_IPD)与上拉输入相反,默认为0,低电平
输入浮空输入(GPIO_Mode_IN_FLOATING)输入不确定,无上拉和下拉。输入阻抗较大,一般用于标准通信协议如、USART的接收端
输入模拟输入模式(GPIO_Mode_AIN)一般由ADC采集电压信号时将其设置为模拟输入。
输出普通推挽输出(GPIO_Mode_Out_PP)输出电平为3.3V
输出普通开漏输出(GPIO_Mode_Out_OD)若要输出5V,则需外加上拉电阻,电源为5V。输出为高阻态时,由上拉电阻和电源向外输出5V的高电平
输出复用推挽输出(GPIO_Mode_AF_PP)引脚复用功能采用复用模式
输出复用开漏输出(GPIO_Mode_AF_OD)复用模式,且加入上拉电阻

由上表可知,我们需要将LED灯的引脚设置为推挽输出。按键部分的输入可以是上拉输入也可以是下拉输入。在这里,因为我们的电路原理图设置的是按键按下为高,释放为低。所以我们使用下拉输入的模式 。


结构体设置

STM32以高效的库函数开发而著称。由于其寄存器过多,不适合类似51系列单片机的寄存器操作,所以我们将直接采用库函数开发的方法(CMSIS 3.5.0版本)。


STM32的库函数将结构体的功效发挥到了极致,我们首先来看一下GPIO口的结构体定义:


typedef struct {

  uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.

                                      This parameter can be any value of @ref GPIO_pins_define */


  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.

                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */


  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.

                                      This parameter can be a value of @ref GPIOMode_TypeDef */

}GPIO_InitTypeDef;


在这个结构体之中,主要包括三个成员:引脚设置(GPIO_Pin)、引脚最大输出速度(GPIO_Speed)和引脚模式(GPIO_Mode)。在这之中,GPIO还有一个重要的定义,即确定组别:GPIOA~GPIOG.

他们的种类又可以分别划分为:


GPIO_Speed:

GPIO_Speed_10MHz

GPIO_Speed_2MHz

GPIO_Speed_50MHz

GPIO_Mode:

GPIO_Mode_AIN

GPIO_Mode_IN_FLOATING

GPIO_Mode_IPD

GPIO_Mode_IPU

GPIO_Mode_Out_OD

GPIO_Mode_Out_PP

GPIO_Mode_AF_OD

GPIO_Mode_AF_PP

GPIO_Pin:

GPIO_Pin_0

GPIO_Pin_1

GPIO_Pin_2

GPIO_Pin_3

GPIO_Pin_4

GPIO_Pin_5

GPIO_Pin_6

GPIO_Pin_7

GPIO_Pin_8

GPIO_Pin_9

GPIO_Pin_10

GPIO_Pin_11

GPIO_Pin_12

GPIO_Pin_13

GPIO_Pin_14

GPIO_Pin_15

熟悉结构体类别以后我们可以进行结构体的定义以及GPIO口的初始化。由于GPIO处于APB2时钟线下,所以我们必须要开启相应的时钟。代码如下:


void key_gpio_config(void) {

    GPIO_InitTypeDef key_struct;    // 定义结构体

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // 开启时钟

    key_struct.GPIO_Pin = GPIO_Pin_0;    //结构体成员设置;对于按键初始化而言,由于GPIO是输入模式,故不必设置最大输出速度

    key_struct.GPIO_Mode = GPIO_Mode_IPD;

    GPIO_Init(GPIOA, &key_struct);    // 初始化引脚

}


void led_gpio_config(void) {    // 同上

    GPIO_InitTypeDef led_struct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    led_struct.GPIO_Pin = GPIO_Pin_5;

    led_struct.GPIO_Speed = GPIO_Speed_50MHz;

    led_struct.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOB, &led_struct);

}


自此,结构体设置结束。下面进行GPIO口的操作。


GPIO操作

对于库函数开发来说,一切硬件操作都可以使用函数来解决。如:



uint16_t  GPIO_ReadInputData (GPIO_TypeDef *GPIOx) 

  // Reads the specified GPIO input data port. 


uint8_t  GPIO_ReadInputDataBit (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 

  // Reads the specified input port pin. 


uint16_t  GPIO_ReadOutputData (GPIO_TypeDef *GPIOx) 

  // Reads the specified GPIO output data port. 


uint8_t  GPIO_ReadOutputDataBit (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 

  // Reads the specified output data port bit. 


void  GPIO_ResetBits (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 

  // Clears the selected data port bits. 


void  GPIO_SetBits (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 

  // Sets the selected data port bits. 


void  GPIO_StructInit (GPIO_InitTypeDef *GPIO_InitStruct) 

  // Fills each GPIO_InitStruct member with its default value. 


void  GPIO_Write (GPIO_TypeDef *GPIOx, uint16_t PortVal) 

  // Writes data to the specified GPIO data port. 


void  GPIO_WriteBit (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, BitAction BitVal) 

  // Sets or clears the selected data port bit. 


对于本题目而言,使用简单的写入操作即可。


int main()

{

    led_gpio_config();

    GPIO_WriteBit(GPIOB, GPIO_Pin_5, 1);    //初始化,使灯为熄灭状态

    key_gpio_config();


    while(1) {

        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1) {

            GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_RESET);

        }

        else {

            GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_SET);

        }

    }

}


至此,GPIO的操作完成,功能也成功实现。但是按键部分未加消抖处理,所以可能出现不稳定的状态。不过对于本示例来说,这一现象并不明显。


推荐阅读

史海拾趣

ERP公司的发展小趣事

进入21世纪20年代,电子智链紧跟智能化浪潮,将人工智能(AI)技术引入ERP系统。公司推出了“智链AI”解决方案,通过机器学习算法自动优化生产流程、预测市场需求和降低库存成本。这一创新使得电子智链在竞争激烈的ERP市场中脱颖而出,成为了电子行业数字化转型的领军企业。

Banner Engineering公司的发展小趣事

Banner Engineering公司成立于XXXX年,起初主要致力于传感器技术的研发和生产。在公司初创时期,面临着激烈的市场竞争和技术挑战。然而,公司凭借其创新的思维和技术实力,成功开发出一系列具有高精度、高可靠性的传感器产品,迅速在市场中获得了认可。这些传感器产品在工业自动化、机器人技术等领域得到了广泛应用,为Banner Engineering公司的初步发展奠定了坚实基础。

D3公司的发展小趣事

在电子行业的激烈竞争中,D3公司凭借其对技术创新的不懈追求,逐渐崭露头角。公司创始人李先生深知,在电子产品日新月异的今天,只有不断创新才能立于不败之地。他带领团队潜心研发,推出了一系列具有创新功能的电子产品,如集成了先进人工智能技术的智能音箱、采用全新电池技术的超薄笔记本等。这些产品一经上市,便受到了市场的热烈追捧,D3公司的市场份额也迅速扩大。

Amveco Toroidal Power Products公司的发展小趣事

Amveco Toroidal Power Products公司成立于XXXX年,初始阶段主要专注于环形变压器的研发与生产。创始人凭借对环形变压器技术的深入了解和市场需求的敏锐洞察,带领团队克服了初创期的种种困难,成功开发出了具有高效能、低噪音特点的环形变压器产品,并赢得了客户的初步认可。随着市场口碑的逐渐积累,公司的业务规模开始稳步扩大。

Allianc公司的发展小趣事

在XXXX年,Allianc公司迎来了一次重大的技术突破。公司研发团队成功开发出了一款具有领先性能的新型电子产品,该产品不仅具有更高的性能和更低的能耗,还具备更好的用户体验。这一技术突破使得Allianc公司在市场上迅速脱颖而出,赢得了大量客户的青睐。随着产品销量的不断攀升,公司的知名度和影响力也逐渐扩大。

华瓷(Chinocera)公司的发展小趣事

在追求经济效益的同时,华瓷始终注重环保和可持续发展。公司投入大量资金用于研发环保型陶瓷材料和生产工艺,致力于减少生产过程中的能源消耗和废弃物排放。同时,华瓷还积极参与社会公益事业,为保护环境、促进可持续发展贡献自己的力量。

问答坊 | AI 解惑

如何更改头像

个人头像更改目前步骤: 个人设置(类似操作均可)->上传头像->点击下方说明图片里的“选择图片”(如图红圈内容)->选择合适大小->预览头像->确定 …

查看全部问答>

按键处理与按键防抖动例子

本帖最后由 paulhyde 于 2014-9-15 09:37 编辑 /***************************************************** 本程序的目标是这样的: 1:不使用INTn中断功能,按键接在普通IO上 2:由定时器T/C2每隔一段时间检测按键一次, 并具有防抖动功能 3:每点击按 ...…

查看全部问答>

电工测量与电测仪表--很基础很实用的好书

电工测量与电测仪表--很基础很实用的好书 序言 前言 第一章 电测技术基础 第一节 测量的定义和分类 第二节 测量误差 第三节 电测仪表的分类 第三节 电测仪表的主要技术指标 第二章 电气测量指示仪表 第一节 电气测量指示仪表的概念和分 ...…

查看全部问答>

编译告警中英文对照分享

1.Found clock-sensitive change during activeclockedge at time <time> on register \"<name>\"原因:vector sourcefile中时钟敏感信号(如:数据,允许端,清零,同步加载等)在时钟的边缘同时变化。而时钟敏感信号是不能在时钟边沿变化 ...…

查看全部问答>

有哪位仁兄开发过笔记本快捷键驱动

能否把原理说一下,另外快捷键调节亮度跟显卡驱动还有BIOS有关系是么?…

查看全部问答>

电压比较器问题~~~~~~~~~~~~~~~~~~

为什么在MULTISIM10中,单独做个电压比较器可以出来结果,加的信号源是系统的函数发生器(输入10V,1KHz,正弦波)~~~~~但为什么连到我们自己做的信号源(示波器显示也是10V,1KHz,正弦波)上就出来结果不对呢?…

查看全部问答>

DVR的朋友进来看看

对于DVR有哪些方案啊?了解的朋友提提哈。具体用是哪个芯片 现在我所知道的 主要是  TI的 DM6446  海思的351x系列 还有台湾的智原818x系列。 从事过DVR开发的朋友,还有其他的方案吗?谢谢啊~~~~…

查看全部问答>

关于LCD显示问题的求助

我的平台是PXA270+Wince5.0 现在LCD的显示比较奇怪,刚进入系统的时候,主画面的显示还算正常,但是一切换画面,屏幕就会局部或者部分发白。 比方说,打开IE,屏幕就会整个发白,字体看不太清楚。 打开控制面板,屏幕会变成一条一条的,什么字都 ...…

查看全部问答>

用1602LCD碰到的奇怪问题(难)

我用AT89S52与1602LCD相连,P1口与LCD的D0-D7相连,编写了一个程序,但LCD上显示的如果是数字,那只能显示偶数,如果是字母,那只能是b,d,f...我应该是D0脚有问题,每次这里测电平都是低电平,这跟前面的电路没有关系把?因为我是直接把P1.0和D1相 ...…

查看全部问答>

关于FPGA设计资源整和积累问题

各位FPGA论坛的大虾:        为了方便大虾和后来者使用,学习和共享. 我呼吁大家把已经经过验证的FPGA 模块 整理成册, 分享到论坛给使用!             &n ...…

查看全部问答>