Detailed analysis of the basic knowledge of STM32

STM32 is a 32-bit single-chip microcomputer with powerful functions. It is widely used in various embedded devices. Due to its popularity and rich resources, it is favored by the majority of embedded developers, but it is also necessary to learn and use STM32. It's not easy. After all, STM32 is much more complicated than 8-bit and 16-bit products.

STM32 clock

It is well known that the STM32 has five clock sources HSI, HSE, LSI, LSE, and PLL. In fact, it has only four, because it can be seen from the following figure that the PLL is provided by HSI or HSE.

Among them, the high-speed clock (HSE and HSI) is supplied to the main clock of the chip body. The low-speed clock (LSE and LSI) is only provided to the RTC (real-time clock) and the independent watchdog in the chip. It can be seen that the high-speed clock is also used. Can be provided to the RTC. The internal clock is generated by the internal RC oscillator of the chip, and the start-up is faster. Therefore, when the clock is just powered on, the internal high-speed clock is used by default. The external clock signal is input by the external crystal oscillator, which has great advantages in accuracy and stability. Therefore, after power-on, we use the software configuration to switch to the external clock signal.

High-speed external clock (HSE): The external crystal oscillator is used as the clock source. The crystal frequency can be in the range of 4~16MHz. We generally use an 8MHz crystal oscillator.

High Speed ​​Internal Clock (HSI): Generated by the internal RC oscillator at 8MHz, but unstable.

Low-speed external clock (LSE): The external crystal oscillator is used as the clock source and is mainly supplied to the real-time clock module, so 32.768KHz is generally used.

Low-speed internal clock (LSI): Generated by the internal RC oscillator and also supplied to the real-time clock module at a frequency of approximately 40KHz.

OSC_OUT and OSC_IN start, these two pins are respectively connected to the external crystal oscillator 8MHz, the first divider PLLXTPRE, encounter the switch PLLSRC (PLL entry clock source), we can choose its output, the output is the external high-speed clock (HSE) Or an internal high speed clock (HSI). Here, the output is selected as HSE, and then the phase-locked loop PLL is encountered, which has a frequency multiplication function. Here we can input the multiplication factor PLLMUL. If you want to overclock, you have to do this on the register. The clock that passes through the PLL is called PLLCLK. The multiplication factor is set to 9x, which means that after the PLL, our clock changes from the original 8MHz HSE to the 72MHz PLLCLK. Then, a switch SW is encountered. After this switch, it is the system clock (SYSCLK) of the STM32. Through this switch, you can switch the clock source of SYSCLK, which can be selected as HSI, PLLCLK, HSE. We chose the PLLCLK clock, so SYSCLK is 72MHz. PLLCLK also flows to the USB prescaler before it is input to SW. This divider outputs the clock of the USB peripheral (USBCLK). Returning to SYSCLK, SYSCLK passes through the AHB prescaler, and is divided into other peripherals. If output to a clock called HCLK, FCLK, it is also directly output to the SDIOCLK clock of the SDIO peripheral, the FSMCCLK clock of the memory controller FSMC, and the input of the prescaler as APB1 and APB2. The GPIO peripheral is mounted on the APB2 bus. The APB2 clock is the output of the APB2 prescaler, while the APB2 prescaler clock source is the AHB prescaler. Therefore, by setting the APB2 prescaler to not divide, then we can get the clock of the GPIO peripheral equal to HCLK, which is 72MHz.

SYSCLK: System clock, the clock source for most of the STM32 devices. It is mainly distributed to each component by the AHB prescaler.

HCLK: It is directly output by the AHB prescaler. It is the clock signal of the high-speed bus AHB. It is supplied to the memory, DMA and cortex core. It is the clock running by the cortex core. The cpu main frequency is this signal, its size and STM32 operation. Speed ​​and data access speed are closely related.

FCLK: Also derived from the AHB prescaler output, is the "free running clock" of the core. "Free" is manifested in that it does not come from the clock HCLK, so FCLK also continues to run when the HCLK clock is stopped. It exists to ensure that when the processor is asleep, it can also sample and interrupt and track the sleep event, which is synchronized with HCLK.

PCLK1: Peripheral clock, obtained by the APB1 prescaler output, with a maximum frequency of 36MHz, is provided to the peripherals mounted on the APB1 bus. The peripherals on the APB1 bus are as follows:

RCC_APB1Periph_TIM2 TIM2 clock

RCC_APB1Periph_TIM3 TIM3 clock

RCC_APB1Periph_TIM4 TIM4 clock

RCC_APB1Periph_WWDG WWDG Clock

RCC_APB1Periph_SPI2 SPI2 clock

RCC_APB1Periph_USART2 USART2 clock

RCC_APB1Periph_USART3 USART3 clock

RCC_APB1Periph_I2C1 I2C1 clock

RCC_APB1Periph_I2C2 I2C2 clock

RCC_APB1Periph_USB USB clock

RCC_APB1Periph_CAN CAN clock

RCC_APB1Periph_BKP BKP clock

RCC_APB1Periph_PWR PWR clock

RCC_APB1Periph_ALL All APB1 peripheral clocks

PCLK2: Peripheral clock, obtained by the APB2 prescaler output. The maximum frequency can be 72MHz. It is provided to the peripherals mounted on the APB2 bus. The peripherals on the APB2 bus are as follows:

RCC_APB2Periph_AFIO function multiplexed IO clock

RCC_APB2Periph_GPIOA GPIOA clock

RCC_APB2Periph_GPIOB GPIOB clock

RCC_APB2Periph_GPIOC GPIOC Clock

RCC_APB2Periph_GPIOD GPIOD clock

RCC_APB2Periph_GPIOE GPIOE clock

RCC_APB2Periph_ADC1 ADC1 clock

RCC_APB2Periph_ADC2 ADC2 clock

RCC_APB2Periph_TIM1 TIM1 clock

RCC_APB2Periph_SPI1 SPI1 clock

RCC_APB2Periph_USART1 USART1 clock

RCC_APB2Periph_ALL All APB2 peripheral clocks

Several input modes of STM32

STM32 has 4 input modes:

1) Analog input GPIO_AIN: for AD conversion

2) Floating input GPIO_IN_FLOATING: The pin is in floating mode and the level state is undefined. What is the external signal input, what state is the IO port.

3) Pull-up input GPIO_IPU: Prevents the IO port from being in an indeterminate state. For example, when the IO port is left floating, the point is clamped to a high level by an internal pull-up resistor.

4) Pull-down input GPIO_IPD: The function is similar to the pull-up resistor to prevent the IO port from being in an indeterminate state. For example, when the IO port is left floating, the point is clamped to a low level by an internal pull-down resistor.

Whether the STM32 hollow I/O pin is high or low depends on the situation.

1. The IO port is in a floating state after reset, that is, its level state is determined by the peripheral circuit.

2. The level of the I/O port on the STM32 power-on reset moment is the floating input by default, so it is high impedance. Do low power consumption.

3. The IO pin configuration port of STM32 defaults to floating input, leaving the option to the user. This is a big advantage: on the one hand, the floating input ensures that there is no default level that the user does not want (at this time) The level depends on the user's peripheral circuitry; on the other hand, the power consumption is reduced because there is current consumption whether it is pull-up or pull-down. From another point of view, regardless of the default configuration of the I / O pin, you need to add pull or pull down the output pin, in order to ensure that the output pin is always known during power-on and reset. Level.

4. In the absence of any operation, the pin of the STM32 universal push-pull output mode defaults to a low level, that is, a powered state. Therefore, when configuring, the level of the pin is usually set to be high, so that the circuit does not generate current. The process from power to no power is the process of pin level from low to high.

5. There are two types of I/O pins for STM32: TTL and CMOS. All pins are compatible with TTL and CMOS levels. In other words, from the input identification voltage, all pins can recognize TTL or CMOS levels whether they are TTL pins or CMOS pins.

STM32 interrupt system

In STM32, the number of interrupts is greatly increased, and the setting of interrupts is more complicated.

1 basic concept

The ARM Coetex-M3 core supports a total of 256 interrupts, including 16 internal interrupts, 240 external interrupts, and programmable 256-level interrupt priority settings. STM32 currently supports a total of 84 interrupts (16 internal + 68 external), as well as 16 programmable interrupt priority settings, using only the interrupt priority to set the upper 4 bits of 8 bits.

STM32 can support 68 interrupt channels, which have been fixedly allocated to the corresponding external devices. Each interrupt channel has its own interrupt priority control byte PRI_n (8 bits, but only 4 bits are used in STM32, and the upper 4 bits are valid). The 8-bit interrupt priority control word for every 4 channels constitutes a 32-bit priority register. The 68 channel priority control words form at least 17 32-bit priority registers.

The 4-bit interrupt priority can be divided into two groups. From the high level, the pre-emptive priority is defined earlier, followed by the response priority. According to this grouping, 4bit can be divided into 5 groups.

Group 0: All 4 bits are used to specify the response priority;

Group 1: The highest 1 bit is used to specify the preemptive priority, and the next 3 bits are used to specify the response priority;

Group 2: The highest 2 bits are used to specify the preemptive priority, and the last 2 bits are used to specify the response priority;

Group 3: The highest 3 bits are used to specify the preemptive priority, and the next 1 bit is used to specify the response priority;

Group 4: All 4 bits are used to specify preemptive priority.

The so-called preemptive priority and response priority, the relationship between them is: interrupts with high preemptive priority can be responded to interrupt processing with low preemptive priority, that is, interrupt nesting.

When the preemptive priorities of the two interrupt sources are the same, the two interrupts will have no nesting relationship. When one interrupt arrives, if another interrupt is being processed, the subsequent interrupt will wait until the previous interrupt is processed. Can be processed. If the two interrupts arrive at the same time, the interrupt controller decides which one to process first based on their response priority level; if their preemptive priority and response priority are equal, then according to their rank in the interrupt table The order determines which one to process first. Each interrupt source must define two priorities.

There are a few things to note:

1) If the specified preemptive priority level or response priority level exceeds the range defined by the selected priority grouping, unexpected results may result;

2) There is no nested relationship between the interrupt sources with the same preemptive priority level;

3) If an interrupt source is specified as a preemptive priority level and no other interrupt source is in the same preemptive priority level, then any valid response priority level can be specified for this interrupt source.

2 GPIO external interrupt

In STM32, each GPIO can trigger an external interrupt. However, the GPIO interrupt is one unit of group, and the external interrupt between the same group can only use one at a time. For example, PA0, PB0, PC0, PD0, PE0, PF0, PG0 are one group. If we use PA0 as the external interrupt source, then we can't use it anymore. In this case, we can only use similar An external interrupt source with different end numbers such as PB1 and PC2. Each group uses an interrupt flag EXTIx. EXTI0 – EXTI4 These five external interrupts have their own separate interrupt response functions. EXTI5-9 shares an interrupt response function. EXTI10-15 shares an interrupt response function.

For interrupt control, the STM32 has a dedicated authority: NVIC. For a detailed explanation of the NVIC, refer to the ARM Cortex-M3 Authoritative Guide, Joseph Yiu, Song Yan, Beijing University of Aeronautics and Astronautics Press, Chapter 8, NVIC and Interrupt Control. The interrupt enable, suspend, priority, activity, etc. are all managed by the NVIC. Because I am learning how STM32 focuses on how to develop programs, so some of the internal things, I will not elaborate on them here. If you are interested, you can refer to the number mentioned above.

STM32 external interrupt use case

In fact, the basic concepts and knowledge above are only a general understanding of the STM32 interrupt system, and using the program to speak will be able to deepen how to use interrupts. The basic steps for using an external interrupt are as follows:

1. Set the corresponding clock;

2. Set the corresponding interrupt;

3. IO port initialization;

4. Set the corresponding IO port as an interrupt line (before setting the external interrupt) and initialize it;

5. Interrupt the function in the response function of the selected interrupt channel.

Since the struggle development board I used did not lead to the corresponding chip pins, only the buttons could be used to trigger the corresponding interrupts. According to the schematic, K1/K2/K3 is connected to PC5/PC2/PC3, so I will use EXTI5/EXTI2/EXTI3 for three external interrupts. Three LED lights are connected to the PB5/PD6/PD3. The effect of the interrupt is to press the button and the corresponding LED will be illuminated.

1. Set the corresponding clock

First you need to open GPIOB, GPIOC and GPIOE (because the other end of the button is connected to the PE port). Then, since it is used to trigger an interrupt, it is also necessary to turn on the GPIO multiplexed clock. The corresponding function is explained in detail in the GPIO study notes. The detailed code is as follows:

Void RCC_cfg()

{

//Open the PE PD PC PB port clock and turn on the multiplexed clock

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE);

}

The RCC function required to set the corresponding clock is in stm32f10x_rcc.c, so add this file to the project.

2. Set the appropriate interrupt

Setting the corresponding interrupt is actually setting the NVIC. There is a structure NVIC_InitTypeDef in the firmware library of STM32, which has corresponding flag setting, and then initialized with NVIC_Init() function. The detailed code is as follows:

Void NVIC_cfg()

{

NVIC_InitTypeDefNVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //Select interrupt group 2

NVIC_InitStructure.NVIC_IRQChannel= EXTI2_IRQChannel; //Select interrupt channel 2

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0; //Preemptive interrupt priority is set to 0

NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; //Response interrupt priority is set to 0

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //Enable interrupt

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQChannel; //Select interrupt channel 3

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1; //Preemptive interrupt priority is set to 1

NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1; //Response interrupt priority is set to 1

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //Enable interrupt

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel= EXTI9_5_IRQChannel; //Select interrupt channel 5

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2; //Preemptive interrupt priority is set to 2

NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2; //Response interrupt priority is set to 2

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //Enable interrupt

NVIC_Init(&NVIC_InitStructure);

}

Since there are 3 interrupts, as described above, 3 bits are required to specify the preemption priority, so the second group is selected. Since EXTI5-9 shares an interrupt response function, the interrupt channel selected by EXTI5 is EXTI9_5_IRQChannel, and the detailed information can be queried in the header file. The NVIC related library functions used in stm32f10x_nivc.c need to be copied and added to the project. See the GPIO notes for specific locations. This code compiles without any problems, but it will report an error when linking. You need to add STM32F10xR.LIB to the project, where the location is...\Keil\ARM\RV31\LIB\ST\STM32F10xR.LIB.

3. IO port initialization

Void IO_cfg()

{

GPIO_InitTypeDefGPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //Select pin 2

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //Output frequency up to 50MHz

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //With pull-up resistor output

GPIO_Init(GPIOE,&GPIO_InitStructure);

GPIO_ResetBits(GPIOE, GPIO_Pin_2); //Set the PE.2 pin to low output

GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5; //Select pin 2 3 5

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //Select input mode as floating input

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //Output frequency up to 50MHz

GPIO_Init(GPIOC,&GPIO_InitStructure); //Set PC.2/PC.3/PC.5

GPIO_InitStructure.GPIO_Pin= GPIO_Pin_3 |GPIO_Pin_6; //Select pin 3 6

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //Output frequency up to 50MHz

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //With pull-up resistor output

GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; //Select pin 5

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //Output frequency up to 50MHz

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //With pull-up resistor output

GPIO_Init(GPIOB,&GPIO_InitStructure);

}

The pin connecting the external interrupt needs to be set to the input state, and the pin connecting the LED needs to be set to the output state. The PE.2 is initialized to make the other end of the button output low level. The functions in GPIO are in stm32f10x_gpio.c.

4. Set the corresponding IO port as an interrupt line

Since GPIO is not a dedicated interrupt pin, you need to set the corresponding pin and interrupt line of GPIO when using GPIO to trigger external interrupt. The specific code is as follows:

Void EXTI_cfg()

{

EXTI_InitTypeDefEXTI_InitStructure;

/ / Clear the interrupt flag

EXTI_ClearITPendingBit(EXTI_Line2);

EXTI_ClearITPendingBit(EXTI_Line3);

EXTI_ClearITPendingBit(EXTI_Line5);

/ / Select the interrupt pin PC.2 PC.3 PC.5

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);

EXTI_InitStructure.EXTI_Line= EXTI_Line2 | EXTI_Line3 | EXTI_Line5; //Select interrupt line 2 3 5

EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt; //Set as interrupt request, non-event request

EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling; //Set the interrupt trigger mode to the upper falling edge trigger

EXTI_InitStructure.EXTI_LineCmd=ENABLE; //External interrupt enable

EXTI_Init(&EXTI_InitStructure);

}

The functions that need to be called in EXTI_cfg are all in stm32f10x_exti.c.

5. Write interrupt response function

Unlike the C51 microcontroller, STM32 can use the interrupt keyword to define the interrupt response function. The interrupt response function interface of STM32 exists in the interrupt vector table and is given by the startup code. The default interrupt response function is in stm32f10x_it.c. So we need to add this file to the project.

In this file, we found that many functions have only one function name and no function body. We find the EXTI2_IRQHandler() function, which is the function of the EXTI2 interrupt response. My goal is to light the LEDs, so the function body is actually very simple:

voidEXTI2_IRQHandler(void)

{

//Light up the LED light

GPIO_SetBits(GPIOD, GPIO_Pin_6);

/ / Clear the interrupt flag to prevent continuous interruption

EXTI_ClearITPendingBit(EXTI_Line2);

}

voidEXTI3_IRQHandler(void)

{

GPIO_SetBits(GPIOD, GPIO_Pin_3);

EXTI_ClearITPendingBit(EXTI_Line3);

}

voidEXTI9_5_IRQHandler(void)

{

GPIO_SetBits(GPIOB, GPIO_Pin_5);

EXTI_ClearITPendingBit(EXTI_Line5);

}

Since EXTI5-9 shares an interrupt response function, all EXTI5 – EXTI9 response functions are written in this.

6. Write the main function

#include"stm32f10x_lib.h"

Void RCC_cfg();

Void IO_cfg();

Void EXTI_cfg();

Void NVIC_cfg();

Int main()

{

RCC_cfg();

IO_cfg();

NVIC_cfg();

EXTI_cfg();

While(1);

}

The main function is preceded by a function declaration. The main function body calls the initialization configuration function, then enters an infinite loop and waits for an interrupt response.


Area Array Sensor

Area Array Sensor,Passive Infrared Detector,Infrared Heat Detector,Infrared Area Sensor

Ningbo NaXin Perception Intelligent Technology CO., Ltd. , https://www.nicswir.com