STM32入门:三种编写跑马灯程序的方法详解

前言

本文分别通过库函数、寄存器以及位操作完成跑马灯实验,使用的开发板是正点原子的min核心板。

一、库函数

1.1 硬件连接

图1 LED 与 STM32 连接原理图

 通过min板的原理图可以看出两个LED灯分别接到PD2和PA8引脚,并且LED灯是共阳极,当IO口输出高电平,LED灭;输出低电平,LED亮。

在实际的程序编程中我们需要用到GPIO文件也就是stm32f10x_gpio.h和stm32f10x_gpio.c,来操作对应IO口。同时我们需要设置时钟就要用到stm32f10x_rcc.c与其头文件进行时钟使能。

1.2 GPIO库函数介绍

  • 重要函数

  • 1个初始化函数:

    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

    主要用途是用来初始化GPIO口的状态

    第一个参数是一个结构体类型变量,指定哪组IO口,第二个同样是一个结构体类型变量,它共有三个变量,第一个指定哪个IO口,第二个指定速度,第三个指定Mode模式。

    GPIO_Init函数初始化样例:

    GPIO_InitTypeDef GPIO_InitStructure;
    
    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

    2个读取输入电平函数:

    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, unit16_t GPIO_Pin);

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

    例如:

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

    uint16_t GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

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

    例如:

    GPIO_ReadInputData(GPIOA);//读取GPIOA组中所有io口输入电平

    2个读取输出电平函数:

    uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

    uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

    上面两个函数的作用与读取输入电平大致相同,不同处在于这里读取的是某组或某个GPIO的输出电平。实际操作的是GPIO_ODR寄存器

    4个设置输出电平函数:

    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

    作用:设置某个IO口输出为高电平(1)。实际操作BSRR寄存器。
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

    作用:设置某个IO口输出为低电平(0)。实际操作BRR寄存器。
    void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
    void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

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

    所有的函数都是在主函数中设置寄存器的值,例如SetBits使用了BSRR,ResetBit使用了BRR寄存器。

    1.3 跑马灯程序

    库函数——步骤:

  • 使能IO口时钟。调用函数RCC_APB2PeriphColckCmd();       
  •         不同的IO组,调用的始终使能函数不一样。

  • 初始化IO口模式。调用函数GPIO_Init();
  • 操作IO口,输出高低电平。
  •         GPIO_SetBits();

            GPIO_ResetBits();

    注意:操作IO口之前,必须使能对应的时钟位。

    在项目中新建一个HAREWARE文件夹,在其中新建程序文件夹,创建对应c文件与头文件,例如led.h与LED.c,在led.h头文件中定义LED_Init函数。

    注意这里需要将对应头文件路径加入项目中来。以下是本次程序LED.c的代码内容,实现两个LED灯初始化。

     接下来在USER文件夹中编写main函数,

     编写完后利用flymcu烧录至开发板中,两个LED灯将同时点亮,间隔500毫秒后又同时熄灭,循环往复。

    二、寄存器

    2.1 硬件连接

    连接如库函数。

    2.2 跑马灯程序

    寄存器——步骤:

  • 使能IO口时钟。配置寄存器RCC_APB2ENR;
  • 初始化IO口模式。配置寄存器GPIOx_CRH/CRL;
  • 操作IO口,输出高低电平。配置寄存器GPIOX_ODR或者BSRR/BRR。
  • 2.2.1 使能IO口时钟

     

     mini板的LED引脚分别为PA8和PD2,所以选择配置寄存器RCC_APB2ENR的位5和位2如上面原理图所示。

    同样在项目中新建HAREWARE文件夹,其余操作步骤如库函数,在led.h头文件中定义LED_Init函数,首先我们需要操作RCC寄存器,它的定义在stm23f10x.h中,可以看到定义中使用RCC结构体指针定义了所有寄存器,在代码中我们将RCC指向APB2ENR来操作寄存器。

    2.2.2 初始化IO口模式

     接下来操作端口配置寄存器,我们需要用GPIOx结构体指针指向该寄存器,配置为通用推挽输出模式,最大速度50MHz,对应到寄存器的每一个位是0011B,实际代码中先将对应位清零再进行配置,调用GPIOx的ODR寄存器,拉高需要操作的相应位。

    2.2.3 操作IO口

     main.c里面把stm32f10x.h、delay.h、led.h头文件包含进来,主函数中调用delay_init和LED_Init初始化函数,随后进入while死循环,在死循环中同样可以直接用ODR寄存器对LED进行操作。

     

     程序编写完毕后烧录至开发板实现跑马灯功能。

    三、位操作

    3.1 位操作基本原理

    位操作原理:

    把每个比特膨胀为一个32位的字,当访问这些字的时候就达到了访问比特的目的,比如说BSRR寄存器有32个位,那么可以映射到32个地址上,我们去访问(读-改-写)这32个地址就达到访问32个比特的目的。

    哪些区域支持位操作:

     

     由于位带区一个位对应32位的地址,所以位带区1MB对应别名区32MB。

     映射关系:

  • 位带区:支持位带操作的地址区

  • 位带别名:对别名地址的访问最终作用到位带区的访问上

  • 3.2 硬件连接

    硬件连接与前两个方法相同。

    3.3 跑马灯程序

    具体的代码实现里面,实际上运用的就是映射关系,比如要操作PA,就会宏定义一个PAout()函数,他的原理实际上就是在操作ODR寄存器,相应的,PAin()函数就是操作IDR寄存器,所有方法的最终原理都是操作寄存器,这是永恒不变的。

    //IO口地址映射
    #define GPIOA_ODR_Addr    (GPIOA_BASE+12)    //0x4001080c
    
    //IO口操作,针对单一IO口
    #define PAout(n)    BIT_ADDR(GPIOA_ODR_Addr,n)    //输出
    #define PAin(n)     BIT_ADDR(GPIOA_IDR_Addr,n)    //输入

    位操作——步骤:

  • 使能IO口时钟。调用函数RCC_APB2PeriphColckCmd();
  • 初始化IO口模式。调用函数GPIO_Init();
  • 操作IO口,输出高低电平。使用位带操作
  • 大体上位操作的步骤和库函数相同,其使用的模板与库函数相同。

    3.3.1 使能IO口时钟

    与库函数版本程序代码相同。

    3.3.2 初始化IO口模式

    与库函数版本程序代码相同。

    3.3.3 操作IO口

    在这里只需要通过宏定义的位带函数操作LED灯即可。

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32入门:三种编写跑马灯程序的方法详解

    发表评论