当前位置:硬件测评 > 【STM32学习笔记】:跑马灯实验详解

【STM32学习笔记】:跑马灯实验详解

  • 发布:2023-10-01 11:05

跑马灯实验

在前面的五篇STM32学习笔记中,我们已经对STM32芯片以及STM32的常用寄存器有了初步的了解,介绍了STM32的GPIO模式、STM32工程文件,最后讲解了如何添加源文件和头文件STM32 文件步骤。不过前面的知识只能说是理论和基础,但却非常重要。如果STM32的理论知识不扎实,就会导致在后续的开发项目中给自己一种没有学过STM32的感觉,仿佛自己是一片飘浮的浮萍。在水上。因此,在开发STM32项目的过程中,当我们遇到需要学习一些理论知识的时候,一定要补充自己的理论知识,并在实践中检验自己学习的效果。

GPIO简介

                                                                                                                                                                                                                                                  GPIO 是通用输入输出端口的缩写。 STM32芯片的GPIO分为很多组,每组有16个引脚。例如芯片型号为STM32F103ZET6,共有7组GPIO,从GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF到GPIOG,芯片共有144个引脚。其中GPIO占很大一部分,所有GPIO引脚都具有基本的输入输出功能。

最基本的输出功能是通过STM32控制引脚输出高低电平,实现开关控制。例如,GPIO引脚连接LED灯,可以控制LED灯的亮灭,该引脚连接继电器或晶体管,则可以通过继电器或晶体管来控制LED灯的亮灭。关闭外部大功率电路。

最基本的输入功能就是检测外部输入电平,比如将GPIO引脚连接到按钮上,通过电平来区分按钮是否被按下。

固件库中,GPIO口操作对应的库函数及相关定义在文件stm32f10x_gpio.h和stm32f10x_gpio.c中。

字幕硬件连接

本章使用的硬件仅为 LED(DS0 和 DS1)。其电路已默认连接在ALIENTEK Elite STM32F103开发板上。 DS0连接到PB5,DS1连接到PE5。所以不需要碰硬件上的任何东西。因为LED发光二极管的阳极串联了一个510欧姆的电阻到VCC3.3V电源。 LED发光二极管的负极连接到芯片的GPIO端口。如果要控制发光二极管发光,需要将GPIO输出的电平拉低,电流就会流过发光二极管。当电流流过时,发光二极管就会发光。当两个GPIO输出的电平连续拉高或拉低时,可以实现LED闪烁或跑马灯效果。

注:510欧电阻有两个作用:

  1. 用作上拉电阻。
  2. 起到限流电阻的作用,防止流过发光二极管的电路过大而烧坏。

跑马灯编程

我们跑马灯实验主要用到的固件库文件是:

                                             stm32f10x_gpio.h ?

           其他c.c

                                                                                  每个实验都必须引入stm32f10x_rcc.h头文件,因为系统时钟配置函数和相关外设时钟使能函数都在这个源文件stm32f10x_rcc.c中。我们的SYSTEM文件夹中需要stm32f10x_usart.h和misc.h头文件,因此在每次实验中都会引用它们。

选取框中使用的库函数

1。 GPIO初始化函数

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
/*功能:初始化一个或多个IO口(同组)的工作模式、输出类型、速度和下拉方式。也就是一组IO
端口的四个配置寄存器。
*/
类型定义结构
{
uint16_t GPIO_Pin;
//指定要配置的GPIO引脚。该参数可以是@ref GPIO_pins_define的任何值
GPIOSpeed_TypeDef GPIO_Speed;
//指定所选引脚的速度。该参数可以是ref GPIOSpeed_TypeDef成员变量中的值
GPIOMode_TypeDef GPIO_Mode;
//指定所选引脚的工作模式。该参数可以是GPIOMode_TypeDef成员变量中的值
}GPIO_InitTypeDef;
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< 选择引脚 0 */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< 选择引脚 1 */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< 选择引脚 2 */
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< 选择引脚 3 */#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< 选择引脚 4 */
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< 选择引脚 5 */
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< 选择引脚 6 */
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< 选择引脚 7 */
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< 选择引脚 8 */
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< 选择引脚 9 */
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< 选择引脚 10 */
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< 选择引脚 11 */
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< 选择引脚 12 */
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< 选择引脚 13 */
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< 选择引脚 14 */
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< 选择引脚 15 */#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< 选择所有引脚 */
#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))
#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \
((PIN) == GPIO_Pin_1) || \
((PIN) == GPIO_Pin_2) || \
((PIN) == GPIO_Pin_3) || \
((PIN) == GPIO_Pin_4) || \
((PIN) == GPIO_Pin_5) || \
((PIN) == GPIO_Pin_6) || \
((PIN) == GPIO_Pin_7) || \
((PIN) == GPIO_Pin_8) || \
((PIN) == GPIO_Pin_9) || \
((PIN) == GPIO_Pin_10) || \
((PIN) == GPIO_Pin_11) || \
((PIN) == GPIO_Pin_12) || \
((PIN) == GPIO_Pin_13) || \
((PIN) == GPIO_Pin_14) || \
((PIN) == GPIO_Pin_15))

GPIO_InitTypeDef结构体中已经初始化了成员变量,所以在调用这个初始化函数时,我们首先需要给GPIO_InitTypeDef成员变量赋值。

但是给GPIO_InitTypeDef的成员变量赋值时,赋值的内容需要满足对应结构体类型中的成员变量。

例如:GPIO_Mode的结构体类型为GPIOMode_TypeDef,那么为其赋值的内容需要从下面的结构体中的成员变量中选择。

typedef 枚举
{GPIO_模式_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_模式_IPD = 0x28,
GPIO_模式_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_模式_输出_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_模式_AF_PP = 0x18
}GPIOMode_TypeDef;
#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \
((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \
((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \
((MODE) == GPIO_Mode_AF_OD) || ((模式)== GPIO_Mode_AF_PP))

             GPIO_Speed的结构体类型为GPIOSpeed_TypeDef,所以为其赋值的内容需要从下面结构体中的成员变量中选择。

typedef 枚举
{
GPIO_速度_10MHz = 1,
GPIO_速度_2MHz,
GPIO_速度_50MHz
}GPIOSpeed_TypeDef;
#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \
((速度)== GPIO_Speed_50MHz))

2。两种读取输入电平功能

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

功能:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

参数: 1. GPIOx:其中x可以是(A..G)来选择GPIO外设。

2. GPIO_Pin:指定要读取的端口位。

返回值:输入端口引脚值。

例如:

GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输入电平

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

功能:读取某组GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

参数: GPIOx:其中 x 可以是(A..G)以选择 GPIO 外设。

返回值:GPIO输入数据端口值。

例如:

GPIO_ReadOutputData(GPIOA);//读取GPIOA组中所有io口的输出电平

3。两个读取输出电平功能

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);

功能:读取某个GPIO的输出电平。实际操作的是GPIO_ODR寄存器。

参数: 1. GPIOx:其中x可以是(A..G)来选择GPIO外设。

2. GPIO_Pin:指定要读取的端口位。

返回值:输出端口引脚值。

例如:

GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输出电平

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

功能:读取某组GPIO的输出电平。实际操作的是GPIO_ODR寄存器。

参数: GPIOx:其中 x 可以是 (A..G) 以选择 GPIO 外设。

返回值:GPIO输入数据端口值。

例如:

4。四种设置输出电平功能

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

功能:设置某个IO口输出为高电平(1)。 BSRRL寄存器的实际操作

参数: 1. GPIOx:其中x可以是(A..G)来选择GPIO外设。

2. GPIO_Pin:指定要写入的端口位。

返回值:无

例如:

                 GPIO_SetBits(GPIOA, GPIO_Pin_5); //设置GPIOA.5输出电平为高电平

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

功能:设置某个IO口的输出为低电平(0)。 BSRRH寄存器的实际操作。

参数: 1. GPIOx:其中x可以是(A..G)来选择GPIO外设。

        2. GPIO_Pin:指定要写入的端口位

返回值:无

例如:

              GPIO_ResetBits (GPIOA, GPIO_Pin_5); // 设置GPIOA.5输出电平为低电平

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

功能:设置或清除所选数据端口位。

参数: 1. GPIOx:其中x可以是(A..G)来选择GPIO外设。

2. GPIO_Pin:指定要写入的端口位。

3. BitVal:指定要写入所选位置的值。

此参数可以是 BitAction 枚举值之一:

typedef 枚举

{

E Bit_reset = 0, // bit_reset: 清除端口引脚

T Bit_set // Bit_set:设置端口引脚

}BitAction;

#define IS_GPIO_BIT_ACTION(ACTION) (((ACTION) == Bit_RESET) || ((ACTION) == Bit_SET))

返回值:无

例如:

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

功能:向指定GPIO数据口写入数据。

参数: 1. GPIOx:其中x可以是(A..G)来选择GPIO外设。

            2. PortVal:指定要写入端口输出数据寄存器的值。 。

返回值:无

例如:

R GPIO_WRITE(GPIOA,1);将数据“1”写入指定的GPIOA数据端口。

后两个函数不常用,也是用来设置IO口输出电平的。

编写跑马灯实验的步骤:

1. 使能IO口时钟。调用函数RCC_AHB1PeriphClockCmd();

            不同外设调用的时钟使能函数可能不同

2. 初始化GPIO端口模式。调用GPIO_Init();将目标引脚设置为推挽输出模式;

3、编写一个简单的测试程序,控制GPIO引脚输出高低电平。

跑马灯源文件和头文件中的代码

头文件中的代码:

#ifndef __LED_H
#定义__LED_H
void LED_Init(void);//初始化
#万一

源文件中的代码:

#include "led.h"
//初始化PB5和PE5为输出端口,并打开这两个端口的时钟。
//LED IO初始化
无效LED_Init(无效)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,启用); //使能PB和PE口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设置的参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5输出高电平
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5口配置,推挽输出GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5输出高电平
}

跑马灯实验中main函数中的代码

    main.c中的代码:

#include "delay.h"
#include“led.h”
/**
******************下面您看到的代码是通过调用库函数实现IO控制的方法**************** ** **********************
int 主函数(无效)
{
延迟初始化(); //初始化延时函数
LED_Init(); //初始化LED端口
同时(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉低并点亮
GPIO_SetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5被拉高并关闭
延迟毫秒(300); //延迟300ms
GPIO_SetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5被拉高并关闭 GPIO_ResetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5被拉低并亮
延迟毫秒(300); //延迟300ms
}
}

函数执行流程如下:

(1) 使用GPIO_InitTypeDef定义GPIO初始化结构体变量,以便可以使用它来存储下面的GPIO配置。

                 (2) 调用库函数RCC_APB2PeriphClockCmd,使能LED灯的GPIO口时钟。该函数的调用和细节将在后面的文章中讲解。

(3) 给GPIO初始化结构体赋值,并将引脚初始化为推挽输出模式。

(4) 利用上述初始化结构体的配置,调用GPIO_Init函数向寄存器写入参数,完成GPIO的初始化。

(5) 然后使用两个GPIO库函数GPIO_SetBits()和GPIO_ResetBits(),在设置低电平和设置高电平之间延迟一段时间,实现两个LED灯轮流的实验。目的。

相关文章

最新资讯