赞
踩
首先需要明确下,位段,位带和别名区这三个名词
位段:STM32用户参考手册使用的名字
位带:CortexM3参考手册使用的
别名区:地址总线上用来位访问地址区域,
所以说,位段和位带是一个意思,是不同手册的不同叫法。
位带别名区把每个比特膨胀成一个 32 位的字
处理器存储器映射包括两个 bit-banding 区域。它们分别为 SRAM 和外设存储区域中的最低的 1MB。这些 bit-band 区域将存储器别名区的一个字映射为 bit-band 区的一个位。
Cortex-M3 存储器映射有 2 个 32MB 别名区,它们被映射为两个 1MB 的 bit-band 区。
支持位带操作的两个内存区的范围是:
0x2000 0000~0x200F FFFF
SRAM 区中最低1MB区域0x2200 0000
0x4000 0000~0x400F FFFF
片上外设区中的最低1MB区域0x4200 0000
下面的映射公式给出了别名区中的每个字是如何对应位带区的相应位的:
bit_word_addr = bit_band_base + (byte_offset×32) + (bit_number×4)
其中:
注意:别名字的位[31:1]在 bit-band 位上不起作用,仅第0位起作用。写入 0x01 与写入 0xFF 的效果相同。写入0x00 与写入 0x0E 的效果相同。
读别名区的一个字返回 0x01 或 0x00。0x01 表示 bit-band 区中的目标位置位。0x00 表示
目标位清零。位[31:1]将为 0。
采用大端格式时,对 bit-band 别名区的访问必须以字节方式。否则访问值不可预知。
#define BITBAND(addr, bit) (*(volatile unsigned long*)((addr & 0xF0000000U) + 0x2000000U + ((addr & 0xFFFFFFU) << 5U) + (bit << 2U)))
当你使用位带功能时,要访问的变量必须用 volatile 来定义。因为 C 编译器并不知道同一个比特可以有两个地址。所以就要通过 volatile,使得编译器每次都如实地把新数值写入存储器,而不再会出于优化的考虑。
以STM32F103C8T6为例,GPIO输出输入的位带代码。
#ifndef __BITBAND_H_ #define __BITBAND_H_ #include "stm32f1xx.h" /* 位带别名区计算公式 */ #define BITBAND(addr, bit) (*(volatile unsigned long*)((addr & 0xF0000000U) + 0x2000000U + ((addr & 0xFFFFFFU) << 5U) + (bit << 2U))) /* 输出寄存器 */ #define GPIOA_ODR_ADDR (GPIOA_BASE + 0x0CU) #define GPIOB_ODR_ADDR (GPIOB_BASE + 0x0CU) #define GPIOC_ODR_ADDR (GPIOC_BASE + 0x0CU) #define GPIOD_ODR_ADDR (GPIOD_BASE + 0x0CU) #define GPIOE_ODR_ADDR (GPIOE_BASE + 0x0CU) /* 输入寄存器 */ #define GPIOA_IDR_ADDR (GPIOA_BASE + 0x08U) #define GPIOB_IDR_ADDR (GPIOB_BASE + 0x08U) #define GPIOC_IDR_ADDR (GPIOC_BASE + 0x08U) #define GPIOD_IDR_ADDR (GPIOD_BASE + 0x08U) #define GPIOE_IDR_ADDR (GPIOE_BASE + 0x08U) /* GPIO输出 */ #define PAout(n) BITBAND(GPIOA_ODR_ADDR, n) #define PBout(n) BITBAND(GPIOB_ODR_ADDR, n) #define PCout(n) BITBAND(GPIOC_ODR_ADDR, n) #define PDout(n) BITBAND(GPIOD_ODR_ADDR, n) #define PEout(n) BITBAND(GPIOE_ODR_ADDR, n) /* GPIO输入 */ #define PAin(n) BITBAND(GPIOA_IDR_ADDR, n) #define PBin(n) BITBAND(GPIOB_IDR_ADDR, n) #define PCin(n) BITBAND(GPIOC_IDR_ADDR, n) #define PDin(n) BITBAND(GPIOD_IDR_ADDR, n) #define PEin(n) BITBAND(GPIOE_IDR_ADDR, n) #endif /* __BITBAND_H_ */
选用单片机STM32F103C8T6
GPIO推挽输出实现LED灯亮灭翻转实验
PC13控制LED的亮灭
主要代码如下
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* 采用位带操作实现LED翻转 */
PCout(13) = !PCin(13);
/* 采用HAL库操作实现LED翻转 */
//HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(1000);//延时1000毫秒
}
/* USER CODE END 3 */
工程文件下载链接
参考资料下载链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。