STM32--GPIO点亮LED灯(手把手,超详细)

这篇具有很好参考价值的文章主要介绍了STM32--GPIO点亮LED灯(手把手,超详细)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面:在前面的学习中,我们学习了STM32的编译环境(MDK)、时钟树以及GPIO的8种工作模式;这节我们学习正式入门STM32---点亮第一个LED灯;即利用GPIO进行电灯,尽管是一个十分简单的实现,但是其步骤也是一个完整的STM32项目,可以说是“麻雀虽小,五脏俱全”;因此,作为入门十分合适;

实验介绍:利用STM32开发板,通过HAL库函数对相关寄存器的控制,实现对开发板上LED灯的控制;

实验硬件:正点原子---STM32F1精英版开发板; 

目录

一、GPIO寄存器介绍

1.1 端口配置寄存器(GPIOx_CRL 和 GPIOx_CRH)     

1.2  端口输入数据寄存器(GPIOx_IDR)

1.3 端口输出数据寄存器(GPIOx_ODR)

1.4 端口置位/复位寄存器(GPIOx_BSRR)

1.5 端口位清除寄存器(GPIOx_BRR)

1.6 端口配置锁定寄存器(GPIOx_LCKR)

二、GPIO配置步骤

2.1 使能时钟

2.2 设置工作模式 

2.3 设置输出状态

2.4 读取输入状态

三、硬件设计

3.1 实现功能

3.2 原理图

四、程序设计

4.1 程序流程图

4.2 程序分析

 4.2.1 led驱动函数

4.2.2 main函数

五、实验现象


一、GPIO寄存器介绍

        在前面的学习中,我们对GPIO进行了基本的介绍,基本结构进行了分析以及GPIO的8中工作模式的介绍;详细的内容请大家参考我前面的博客;

STM32--GPIO(8种工作模式)-CSDN博客

         STM32F1 每组(这里是 A~D)通用 GPIO 口有 7 个 32 位寄存器控制; 分别为:CRL、CRH、TDR、ODR、BSRR、BRR以及LCKR寄存器;下面对7个寄存器做出详述(注:每组都有7个寄存器,例如:GPIOA、GPIOB都有7个相关的寄存器);

1.1 端口配置寄存器(GPIOx_CRL 和 GPIOx_CRH)     

        这个寄存器是用于配置GPIO端口的寄存器,其中CRL 控制端口的低八位,CRH 控制端口的 高八位,每个组GPIO有16个端口(例如:GPIOA0-GPIOA15);那么这两个寄存器控制GPIO口的什么呢?用于控制 GPIO 口的工作模式和工作速度;

CRL寄存器:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

 CRH寄存器:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

        这两个32位的寄存器,一共为64位,64位共控制16个端口(如:PA0-PA15);那么相当于每4位控制一个IO口的工作模式与工作速度;CRL寄存器控制(0-7)端口,CRH寄存器控制(8-15)端口;

以3-0位(控制PX_0端口)为例:

    1-0位控制其输入输出: 

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

    3-2位控制其对应的模式:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

        如0-3位为1010,则表示:端口1工作在复用功能的推挽输出模式,最大速度为2MHz;

        又如,我们需要让Px_7端口工作在浮空输入模式,则就要求CRL寄存器的31-28位赋值为:0100;

        故通过上面两个寄存器,作用是控制端口的输入输出模式以及工作速度;

        但是,我们仔细观察,在上面的寄存器中,如果选择的是输入模式,在上拉/下拉输入模式下,通过上面两个寄存器无法确定其到底为上拉还是下拉模式;此时,就需要另外的寄存器;

1.2  端口输入数据寄存器(GPIOx_IDR)

        该寄存器用于读取GPIOx的输出高电平或低电平;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

         寄存器低 16 位有效,分别对应每一组 GPIO 的 16 个引脚。当 CPU 写访问该寄存器,可以读取对应引脚的输入电平(IDRy=0、IDRy=1),该寄存器下方为r,表示为只读寄存器,只可以读取值,不能写入值;

1.3 端口输出数据寄存器(GPIOx_ODR)

        该寄存器用于控制 GPIOx 的输出高电平或者低电平;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

        该寄存器低 16 位有效,分别对应每一组 GPIO 的 16 个引脚。当 CPU 写访问该寄存器,如 果对应的某位写 0(ODRy=0),则表示设置该 IO 口输出的是低电平,如果写 1(ODRy=1),则表示设置该 IO 口输出的是高电平。

        除了 ODR 寄存器,还有一个寄存器也是用于控制 GPIO 输出的,它就是 BSRR 寄存器。

1.4 端口置位/复位寄存器(GPIOx_BSRR)

         该寄存器也用于控制 GPIOx 的输出高电平或者低电平.

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

        该寄存器的31-16(BRy)位控制15-0引脚的ODRy的值,如果为0,对ODRy的值不产生影响,如果为1,则将ODRy的值改为0;

        该寄存器的15-0(BSy)位也控制15-0引脚的ODRy的值,如果为0,对ODRy的值不产生影响,如果为1,则将ODRy的值改为1;

        当BRy与BSy同时作用时,以BSy为主;

        此处,我们需要思考一下,为什么输出一个引脚的值,需要两个寄存器对其进行双重控制呢?

官方给出的解释是:在使用ODR在读和修改之间产生中断时,会对ORD的值产生风险,而BSRR无风险;

        我们对其进行简单的分析,ODR是一个可读可写的寄存器,那么对其进行赋值时(确定某个IO口输出电平),首先需要读出ODR寄存器的值,然后再重新为ODR进行赋值。而BSRR是一个只写寄存器,赋值时直接设置即可。BSRR 寄存器改变引脚状态的时候,不会被中断打断,而 ODR 寄存器有被中断打断的风险。

1.5 端口位清除寄存器(GPIOx_BRR)

        该寄存器用于清除ODR寄存器的值,不经常使用;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

        该寄存器低 16 位有效,若为0,对应的ODRy位不产生影响;若为1,清除对应位ODRy为0;

1.6 端口配置锁定寄存器(GPIOx_LCKR)

        当执行正确的写序列设置了位16(LCKK)时,该寄存器用来锁定端口位的配置。位[15:0]用于锁 定GPIO端口的配置。在规定的写入操作期间,不能改变LCKP[15:0]。当对相应的端口位执行了 LOCK序列后,在下次系统复位之前将不能再更改端口位的配置。 每个锁定位锁定控制寄存器(CRL, CRH)中相应的4个位。

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

以上7个寄存器中,我们需要重视的为CRL、CRH、ODR、IDR以及BSRR寄存器

二、GPIO配置步骤

一般外设的配置驱动模型为:

1、初始化

分为:时钟设置(包括时钟源与开启时钟);

           参数设置;

           IO设置(可选);

           中断设置(可选);

2、读函数:从外设读取数据(可选);

3、写函数:往外设写入数据(可选);

4、中断服务函数(可选);

         在此,我学习的时候就有个疑问与大家分享,为什么STM32进行IO口操作时,必须先要进行时钟设置(使能时钟)?

        在学习52单片机的时候,只需要直接将对应的外设寄存器配置好,就直接使用,为什么32要先配置时钟呢?

        经过查阅资料发现,51单片机的做法虽然简单,但是这样对于功耗的浪费很大,也就是说尽管有些地方用不到,还需要配置资源。为了降低功耗与发热,芯片厂商需要精准的控制某个设置的开与关,达到节能省电的目的;此外,51只有一个晶振时钟,好控制,而32的晶振4个起步,对于不同的外设需要分配不同的晶振时钟,故STM32中I/O要先进行时钟配置,在进行IO口操作;

GPIO配置步骤:

1、使能时钟 __HAL_RCC_GPIOB_CLK_ENABLE();//宏定义

2、设置工作模式:HAL_GPIO_Init 函数;

3、设置输出状态:HAL_GPIO_WritePin 函数;

                               HAL_GPIO_TogglePin 函数;

4、读取输入状态:HAL_GPIO_ReadPin函数;

口诀:GPIO配置,一个宏,四个函数;

下面我们对于这四个步骤进行详细说明,包括利用HAL库函数进行相关的配置说明;

2.1 使能时钟

        STM32 在使用任何外设之前,我们都要先使能其时钟(也就是打开时钟),此处利用一个宏定义:

__HAL_RCC_GPIOX_CLK_ENABLE();

此处,我们看看代码种对于其宏定义的说明是什么。打开任意一个例程源码进行搜索;(此处以GPIOA作为举例); 

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

宏定义的作用就是替代,将被定义的量用定义的量进行替代;

 代码中对于此宏的定义是这样说的:

其中关键在于划线这句:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

 SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);

其中,SET_BIT的意思我们不知,再次进行查找,右键Go to Definiation of "SET_BIT"其又是一个宏定义:其含义为括号中的两个参数做或运算;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

 SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN)的参数1:RCC->APB2ENR;参数2:RCC_APB2ENR_IOPAEN;分别代表什么意思呢?

RCC_APB2ENR_IOPAEN:这又是一个宏定义,我们同样跳转过去看一下去其含义:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

这三行代码可以说是层层宏定义,其表达的意思就是将0X00000002(二进制为:0x00000000000000000000000000000010)左移一位成为0X00000004(二进制为:0x00000000000000000000000000000100);

RCC->APB2ENR:是APB2外设时钟使能寄存器,让其与0X00000004进行或运算,则该寄存器的第2位进行置1;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

查看参考手册,将位2置1的作用就是打开IO口时钟;

例如,我们需要使能IO端口B时钟使能,那么怎么设置呢?

__HAL_RCC_GPIOB_CLK_ENABLE();

综上过程,__HAL_RCC_GPIOX_CLK_ENABLE();宏定义的作用就是打开GPIO端口的时钟;

2.2 设置工作模式 

        设置工作模式:HAL_GPIO_Init 函数;

        那么同样我们对于HAL_GPIO_Init函数进行分析;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

对其两个参数进行分析:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)

这两个参数都为结构体指针:

结构体指针1:GPIO_TypeDef其定义格式为:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

主要包括一些相关的寄存器,当然库函数已经给我们定义了这些结构体变量,例如下面的:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

因此也将GPIOA成为GPIO寄存器基地址

结构体指针2:GPIO_InitTypeDef其定义格式为:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

该结构体变量需要在使用时对其结构体成员进行定义使用,包括端口的引脚、工作模式、上

下拉方式以及输出速度;

PIN:引脚设置;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

Mode:(工作模式)

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

Pull上下拉

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

Speed:速度

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

例如,我们需要初始化IO端口B的引脚5,使其工作在推挽模式,输出速度为低速,那么怎么设置呢?

GPIO_InitTypeDef  gpio_init_struct;//定义第二个结构体变量

设置变量对应的结构体成员;

gpio_init_struct.Pin=GPIO_PIN_5;
gpio_init_struct.Mode=GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Speed=GPIO_SPEED_FREQ_LOW ; 

HAL_GPIO_Init(GPIOB,&gpio_init_struct);、、引用初始化函数;

2.3 设置输出状态

        设置输出状态:HAL_GPIO_WritePin 函数;

        下面我们对于Wirte_Pin进行分析:同样利用右键或者查找找到对应函数的定义;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

该函数共有三个参数:GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState

参数1:GPIO_TypeDef *GPIOx结构体指针类型,与设置工作模式的参数相同,此处不进行详述;

参数2:uint16_t GPIO_Pin与上文所说的PIN引脚的相同,选择端口对应的引脚;

参数3:GPIO_PinState此处为一个枚举类型,GPIO的状态0/1;

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

例如,我们需要设置PB6=1,那么怎么设置呢?

参数1为:GPIOB;参数2为:GPIO_PIN_1;参数3为:GPIO_PIN_SET;   

        HAL_GPIO_TogglePin 函数;

        下面对于TogglePin 函数进行详述:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

该函数有两个参数:GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin

参数1:GPIO基地址,上文已经提及;

参数2:GPIO_Pin,端口引脚上文已经提及;

例如,我们需要设置PB10进行翻转,那么怎么设置呢?

参数1为:GPIOB;参数2为:GPIO_PIN_10;

2.4 读取输入状态

        HAL_GPIO_ReadPin函数;

        下面我们对于ReadPin函数进行详述:

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

该函数共有三个参数:GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin这两个参数上文已经介绍过,分别为:GPIO基地址、GPIO_Pin,端口引脚;

该函数的返回值为枚举类型,返回0代表IO为低电平,返回1代表IO为高电平;

例如,我们需要知道PB10的输入,那么怎么设置呢?

参数1为:GPIOB;参数2为:GPIO_PIN_10;在设置一个变量,将返回值赋值给变量即可;

三、硬件设计

3.1 实现功能

        使STM32F1精英版上的LED1进行闪烁;

3.2 原理图

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

        在该开发板上的LED灯共有3个,本次我们点亮LED0,即对PB5进行操作;我们看到LED0右端接的是VCC3.3V,那么只需要控制左端的PB5输出即可;(输出0点亮,输出1熄灭);

        我们还需要确定GPIOB_5的工作模式;我们采用推挽输出,其特点为:输出引脚电平,高电平为VDD,低电平为VSS;

四、程序设计

4.1 程序流程图

STM32--GPIO点亮LED灯(手把手,超详细),STM32,单片机,嵌入式硬件,stm32

4.2 程序分析

 4.2.1 led驱动函数

void led_init(void)//led初始化函数
{

     __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
    GPIO_InitTypeDef  gpio_init_struct; //定义结构体变量  
    gpio_init_struct.Pin=GPIO_PIN_5;//定义结构体变量成员-引脚号为5;
    gpio_init_struct.Mode=GPIO_MODE_OUTPUT_PP;//定义结构体变量成员-工作模式为推挽输出;
    gpio_init_struct.Speed=GPIO_SPEED_FREQ_LOW ; 定义结构体变量成员-输出速度为低速;
    HAL_GPIO_Init(GPIOB,&gpio_init_struct);//引用GPIO初始化函数;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);//引用GPIO写入函数;

}

4.2.2 main函数

int main(void)
{
    HAL_Init();                              /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);      /* 设置时钟, 72Mhz */
    delay_init(72);                          /* 延时初始化 */
    led_init();                              /* LED初始化 */
    
    while(1)
    { 
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);    /* PB5置1 */ 
        delay_ms(500);
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);  /* PB5置0 */
        delay_ms(500); 
    }
}

五、实验现象

32点灯

总结:本文主要讲解了如何在STM32开发板上点亮第一个LED灯,主要的学习内容为:GPIO配置步骤以及GPIO相关的寄存器,硬件设计部分入代码分析;尽管本文的代码难度不难,但是对于程序中相关函数以及寄存器的理解,对于初学者还有一定的难度因此还是需要多加练习;

创作不易,还请大家多多点赞支持!!!文章来源地址https://www.toymoban.com/news/detail-768108.html

到了这里,关于STM32--GPIO点亮LED灯(手把手,超详细)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • cubmx基础操作,hal库基本配置流程之使用 stm32cubmx生成HAL库进行gpio点亮led(stm32h7xx)(超详细,小白教程)

    HAL库(硬件抽象层库)是一个提供对底层硬件操作的抽象的库,它使得开发者可以使用统一的接口进行硬件操作,而不必关心底层硬件的具体实现细节。HAL库通常由硬件厂商提供,用于支持其硬件设备,并为其提供标准化的接口。 HAL库的主要目的是简化底层硬件的操作,使得

    2024年02月20日
    浏览(46)
  • STM32CubeMX教程2 GPIO输出 - 点亮LED灯

    开发板(STM32F407G-DISC1) STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 使用STM32CubeMX软件配置STM32F407开发板点亮LED灯 笔者使用的STM32F407G-DISC1开发板主控制器为STM32F407VGT6,该MCU封装为LQFP 100,一共100个引脚,除去16个POWER引脚、1个NRST引脚和一个BOOT0引脚外,

    2024年02月03日
    浏览(46)
  • 【stm32】01,今晚,整个32将为你闪烁(GPIO输出,点亮led灯)

    往期内容: 【stm32】00亲爱的勇者,在踏上这个波澜壮阔的大陆之前,厉兵秣马,我们即刻出发 各位勇者你们好啊,我是weib。祝贺你们已经厉兵秣马做好在这个世界中闯出一番天地的准备了,也欢迎来到第一个关卡——GPIO的输出操作,闲言少叙让我们进入正题吧。 请各位勇

    2024年02月12日
    浏览(31)
  • STM32萌新学习日志——用GPIO外设寄存器输出点亮LED对比库函数点亮LED——谈学习感悟

            本周学习STM32单片机,由于之前学过51单片机,为了便于切入,先学习了寄存器点亮LED灯的方法,整体思路与51单片机相似。在基本掌握后,尝试自己构建库函数雏形,过程比较困难,后面开始借鉴野火官方库函数。         这里其实建议大家在学会构建库函数后

    2024年03月17日
    浏览(80)
  • STM32/51单片机编程入门(点亮LED)

    目录 一、Proteus电路仿真软件上的C51程序设计及仿真 1.原理图绘制 2.Keil5上的51程序编写 3.仿真 二、安装mdk5软件和stm32包,完成一个stm32的简单程序 1.mdk5软件中编写程序 2.stm32仿真程序调试 三、STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置的一般步骤

    2024年02月02日
    浏览(48)
  • STM32对GPIO进行基础输出操作:点亮LED灯并闪烁,跑马流水灯(标准库GPIO输出模式)

    操作STM32的GPIO需要三个步骤 第一步:RCC开启时钟 第二步:使用GPIO_Init函数初始化GPIO 第三步:使用输出或输入的函数控制GPIO口 这三个函数分别是使能或失能AHB、APB1、APB2外设时钟控制。 GPIO复位函数 DeInit复位指定的GPIO外设 AFIODeInit函数,可以复位AFIO外设 GPIO_Init函数是通过结

    2024年02月03日
    浏览(35)
  • STM32 F103C8T6学习笔记2:GPIO的认识—GPIO的基本输入输出—点亮一个LED

    今日继续学习使用  STM32 F103C8T6开发板 点亮一个LED灯,文章提供源码,测试工程,实验效果图,希望我的归纳总结会对大家有帮助~ 目录 GPIO的认识与分类 : 引脚安排整理: 定时器的引脚例举: 串口的引脚例举:  CAN串口通信: SPI通信: IIC通信:  其余引脚: 烧录引脚:

    2024年02月11日
    浏览(34)
  • STM32F103ZET6 GPIO工作模式介绍+使用寄存器点亮第一个LED灯

    目录  GPIO的工作模式介绍 1.输入模式(模拟、上拉、下拉、浮空) 2.输出模式(推挽/开漏) 3.复用功能(推挽/开漏) 4.模拟输入输出(上下拉无影响) 如何使用寄存器点亮第一个LED灯         在输入模式时,施密特触发器打开,输出被禁止。可通过输入数据寄存器 GPIOx_

    2024年02月06日
    浏览(40)
  • 手把手教你编写跑马灯——STM32

    新建一个文件夹 ,打开KeiL,projiece-----new vision projection  给文件命名(随便取)  根据自己开发板的信号选择对应的型号  在刚才创建的文件夹里面 新建一个main.c文件  双击source group 1,点击main.c,点击add  添加头文件 led.c main.c led就可以全亮然后全灭一直循环

    2024年02月08日
    浏览(33)
  • 手把手教你STM32入门教程(标准库)

    目录 前言 步骤一:准备工作 步骤二:安装Keil MDK-ARM开发工具 步骤三:创建工程 步骤四:配置工程 步骤六:编写代码 步骤七:下载程序   总结 在物联网时代,嵌入式系统的应用越来越广泛,而STM32作为业内领先的嵌入式芯片之一,受到了越来越多开发者的关注和喜爱。然

    2024年02月12日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包