STM32F429第十二篇之位带操作
发布日期:2021-05-14 11:31:21 浏览次数:27 分类:精选文章

本文共 2213 字,大约阅读时间需要 7 分钟。

前言

本文主要介绍了以位带操作为代表的F429寄存器的位操作方法。常见的寄存器位操作方法包括与或操作、位域操作和位带操作。本文将以GPIO输入输出寄存器(GPIO_ODR)为例,详细阐述三种方法的实现方式。

文章目录

  • 与或操作
  • Struct位域操作
  • 位带操作
    • 基本概念
    • 地址转换
    • 编程实现
  • GPIO置位寄存器

与或操作

与或操作是最通用的寄存器位操作方式。该方法分为两种常见操作:设置目标位为1或清除目标位为0。

  • 若需要将寄存器目标位置为1,可以执行以下运算:寄存器 |= (1 << 位数)。这种方法适用于整个寄存器,但只改变目标位。
  • 若需要将寄存器目标位清为0,可以执行以下运算:寄存器 &= ~((1 << 位数) - 1)。这种方法同样适用于整个寄存器,但只改变目标位。
  • 这种方法的优点是通用性强,适用于大多数寄存器。不过,当用于高效位操作时,其速度相对较低。这也是为其他方法(如Struct位域和位带操作)提供了基础。

    Struct位域操作

    Struct位域操作是C语言本身支持的一种高效位操作方法。这种方法通过定义一个包含每位描述的结构体,实现对寄存器每一位的独立操作。

    例如,可以定义如下的结构体:

    typedef struct{  
    unsigned int bit0 : 1;
    unsigned int bit1 : 1;
    ...
    unsigned int bit31 : 1;
    } BIT_TypeDef;

    然后,将需要操作的寄存器地址与BIT_TypeDef强制类型转换,并通过结构体成员访问目标位。例如:

    #define IOB ((BIT_TypeDef*)GPIOB_ODR_Addr)  
    IOB->bit1 = 0;

    这种方法的优点是编程简单,并且其速度和资源占用都很低。但是,它的缺点是语法复杂,且不支持位带操作的原子性访问。

    位带操作

    基本概念

    位带操作是一种高效的位操作方式,通过特定的位带区域和位带别名,实现对寄存器单个位的快速访问。这种操作方式在外设中具有广泛应用。

    位带操作的关键概念包括:

    • 位带区域:支持位带操作的存储器区域
    • 位带别名:提供对位带区域的高效访问方式

    常见的位带区域和对应的其它信息如下:

    位带区域 位带别名
    0x20000000-0x200FFFFF 0x22000000-0x23FFFFFF
    0x40000000-0x400FFFFF 0x42000000-0x43FFFFFF

    地址转换

    位带操作需要将寄存器地址转换为位带所用的字节地址。转换公式如下:

    $bit\_word\_addr = bit\_band\_base + ((address - bit\_band\_base) \times 32) + (bit\_number \times 4)$

    其中:

    • $bit\_band\_base$:位带别名的起始地址
    • $(address - bit\_band\_base)$:因子
    • $bit\_number$:目标位在字节中的位置

    例如,APB1和AHB1等外设的位带别名如下:

    外设 位带别名
    APB1 0x22000000-0x23FFFFFF
    APB2 0x42000000-0x43FFFFFF

    编程实现

    实现位带操作可以通过宏定义或特定关键字。常见的实现方法包括以下两种:

  • 宏定义方式

    #define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr &0xFFFFF) << 5) + (bitnum << 2))

    该宏定义通过按位操作生成位带操作的字节地址。

  • 属性属性方式

    typedef struct{  
    unsigned int bit0 : 1;
    ...
    unsigned int bit31 : 1;
    } __attribute__((bitband)) BB;

    定义一个带有“bitband”属性的结构体,用于实现高效位操作。例如,可以这样使用:

    BB PBO __attribute__((at(GPIOB_ODR_Addr)));
  • GPIO置位寄存器

    在GPIO中,常见的寄存器包括输入向量寄存器(IDR)和输出向量寄存器(ODR)。这些寄存器提供了对各个IO线的控制方式,通过与或操作、位域操作或位带操作实现高效的位管理。

    例如,HAL库中的实现代码如下:

    void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) {  
    assert_param(IS_GPIO_PIN(GPIO_Pin));
    assert_param(IS_GPIO_PIN_ACTION(PinState));
    if (PinState != GPIO_PIN_RESET) {
    GPIOx->BSRR = GPIO_Pin;
    } else {
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
    }
    }

    该函数通过访问GPIOx的BSRR寄存器,实现对目标位的高效操作。

    上一篇:STM32F429第十一篇之数据类型
    下一篇:STM32F429第十篇之systick

    发表评论

    最新留言

    哈哈,博客排版真的漂亮呢~
    [***.90.31.176]2025年04月30日 20时55分06秒