Operação de banda de STM32(4) bits

O motivo para escrever a operação de banda de bits é que, quando usei o MCU da série ch32v30x da Qinheng, transplantei alguns códigos periféricos no STM32, mas descobri que o STM32 usava muitas operações de banda de bits para a parte GPIO e o ch32 baseado no RISC-V não há nenhuma operação de banda de bits, então revisito especialmente o princípio de operação de banda de bits do STM32.


1. O que é operação de banda de bits

Nas palavras dos livros didáticos, bit banding (Bit Banding), operação de bit significa que um bit pode ser lido e escrito separadamente, o que é muito comum em 51 microcomputadores de chip único. 51 A palavra-chave sbit é usada para realizar a definição de bit no MCU.STM32 não possui tal palavra-chave, mas é realizada acessando a área de alias da banda de bits.
  No STM32, há dois locais onde as bandas de bits são implementadas, um é o menor espaço de 1 MB na área SRAM e o outro é o menor espaço de 1 MB na área periférica. Esses dois espaços de 1 MB podem ser operados como RAM normal e também possuem sua própria área de alias de bits. A área de alias de bits expande cada bit do espaço de 1 MB em uma palavra de 32 bits. Ao acessar bits Ao usar essas palavras na área de alias , o objetivo de acessar um determinado bit na área de banda de bits pode ser alcançado. Ele implementa operações de leitura e gravação em bits individuais, mapeando cada bit de memória para um espaço de endereço independente.
Especificamente, as operações de banda de bits são implementadas mapeando um endereço de memória de 32 bits para outro espaço de endereço de 32 bits. Por exemplo, suponha que queremos operar no 0º bit de uma variável, então o endereço da variável pode ser mapeado para um novo espaço de endereço por meio de uma banda de bits, e o 0º bit do espaço de endereço corresponde ao 0º bit do variável de endereço original.Isto permite que o bit seja lido ou escrito diretamente sem ter que ler ou escrever toda a variável.

Em termos humanos, se o STM32 deseja executar operações em nível de bit no pino 1 do PA , por exemplo, isso não pode ser realizado diretamente . Para operar e atribuir esse bit separadamente, é necessário usar a operação de banda de bits. Mapeie este bit para outro espaço de memória com um comprimento de 32 bits, ou seja, 4 bytes, ou seja , dê a este 1 bit um alias, mas você pode operar diretamente este alias, o efeito é equivalente ao mapeamento para o nome real . Expanda o endereço original de PA1 em um endereço de palavra de 32 bits e opere no endereço de 32 bits.
De forma mais geral, quero comer uma das três frutas: melancia, maçã e pêra, mas há restrições claras e não posso comer frutas com nomes específicos. Então chamarei a melancia de fruta que cresce em o chão, maçã Chama-se a fruta que cresce na árvore, então, eu posso, e o que eu como é a fruta que cresce no chão. Na verdade, o que eu como é melancia, contornando essa restrição, e ao mesmo tempo tempo comendo a fruta específica que eu quero comer.

2. Banda de bits e área de alias de banda de bits

1. Banda de bits periféricos

O endereço da área periférica é: 0X40000000~0X40100000 , e o tamanho é 1 MB. O tamanho deste 1 MB inclui todos os registros dos periféricos no chip na série 103 de MCUs de grande/média/pequena capacidade. O endereço destes registradores é: 0X40000000 ~0X40029FFF.
O endereço da área de alias de banda de bits expandida da área de banda de bits periférica é 0X42000000~0X43FFFFFF , e esse endereço ainda está no espaço de endereço do periférico no chip CM3. Nos microcontroladores de grande/médio e pequena capacidade da série 103, 0X40030000~0X4FFFFFFF é um endereço reservado, e a área de alias de bit expandida de 32 MB apenas cai dentro dessa faixa de endereço e não coincidirá com outros endereços de registro de periféricos no chip.
  Todos os registradores do STM32 podem alcançar o efeito de acessar os bits originais do registrador acessando a área de alias da banda de bits, que é muito mais poderosa do que o microcomputador de 51 chips únicos. Como nem todos os registradores no microcomputador de chip único 51 podem ser operados por bits, alguns registradores ainda precisam ser operados por bytes, como o SBUF.
  Embora seja dito que todos os registradores podem implementar operações de bit, não faremos isso em projetos reais, ou mesmo o faremos. Às vezes, para necessidades específicas do projeto, como operação frequente de muitas portas IO, neste momento podemos considerar a implementação de operações de bit em registradores relacionados a IO.

2. Banda de bits SRAM

O endereço da área de banda de bits da SRAM é: 0X2000 0000~X2010 0000 , o tamanho é de 1 MB e o endereço da área de alias de banda de bits após a expansão é: 0X2200 0000 ~ 0X23FF FFFF, o tamanho é de 32 MB. Bits para manipular SRAM raramente são usados.

3. Relação de mapeamento de endereço

Tome a área de banda de bits periférica como exemplo:
Para um bit na área de banda de bits periférica no chip , registre o endereço do byte onde ele está localizado como A e o número do bit como n (0<=n<=7) , então o bit está na área de alias O endereço é:
  AliasAddr= =0x42000000+ (A-0x40000000)✖8✖4 +n✖4
0x42000000 é o endereço inicial da área de alias da zona de bits, A é o endereço dos dados de saída registrar GPIOA->ODR, o endereço de A é primeiro subtraído O endereço base da área de banda de bits é o endereço de deslocamento relativo ao endereço de base da área de banda de bits. Após a expansão, ainda é um endereço de deslocamento, que é o deslocamento relativo ao endereço base da área de alias da banda de bits, mais o endereço base da área de alias da banda de bits. Este é o princípio geral, um byte tem 8 bits, então ✖8, um bit é expandido para 4 bytes, então multiplique por 4, n significa que o bit está em A O número de série do endereço, porque um bit é expandido para quatro bytes, também é multiplicado por 4.

3. Use exemplos

1. Definição de macro de operação de banda de bits

Um exemplo de STM32 frequentemente encontrado aqui é a operação de entrada e saída GPIO. O código específico é:

//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//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)) 

BITBAND(addr, bitnum) : Usado para mapear um endereço e um número de bit no espaço de endereço bitband. Especificamente, ele mapeia o endereço addr e o número de bit bitnum para um espaço de endereço entre 0x20000000~0x3FFFFFFF e retorna o endereço correspondente no espaço de endereço.
Em termos humanos, addr & 0xF0000000 é para distinguir entre SRAM e periféricos. O efeito real é remover 4 ou 2. Se for um periférico, remove 4. Depois de +0X02000000, é igual a 0X42000000 e 0X42000000 é o endereço inicial da área de alias periférico. addr & 0x00FFFFFF protege os três bits superiores, o que equivale a subtrair 0X20000000 ou 0X40000000, mas por que os três bits superiores são protegidos? Como o endereço mais alto do periférico é: 0X2010 0000, ao subtrair o endereço inicial 0X20000000, os 5 bits inferiores são sempre válidos, portanto, basta mascarar os três bits superiores para obter o efeito de subtrair o endereço inicial. <<5 é multiplicar o valor da esquerda por 2 elevado a 5, ou seja, deslocar 5 bits para a esquerda equivale a multiplicar o valor da esquerda por 32. Da mesma forma, <<2 é multiplicar por 4, e bitnum é o número de série do bit específico.

MEM_ADDR(addr) : Usado para converter um endereço em um ponteiro para o endereço. Especificamente, ele converte o endereço addr em um ponteiro para uma variável volátil do tipo unsigned long.

BIT_ADDR(addr, bitnum) : usado para mapear um endereço e um número de bit no espaço de endereço de banda de bits e retornar um ponteiro para o endereço correspondente no espaço de endereço. Especificamente, ele usa duas macros, BITBAND e MEM_ADDR, para primeiro mapear o endereço addr e o número de bit bitnum no espaço de endereço da banda de bits e, em seguida, usar MEM_ADDR para converter o endereço em um ponteiro.

2. Operação de banda de bits GPIO

Em primeiro lugar, o ODR e o IDR do GPIO são o registro de dados de saída e o registro de dados de entrada da porta GPIO, que são usados ​​para controlar os estados de entrada e saída do pino GPIO.
Em segundo lugar, os deslocamentos dos dois registradores ODR e IDR correspondentes ao endereço base GPIO são 12 e 8. O mapeamento de endereço desses dois registradores é o seguinte:

//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 

Por fim, implemente a manipulação de bits do GPIO:

//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)  //输入

GPIOA_ODR_Addr é o endereço do registro ODR do GPIOA e n é o número do pino específico, de modo que a operação de banda de bits para o pino específico do GPIO seja concluída.

3. Use o efeito

#define SDA PCout(4)
SDA=1;

A definição de macro #define SDA PCout(4) aqui na verdade define SDA como uma macro funcional, que encapsula o controle de estado de saída do pino PC4 na função SDA. Especificamente, PCout(4) é uma macro funcional usada para controlar o estado de saída do pino PC4. Quando o pino PC4 precisa ser definido para um nível alto, SDA=1 será estendido para PCout(4)=1, definindo assim o estado de saída do pino PC4 para um nível alto.
Aqui, PCout(4) é outra definição de macro, que é usada para mapear o registro ODR e o número do pino da porta GPIO para o espaço de endereço da banda de bits correspondente e retornar o ponteiro do estado do pino correspondente no espaço de endereço. Portanto, SDA=1, na verdade, controla indiretamente o estado de saída do pino, modificando o ponteiro do estado do pino correspondente no espaço de endereço da faixa de bits.

Resumir

As vantagens da operação STM32 bit são as seguintes:
(1) É muito simples controlar a entrada e saída do GPIO
(2) É muito conveniente operar chips de interface serial (DS1302, 74HC595, etc.), se as funções da biblioteca forem usado, então a escrita do tempo é muito inconveniente.
(3) O código é conciso e fácil de ler.
Esta é a operação bit-band, mas para chips de outras arquiteturas, quando não há operação bit-band, a função só pode ser implementada de forma honesta e prática. No próximo artigo, analisarei em detalhes a interrupção de recepção da porta serial e a interrupção ociosa da porta serial.

Guess you like

Origin blog.csdn.net/qq_53092944/article/details/130645901