STM32 neutral band operation

Bitband operations in stm32

1. Review of basic concepts

1…What are bit operations? Bit operation means that you can read and write
a single bit individually . 2. What is a bit band operation? After supporting bit band operations, you can use ordinary load/store instructions to read and write single bits. In CM3, bitbanding is implemented in two zones. One of them is the lowest 1MB range of the SRAM area, and the second is the lowest 1MB range of the on-chip peripheral area. In addition to being used like ordinary RAM, the addresses in these two bit bands also have their own "bit band alias areas" that expand each bit into a 32-bit word. When you access these words through the bitband alias area, you can access the original bits. 3. What is the bitband area? The bit band area is the area of ​​IO that you want to operate alone, that is, the area where the memory of PA, PB, etc., and this bunch of IO ports are located. 4. What is the bit band alias area? The bit band alias area is the address area where you give each bit a new name. 5. The operating formula of the bit band area and the bit band alias area 1. For a certain bit in the SRAM bit band area, record the word where it is located The section address is A and the bit number is n (0<=n<=7). Then the address of this bit in the alias area is:







 AliasAddr=0x22000000+((A-0x20000000)*8+n)*4 =Ox22000000+ (A-Ox20000000)*32 +n*4

2. For a certain bit in the on-chip peripheral bit band area, record the address of the byte where it is located as A and the bit sequence number as n (<=n<=7), then the address of the bit in the alias area is:

AliasAddr=0x42000000+((A-0x40000000)*8+n)*4 =0x42000000+ (A-Ox40000000)*32 +n*4

5. Why are the operating formulas of the bitband area and bitband alias area like this?
5.1 Let’s look at the memory image first.
Insert image description here
In Figure 6.4 above, the FLASH, RAM, FSMC and AHB to APB bridge of the controlled unit (i.e. on-chip peripherals), these functional components are arranged together in a 4GB address space. When we are programming, we can find them by their addresses and then operate them. (Read and write data through C language)
Insert image description here
In this 4GB address space, ARM has been roughly divided into 8 blocks, each block is 512MB, and each block has its own purpose. See Table 6 for specific classifications. -1. Each block is 512MB in size, which is obviously very large.
Insert image description here
We know that in CM3, bit bands are implemented in two places, one is the minimum 1MB space in the SRAM area. One is the minimum 1MB space in the peripheral area.
Insert image description here

 AliasAddr=0x22000000+((A-0x20000000)*8+n)*4 =Ox22000000+ (A-Ox20000000)*32 +n*4
/*
则在SRAM区
AliasAddr是别名区的地址
0x22000000是SRAM位带别名区的起始地址
A是SRAM位带区的某个比特,记它所在字节的地址为A,位序号为n(0<=n<=7)
(A-0x20000000)代表该比特前面有多少个字节,一个字节8位所以乘以8,
一个位膨胀后是4字节,所以乘以4.n表示该比特在A地址的序号,因为一
个位膨胀后是4字节,所以也*4
*/

2. How to perform bit band operation

If you want to perform a bit band operation to operate a certain bit of an IO port, then in the STM32 environment, you should find the address of the alias area corresponding to the bit, find this address, and operate on this address, then actually The above is to operate on this bit.

2.1 Unified formula:
1 //把"位带地址+位序号"转换成别名地址的宏
2 #define BITBAND(addr, bitnum)  ((addr & 0xF0000000)+0x02000000+ ( (addr & 0x00FFFFFF)<<5)+(bitnum<<2))
/*
addr & 0xF0000000是为了区别SRAM还是外设,实际效果就是取出4或者2,如果是外设则取出4+0x02000000就是0x42000000
addr & 0x00FFFFFF 屏蔽了高三位,相当于减去0x20000000或者0x40000000
为何屏蔽高三位?
因为外设地址最高地址是:0x20100000,和起始地址0x20000000之间相减时候
总是低五位才有效,所以才把高三位屏蔽来达到减去地址的效果,而<<5相当于
*4*8.<<2相当于*4
*/
2.2GPIO bit band operation example

Here we operate by setting GPIOx_IDR (port input data register) and GPIOx_ODR (port output data register).
Insert image description here
Insert image description here

According to the data manual, the offset address of GPIOx_IDR is 0x10 (16) and the offset address of GPIOx_ODR is 0x14 (20)
:

#ifndef __LED_H__
#define __LED_H__

//IO口操作宏定义
#define BITBAND(addr, bitnum) (0x42000000 +((addr-0x40000000)<<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) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
 //单一IO口操作
#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) 

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n) 

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  
//°´¼ü³õʼ»¯º¯Êý
void led_init(void);

#endif

Just call it in the main function

#include "stm32f4xx.h"
#include "led.h"

//延时
void delay(int x)
{
    
    
	int i,j;
	for(i=0;i<x;i++)
		for(j=0;j<10000;j++);
}

int main()
{
    
    
	led_init();
	while(1)
	{
    
    
			PAout(6)=0;//设置PA6为低电平,点亮led灯
		delay (100);
			PAout(6)=1;//设置PA6为高电平,熄灭led灯
		delay (100);
	}

}

Guess you like

Origin blog.csdn.net/qq_44772972/article/details/113354631