位带操作(Bit-banding Operation)是一种在嵌入式系统中的编程技术,用于对单独的位(bit)进行读取和写入操作,以方便对特定位进行控制和操作。
在嵌入式系统中,内存按字节(Byte)进行寻址,而数据通常以比特(Bit)的形式进行操作。位带操作技术通过将每个比特映射到一个独立的内存位置,使得可以直接对一个比特进行读取和写入操作,而不需要额外的位操作指令。
在位带区中,通常将每个字节(Byte)的每个比特都映射到一个对应的位带别名地址。这些位带别名地址被用于访问位带区,可以通过读取或写入位带别名地址来操作相应的位。由于每个比特都有独立的地址,因此可以直接对其中的某个比特进行读取或写入操作,而无需使用位操作指令或遮罩操作。
2.位带别名区(Bit-band Alias Region)是一种在某些嵌入式系统中的内存映射区域,用于实现位带操作技术。
在位带别名区中,每个比特(Bit)都被映射到一个真实的内存地址。通常,每个字节(Byte)的位带别名区域将比特和字节的内存地址相关联。这种映射关系使得可以使用普通的内存访问指令来对单个比特进行读取和写入操作。
位带区与位带别名区的膨胀关系图A
位带区与位带别名区的膨胀关系图B
程或中断处理等并发环境下,不会出现竞争条件(Race condition)的问题。位带操作可以确保对比特的操作是稳定和可靠的。
地址,可以使用常规的内存访问指令,而不需要通过位操作运算符和位操作指令来实现对特定位的访问和控制。这样可以降低代码的复杂性和维护成本。
常更高效。这是因为位带操作可以直接读取和写入单个比特,而不需要对整个字节进行访问和操作。这降低了内存带宽的占用,并减少了 CPU 的计算和周期消耗。
号,但位带操作的概念和原理是相对通用的。这意味着一旦掌握了位带操作的基本知识和技巧,可以在不同的嵌入式平台上进行迁移和应用。
注意:位带操作不一定适用于所有的嵌入式系统和芯片。在使用位带操作时,应仔细阅读相关芯片的文档和手册,并了解具体的实现细节和使用方法。!!!!
2.代码如下
#ifndef __IO_BIT_H
#define __IO_BIT_H
#include "stm32f4xx.h"
#include
#include
#include
#define BYTE0(dwTemp) (*( char *) (&dwTemp))
#define BYTE1(dwTemp) (*((char *) (&dwTemp) + 1))
#define BYTE2(dwTemp) (*((char *) (&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *) (&dwTemp) + 3))
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<>第五章(87页~92页).
//IO口操作宏定义 //(addr & 0xF0000000)获得SRAM的地址或者外设地址
//0x2000000补偿,,基地址
//(addr &0xFFFFF) 我们只需要的到1M偏移
// <<5 地址膨胀*32
// (bitnum<<2) 写进去的偏移值(N)*4 4个字节
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40011E08
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#endif
注意:所写的文章均用于记录作者的学习过程!!!!!