bit band功能,相信大家都比较熟悉了。因为在CM3时,我们就有这个功能,CM4当然也继承了。
下面,我们谈谈M471对应的CM4核的bit band。在规格书里面,新唐并未对其做很多的说明,
仅仅是一带而过。具体感兴趣的,可以去看《Cortex M3与M4权威指南.pdf》,l里面很多CM4
内核相关的,都说的比较清楚~
流程示意:
用BITBANG与不用的区别:
给出的具体转换方法:
有2除寄存器位置可以用bitband:
官方给的例子是操作SRAM的,但是这个现象不是很明显,我们这里操作外设-->GPIO来试一下:
获取GPIO的读写寄存器地址:
我们或得各个PORT对应的读写寄存器地址后,就可以着手程序了:
程序:
- //IO口操作宏定义
- #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_BASE (AHBPERIPH_BASE + 0x04000UL)
- //#define GPIOB_BASE (AHBPERIPH_BASE + 0x04040UL)
- //#define GPIOC_BASE (AHBPERIPH_BASE + 0x04080UL)
- //#define GPIOD_BASE (AHBPERIPH_BASE + 0x040C0UL)
- //#define GPIOE_BASE (AHBPERIPH_BASE + 0x04100UL)
- //#define GPIOF_BASE (AHBPERIPH_BASE + 0x04140UL)
- //#define GPIOG_BASE (AHBPERIPH_BASE + 0x04180UL)
- //#define GPIOH_BASE (AHBPERIPH_BASE + 0x041C0UL)
- //#define GPIOI_BASE (AHBPERIPH_BASE + 0x04200UL)
- //写寄存器
- #define GPIOA_DOUT_Addr (GPIOA_BASE+8) //0x40004008
- #define GPIOB_DOUT_Addr (GPIOB_BASE+8) //0x40004048
- #define GPIOC_DOUT_Addr (GPIOC_BASE+8) //0x40004088
- #define GPIOD_DOUT_Addr (GPIOD_BASE+8) //0x400040C8
- #define GPIOE_DOUT_Addr (GPIOE_BASE+8) //0x40004108
- #define GPIOF_DOUT_Addr (GPIOF_BASE+8) //0x40004148
- #define GPIOG_DOUT_Addr (GPIOG_BASE+8) //0x40004188
- #define GPIOH_DOUT_Addr (GPIOH_BASE+8) //0x400041C8
- #define GPIOI_DOUT_Addr (GPIOI_BASE+8) //0x40004208
- //读寄存器
- #define GPIOA_PIN_Addr (GPIOA_BASE+16) //0x40004010
- #define GPIOB_PIN_Addr (GPIOB_BASE+16) //0x40004050
- #define GPIOC_PIN_Addr (GPIOC_BASE+16) //0x40004090
- #define GPIOD_PIN_Addr (GPIOD_BASE+16) //0x400040D0
- #define GPIOE_PIN_Addr (GPIOE_BASE+16) //0x40004110
- #define GPIOF_PIN_Addr (GPIOF_BASE+16) //0x40004150
- #define GPIOG_PIN_Addr (GPIOG_BASE+16) //0x40004190
- #define GPIOH_PIN_Addr (GPIOH_BASE+16) //0x400041D0
- #define GPIOI_PIN_Addr (GPIOI_BASE+16) //0x40004210
- //IO口操作,只对单一的IO口!
- //确保n的值小于16!
- #define PAout(n) BIT_ADDR(GPIOA_DOUT_Addr,n) //输出
- #define PAin(n) BIT_ADDR(GPIOA_PIN_Addr,n) //输入
- #define PBout(n) BIT_ADDR(GPIOB_DOUT_Addr,n) //输出
- #define PBin(n) BIT_ADDR(GPIOB_PIN_Addr,n) //输入
- #define PCout(n) BIT_ADDR(GPIOC_DOUT_Addr,n) //输出
- #define PCin(n) BIT_ADDR(GPIOC_PIN_Addr,n) //输入
- #define PDout(n) BIT_ADDR(GPIOD_DOUT_Addr,n) //输出
- #define PDin(n) BIT_ADDR(GPIOD_PIN_Addr,n) //输入
- #define PEout(n) BIT_ADDR(GPIOE_DOUT_Addr,n) //输出
- #define PEin(n) BIT_ADDR(GPIOE_PIN_Addr,n) //输入
- #define PFout(n) BIT_ADDR(GPIOF_DOUT_Addr,n) //输出
- #define PFin(n) BIT_ADDR(GPIOF_PIN_Addr,n) //输入
- #define PGout(n) BIT_ADDR(GPIOG_DOUT_Addr,n) //输出
- #define PGin(n) BIT_ADDR(GPIOG_PIN_Addr,n) //输入
- #define PHout(n) BIT_ADDR(GPIOH_DOUT_Addr,n) //输出
- #define PHin(n) BIT_ADDR(GPIOH_PIN_Addr,n) //输入
- #define PIout(n) BIT_ADDR(GPIOI_DOUT_Addr,n) //输出
- #define PIin(n) BIT_ADDR(GPIOI_PIN_Addr,n) //输入
我们知道PH4对应KEY,PB14对应LED,在正常的GPIO初始化后,我们开始用BITBAND的模式来读取控制:
- while(1)
- {
- if(PHin(4)==0)
- {
- while(PHin(4)==0){};
- PBout(14)=~PBout(14);
- }
- }
如果按键被按下,等待按键释放后,LED切换状态。
编译,下载,查看:
新唐和其他家的不一样,它的库里面,直接就可以对GPIO PIN 单独操作,如PA5=0 类似的。
这个例子在其他家结合BITBAND 会比较简单些。
我们看看它是具体怎实现的:
先看一个例子:
#define PA0 GPIO_PIN_DATA(0, 0 )
展开定义:
#define GPIO_PIN_DATA(port, pin) (*((volatile uint32_t *)((GPIO_PIN_DATA_BASE+(0x40*(port))) + ((pin)<<2)))) /*!< Pin Data Input/Output \hideinitializer */
再展开:
#define GPIO_PIN_DATA_BASE (AHBPERIPH_BASE + 0x04800UL)
再展开:
#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral Base Address */
#define AHBPERIPH_BASE PERIPH_BASE
好,现在我们重新从下往上推:
#define GPIO_PIN_DATA_BASE ((uint32_t)0x40000000+ 0x04800UL)
我们查看:
可见 GPIO_PIN_DATA_BASE 对应的是GPIO PA.n Pin Data Input/Output Register
根据表格得,每一个PORT的GPIO_PIN_DATA_BASE 地址相差0x40
对应某一个PORT 的GPIO_PIN_DATA_BASE其内部的0~15 引脚地址关系:在这个地址上再加上0x04*n (n=0~15)
那也就是 ((pin)<<2)) (pin:0~15)
那么:#define PA0 GPIO_PIN_DATA(0, 0 )
这个宏,其实就是定义到对应PORT 对应pin的 PAn_PDIO寄存器上面,我们查看PDIO寄存器:
我去,这个寄存器太好了,直接能读,又能写,比我们之前分开的那个好多了~
ST是没有这个,NXP的有类似的~
好了,bitband就到这了,谢谢观看~
|