STM32F103 register mode turns on the LED water flow lamp

catalogue

1, Address mapping and register mapping principle of STM32F103 series chips

1. Address mapping

2. Register mapping

2, Understand the three steps of GPIO port initialization settings

3, Turn on the LED water lamp

1. Code

2. Execution waveform

3. Results

4, References

1, Address mapping and register mapping principle of STM32F103 series chips

1. Address mapping

In the STM32 firmware library, there is a header file called stm32f10x.h, which defines the mapping of registers. Some codes are as follows:

Peripheral base address PERIPH_BASE:

#define PERIPH_BASE           ((uint32_t)0x40000000)

Bus base address, add offset to peripheral base address:

#define APB1PERIPH_BASE       PERIPH_BASE
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)

GPIO peripheral base address, add offset to APB2 bus base address:

#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)

Define the GPIO peripheral structure. Because the structure members are continuous in memory, this form is very similar to the register group, so the structure can be used to manage the registers well:

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

Define the GPIOA structure pointer. Because defining the GPIO peripheral structure alone cannot determine its memory address, bind it to the GPIOA peripheral base address with a pointer:

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

Compared with register access methods, mapping access is obviously more intuitive:

//Direct address access
*(unsigned int *)(0x4001_0800)|= 0x0001;
//Map access
GPIOA->CRL |= 0x0001;

2. Register mapping

         Register mapping is mainly for Block2. This mapping is different from the address allocation operation of memory mapping, but the process of naming memory units with specific functions in the program. Each memory unit is four bytes, called registers. For example, the GPIOA peripheral has a register with an address range of 0x4001_0800~0x4001_0803, this register is used to configure the working mode of some ports of GPIOA, so it is mapped to GPIOA_CRL. It can be seen that this mapping facilitates the access to the register, because it is very painful to check the address range every time you access the register.

        How to implement this mapping? In gpioa_ Taking CRL as an example, its mapping address = total peripheral base address (block base address) + offset of bus from total peripheral base address + offset of specific peripheral base address from bus base address + offset of register from external base address.

The total base address of the peripheral is exactly the starting address 0x4000 of Block2_ 0000;

GPIO belongs to APB2 bus peripherals. Therefore, refer to the chip manual as shown in the figure below. In fact, we can directly obtain the APB2 start address and GPIOA start address. However, this is generally not done in the program, but the hierarchical relationship is represented by offset. It can be calculated from the figure that the offset of the bus relative to the total base address of the peripheral is 0x1_0000, the offset of GPIOA relative to APB2 base address is 0x800.

Then check the register group of GPIO, as shown in the figure below. It can be obtained that the offset of CRL register relative to GPIO base address is 0x00. To sum up, gpioa_ The base address of CRL is 0x4000_0000+0x1_0000+0x800+0x00.

2, Understand the three steps of GPIO port initialization settings

There are 7 groups of IO ports in the development board of STM32F103ZE, and each group has 16 IO ports, that is, there are 112 IO ports in this board, which are GPIOA~GPIOG respectively. Each I/O port bit can be programmed freely, but the I/O port register must be accessed by 32-bit bytes, and half word or single byte access is not allowed.
There are eight main working modes of GPIO: four input modes and four output modes: input floating, input pull-up, input pull-down and analog input; The output mode is open drain output, open drain multiplex output, push-pull output and push-pull multiplex output.
(1)GPIO_Mode_AIN analog input (apply ADC analog input or save power under low power consumption)
(2)GPIO_Mode_IN_FLOATING floating input (floating is floating in mid air, which can be pulled up or down by other objects, and can be used for key input)
(3)GPIO_Mode_IPD pull-down input (IO internal pull-down resistance input)
(4)GPIO_Mode_IPU pull-up input (IO internal pull-up resistance input)
(5)GPIO_Mode_Out_OD open drain output (open drain output: the output end is equivalent to the collector of the triode. To get the high-level state, you need to pull up the resistance)
(6)GPIO_Mode_Out_PP push-pull output (push-pull means push and pull, and the levels are determined without pull-up and pull-down. IO output 0-GND, IO output 1-VCC, and the read input value is unknown)
(7)GPIO_Mode_AF_OD multiplex open drain output (on-chip and off-chip functions (SCL and SDA of I2C))
(8)GPIO_Mode_AF_PP multiplex push-pull output (on-chip and off-chip functions (TX1,MOSI,MISO.SCK.SS))

GPIO initialization steps
Step 1: enable the clock of GPIOx port
Step 2: indicate which bit of GPIOx port, the speed, size and mode of this bit.
Step 3: call the GPIOx port initialization function to initialize.
Step 4: call GPIO setbits function to set corresponding.

Examples are as follows
☞ the initialization of a single GPIO port is as follows

GPIO_InitTypeDef GPIO_InitStructure;
Step 1: enable the clock of GPIOA:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

Step 2: set GPIOA parameters: output, OR input, working mode and port turnover rate
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_6| GPIO_Pin_7| GPIO_Pin_8; // Set pin to operate
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Set to push-pull output
GPIO_ InitStructure.GPIO_ Speed = GPIO_ Speed_ 50MHz; // The speed of IO port is 50MHz

Step 3: call the GPIOA port initialization function to initialize.
GPIO_ Init(GPIOA, &GPIO_InitStructure); // Initialize gpioa according to the set parameters

Step 4: call GPIO setbits function to set corresponding.
GPIO_SetBits(GPIOA,GPIO_Pin_0); // Output high

The initialization of multiple GPIO ports is as follows

GPIO_InitTypeDef GPIO_InitStructure;
Step 1: enable the clock of GPIOA and GPIOE:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

Step 2: set gpioa and gpioe parameters: output OR input, working mode and port turnover rate
Step 3: call the GPIOA port initialization function to initialize.
Step 4: call GPIO setbits function to set corresponding.

▶ Merge the second, third and fourth steps to set GPIOA and GPIOE respectively
Set GPIOA first
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // Fourth port, PA4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Set to push-pull output
GPIO_ InitStructure.GPIO_ Speed = GPIO_ Speed_ 50MHz; // The speed of IO port is 50MHz
GPIO_ Init(GPIOA,&GPIO-InitST); // Initialize gpioa according to the set parameters
GPIO_SetBits(GPIOA,GPIO_Pin_4); // Output high

Then set GPIOE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // Third port, PE3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Set to push-pull output
GPIO_ InitStructure.GPIO_ Speed = GPIO_ Speed_ 50MHz; // The speed of IO port is 50MHz
GPIO_ Init(GPIOE,&GPIO-InitST); // Initialize gpioe according to the set parameters
GPIO_SetBits(GPIOE,GPIO_Pin_3); // Output high

3, Turn on the LED water lamp

1. Code

1.c

#include "stm32f10x.h"
//----------------APB2??????? ---------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)
//----------------GPIOA????? -----------------------
#define GPIOA_CRL		*((unsigned volatile int*)0x40010800)
#define	GPIOA_ODR		*((unsigned volatile int*)0x4001080C)
//----------------GPIOB????? -----------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)
//----------------GPIOC????? -----------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR		*((unsigned volatile int*)0x4001100C)
	
extern void led(void);

//????
 void Delay()
 {
   u32 i=0;
   for(;i<5000000;i++);
 }
 
//?1
 void led1()
 {
    GPIOA_ODR|=1<<4;		//PA4???
	 	Delay();
		GPIOA_ODR&=~(1<<4);//PA4???,???????
		Delay();		
 }
 
//?2
 void led2()
 {
	  GPIOB_ODR|=1<<5;		//PB4???
	 	Delay();
		GPIOB_ODR&=~(1<<5);//PB4???,???????
		Delay();		
 }
 
//?3
 void led3()
 {
	 
		GPIOC_ODR|=1<<14;	//PC14???
	 	Delay();
		GPIOC_ODR&=~(1<<14);//PC14???,???????
		Delay();		
 } 
 
 int main(void)
 {	
	 led();
	RCC_APB2ENR|=1<<2|1<<3|1<<4;	//APB2-GPIOA?GPIOB?GPIOC??????		
	
	GPIOA_CRL&=0xFFF0FFFF;	//??? ??		
	GPIOA_CRL|=0x00020000;	//PA4????	
	GPIOA_ODR&=~(1<<4);		//???????	
	
	GPIOB_CRL&=0xFF0FFFFF;	//??? ??		
	GPIOB_CRL|=0x00200000;	//PB5????		
	GPIOB_ODR&=~(1<<5);		//???????	
	 
	GPIOC_CRH&=0xF0FFFFFF;	//??? ??		
	GPIOC_CRH|=0x02000000;	//PC14????		
	GPIOC_ODR&=~(1<<14);	//???????			

	while(1){		
		led1();
		
        led2();
		
        led3();
		}
}

 2.s

 AREA MYDATA, DATA
	
 AREA MYCODE, CODE
	ENTRY
	EXPORT led

led
	;??A,B,C
    ldr r0, =0x40021018
    ldr r1, =0x0000001c
    str r1, [r0]                


	;????A4
	ldr r0, =0x40010800
    ldr r1, [r0]
    bic r1, r1, #0x000f0000
    orr r1, r1, #0x00010000
    str r1, [r0]

	;????B5
    ldr r0, =0x40010c00
    ldr r1, [r0]
    bic r1, r1, #0x00f00000
    orr r1, r1, #0x00100000
    str r1, [r0]
	
	;????C14
	ldr r0, =0x40011004
    ldr r1, [r0]
    bic r1, r1, #0x0f000000
    orr r1, r1, #0x01000000
    str r1, [r0]

	;??A4??
	ldr r0, =0x4001080c
    ldr r1, =0x00000010
    str r1, [r0]

	ldr r0, =5000000;??
    ldr r1, =0
	
;????
blink
    add r1, r1, #1
    cmp r1, r0
    blt blink
	
	;??A4?
	ldr r1, =0x4001080c
    ldr r2, [r1]
    eor r2, r2, #0x00000010
    str r2, [r1]
	
	;??B5?
	ldr r1, =0x40010c0c
    ldr r2, [r1]
    eor r2, r2, #0x00000020
    str r2, [r1]
	
	ldr r1, =0

blink1	
	add r1, r1, #1
    cmp r1, r0
    blt blink1
	
	;??B5?
	ldr r1, =0x40010c0c
    ldr r2, [r1]
    eor r2, r2, #0x00000020
    str r2, [r1]
	
	;??C14?
	ldr r1, =0x4001100c
    ldr r2, [r1]
    eor r2, r2, #0x00004000
    str r2, [r1]
	

	ldr r1, =0

blink2
	add r1, r1, #1
    cmp r1, r0
    blt blink2
	
    ;??C14?
	ldr r1, =0x4001100c
    ldr r2, [r1]
    eor r2, r2, #0x00004000
    str r2, [r1]
	
	;??A4?
	ldr r1, =0x4001080c
    ldr r2, [r1]
    eor r2, r2, #0x00000010
    str r2, [r1]
	

	ldr r1, =0
    b blink

	
	END

2. Execution waveform

3. Results

 12346876453_ Beep beep beep_ bilibili

 

4, References

STM32 memory mapping and register mapping - KenSporger - blog Park (cnblogs.com)

  STM32 getting started - GPIO initialization steps_ Love learning big meow blog - CSDN blog

  STM32F103 register mode turns on the LED water flow lamp_ Parallel leaf blog - CSDN blog

Tags: Single-Chip Microcomputer stm32

Posted on Sat, 23 Oct 2021 09:10:12 -0400 by rizi