[STM32 learning] - ADC analog-to-digital converter & plug-in / STM32 successive approximation ADC & input channel / conversion mode / trigger control / data alignment / conversion time / calibration & AD single / multi-channel practical operation


Disclaimer: The study notes are edited according to the stm32 introductory tutorial of Jiangke University of Science and Technology of China, and are only for learning and communication!
Note: This article is 9920 words, and it takes about 15 minutes to read, please be patient and you will gain a lot!

foreword

There are two practical programs for this study, the first program is AD single channel, the second is AD multi-channel
STM32 ADC is 12 bits, the maximum value of AD is 4095, corresponding to the maximum voltage of 3.3V, which can be adjusted from 0-3.3 Any voltage between v is quantized, so the ADC is equivalent to a voltmeter. For GPIO, only the high and low levels of the pin can be read.


1. Introduction to ADCs

1 Overview

insert image description here
Note: The switch control corresponds to the ADC_Cmd library function, which is used to power up the ADC.
The ADC (Analog-Digital Converter) analog-to-digital converter, the ADC can convert the continuously changing analog voltage on the pin into a digital variable stored in the memory, and establish an analog Circuit to digital circuit bridge.
12-bit successive approximation ADC, 1us conversion time . 12 is located at 1us and involves two key parameters of the ADC. The first bit resolution, generally expressed in how many bits, indicates the quantifiable fineness. The second is the conversion time, that is, the conversion frequency. AD conversion takes a certain amount of time. 1us means the time from AD conversion to the result, and the corresponding frequency is 1MHz. 》Input voltage range: 0-3.3V, conversion result range:
0 ~ 4095 . One-to-one correspondence linear relationship
> 18 input channels can measure 16 external and 2 internal signal sources . The external clock source signal is 16 GPIO ports, and the analog signal can be directly connected to the pin. The two internal signal sources are the internal temperature sensor and the internal reference voltage. The temperature sensor can measure the temperature of the CPU; the internal reference voltage is a reference voltage of about 1.2v, which does not change with the external power supply voltage. If the power supply voltage of the chip is not standard 3.3v, then it may be wrong to measure the voltage of the external pin. At this time, the reference voltage can be read for calibration to obtain the correct voltage value of the external pin.
" Rule group and injection group are two conversion units . It belongs to the enhanced function of STM32 ADC. The ordinary AD conversion process is to start a conversion to read the value once, and then start the process of reading the value again. After enhancement, one group can be listed, one group can be started at one time, and multiple values ​​can be converted continuously; and there are two groups, the rule group is used for routine use, and the injection group is used for emergencies.
Analog watchdog automatically monitors the input voltage range. ADCs can generally be used to measure light intensity and temperature values, and there is often a requirement: if the light or temperature is higher than a certain threshold or lower than a certain threshold, perform some operations. The judgment of being higher/lower than a certain threshold can be automatically performed by the analog watchdog. The analog watchdog can monitor certain specified channels. When the AD value is higher than its set upper threshold or lower than the lower threshold, it will Apply for an interrupt, and perform corresponding operations in the interrupt function. In this way, there is no need to manually (software resources) read the value, and then use if to judge.
STM32F103C8T6 ADC resources : ADC1, ADC2, 10 external input channels, the 16 mentioned above is the largest number of channels in this series, this model only has 10.
Expansion:
DAC is the opposite of digital-to-analog converter, which is a bridge from digital to analog! However, PWM, which is mentioned in the comparison of timer output, can also realize digital-to-analog conversion. At the same time, PWM has only two states: completely on and completely off, and there is no power loss. Therefore, in high-power application scenarios such as DC motor speed regulation, Using PWM to equivalent analog is a better choice than DAC, and the PWM circuit is simpler and more commonly used. The application of DAC is mainly in the field of waveform generation, such as signal generators, audio decoding chips, etc. PWM is not a good substitute for these fields! ! The practical SYM32 does not have a DAC peripheral.


2. Graphical explanation

1. External successive approximation ADC

》External successive approximation ADC: (Basically the same principle as the ADC in STM32)
It is an external (independent) ADC chip. With the improvement of the integration of single-chip microcomputers, many single-chip microcomputers have integrated ADC peripherals. , there is no need for this kind of external chip, it is very convenient to measure the voltage directly on the pin!
insert image description here
1. First, IN0-IN7 on the left is 8 input channels. Select one input channel through the channel selection switch to convert to the next step. The address latch and decoding means which channel (8 channels) you want to select, put the channel number in ADDA-ADDC On the three pins, ALE can automatically dial the corresponding access switch on a latch signal. This part is equivalent to a data selector that can pass through analog signals. Of course, the ADC of STM32 has 18 input channels!
2. Successive approximation method : the signal is sent to a voltage comparator , which can judge the relationship between the two input signal voltages, and output a high and low level to indicate who is bigger and who is smaller; one of the two input terminals is the voltage to be measured, and the other is the DAC . Voltage output terminal (DAC internally uses weighted resistor network to achieve conversion, please refer to 51 tutorial), compare the two and continuously adjust the input code value of DAC voltage to make the two keep approaching, so that the input data of DAC is the code data of external voltage up. The process of voltage regulation is completed by the successive approximation SAR in the figure
3. After the AD conversion is completed, the input data of the DAC (SAR downward double arrow) is the code of the voltage to be measured at the position, which is output to the three-state latch buffer through the right double arrow , 8 bits and 8 lines, 12 bits 12 wires.
4. Pin : EOC is End of Convert, that is, the conversion end signal; START is the start of conversion, and an input pulse is given; CLOCK is the ADC clock, because the inside of the ADC is judged step by step, and the clock is needed to promote this process; the following VREF+ And VREF- is the reference voltage of the DAC. For example, if a data of 255 is given to the DAC, it is determined by the reference voltage whether it corresponds to 5V or 3.3V. The reference voltage of the DAC also determines the input range of the ADC, so it is also the reference voltage of the ADC; Vcc and GND For power supply, usually the reference voltage + is the same as Vcc, and it will be connected together, and the negative pole and GND will also be connected together!


2. STM32 successive approximation ADC

》STM32 successive approximation ADC: (Chapter 11, 11.3 of the chip manual)
insert image description here
The following intercepts the part
insert image description here
of the above picture, and analyzes part by part: Compared with the above external ADC, it is more advanced: multiple channels can be selected at the same time, and the conversion is divided into Two sets of regular channels and injected channels. It is compared to a restaurant menu introduction:
(1) The rule group menu can store 16 dishes at the same time, but there is a disadvantage: the rule group has only one data register, that is, the table is relatively small and can only hold one dish at most. If 16 dishes are served, then The first 15 dishes will all be squeezed out, and only the 16th dish can be obtained. Therefore, if you use this menu for rule group conversion, it is best to implement it with DMA. DMA is a data transfer assistant. It can move this dish to other places after each dish is served to prevent it from being overwritten. We will note in the next section Let's learn DMA together. The DMA request in the above figure is used to trigger DMA for data transfer.
(2) The injection group is more advanced, like a VIP seat in a restaurant. You can order up to 4 dishes at a time on this seat, and there are 4 data registers (you can serve these 4 dishes at the same time), so you don’t have to worry about data overwriting.
Generally, it is enough to use the rule group. The following also mainly involves the rule group. For the injection group, please refer to the chip manual!
" There are two types of signals that trigger the STM32's ADC to start converting:
insert image description here
(1) Software trigger . That is, manually call a code in the program to start the conversion
(2) hardware trigger. That is, the trigger sources in the above figure, the top is the trigger source of the injection group, and the bottom is the trigger source of the rule group. These trigger sources are mainly from the timer, each channel of the timer, and the output of the main mode of the TRGO timer. The timer can be connected to peripherals such as ADC and DAC to trigger the conversion, because the ADC often needs to be converted once in a fixed period of time. The normal implementation idea is to use the timer to apply for an interrupt every certain time, and manually perform a conversion in the interrupt , but just like the frequent interrupts that have been emphasized before will block the main program. Generally, such problems will have hardware support, such as the example above: set a time of 1 ms for TIM3, and select the update event of TIM3 as TRGO output, and then select the TRGO whose trigger signal is TIM3 in the ADC, so that TIM3 The update event can automatically trigger the ADC conversion through the hardware, and the whole process does not need to be interrupted to save interrupt resources. Of course, the external interrupt pin EXTI_11 can also be selected to trigger the conversion.
" The clock ADCCLK of STM32ADC comes from the ADC prescaler, and the ADC prescaler comes from RCC. As shown in the RCC clock tree:
Because the maximum ADCCLK is 14MHz, although the ADC prescaler has 2, 4, 6, and 8 frequency divisions, in fact, only 6 frequency divisions of 12MHz and 8 frequency divisions of 9MHz meet the requirements.
insert image description here
Analog watchdog and EOC signal :
The analog watchdog is used to monitor the range of conversion results, and can store a threshold high limit and threshold low limit. If the analog watchdog is started and the channel of the watchdog is specified, then this The watchdog will pay attention to this channel, and once it exceeds this threshold range, it will bark, apply for an interrupt that simulates the watchdog on it, and finally lead to the NVIC.
Then for the rule group and the injection group, after their conversion is completed, there will also be a signal that the EOC or JEOC conversion is completed. These two signals will respectively set a flag in the status register, and you can know by reading this flag Is the conversion over? At the same time, these two flags can also go to the NVIC to apply for an interrupt (if the channel corresponding to the NVIC is enabled, they will trigger an interrupt)


Second, the details

1. Input channel

The figure below shows the relationship between ADC channels and pin multiplexing: (You can also refer to the pin definition table)
insert image description here
Only ADC1 has channels 16 and 17, while ADC2 and ADC3 do not. The pins of channel 0-15 GPIO ports, the pins of ADC1 and ADC2 are exactly the same, and there are some changes in the middle of ADC3, but the chip used in this practice does not have ADC3. The pins marked in green are not available in this chip. (STM32F10xxx)


2. Four conversion modes (rule groups)

In the ADC structure initialized with the library function, there will be two parameters, one selects single or continuous conversion, and the other selects scanning or non-scanning mode.
1. Single conversion,
insert image description here
the simplest non-scanning mode (the "menu" list is not used), this list is the "menu" in the rule group, sequence 1-16, you can "order" here, It is to write the channel you want to convert. In the non-scanning mode, only the position of sequence 1 is valid in the menu. At this time, the method of selecting a group at the same time in the "menu" degenerates into a method of simply selecting one. The channel we want to convert can be written in sequence 1, such as channel 2 in the above figure, and the conversion can be triggered. The conversion result is placed in the data register, and the EOC flag is set to 1 at the same time, and the conversion process ends. Judging the EOC flag bit, if the conversion is completed, the result can be read in the data register. If you want to start a conversion again, you need to trigger it again, and then cycle. If you want to switch to another channel, change the channel 2 in the sequence 1 position to other channels before conversion.
2. Continuous conversion, non-scanning mode
insert image description here
or non-scanning mode, the "menu" only uses the sequence 1 position, the difference from the previous single conversion is that it will not stop after one conversion, but start the next round immediately Conversion, and on and on. That is, it only needs to be triggered once at the very beginning, and then it can be converted all the time. The advantage is that there is no need to wait for a period of time after starting the conversion, and there is no need to manually start the conversion.

3. Single conversion, the scan mode
insert image description here
is also a single conversion, and it will stop after each trigger conversion; the scan mode will use the "menu" list, and you can "order" in the menu, such as the few in the picture above Channel, each position is that the number of channels can be specified arbitrarily and can be repeated. There is also a parameter in the ADC initialization structure - the number of channels, as shown in the figure, 7 is selected.

4. Continuous conversion, scanning mode
insert image description here
Similarly, we can know this mode. In the scan mode, there is also a mode—intermittent mode, which is used to pause every few conversions during the scan process, and needs to be triggered again to continue. If this mode is not listed, there will be too many categories.


3. Trigger control

insert image description hereinsert image description here
I talked about trigger control before. This table is the trigger source of the rule group, which is the green circle in the figure below. There are signals from timers, pins or timer signals (specifically pins and timers, which need to be reset with AFIO) Mapping to determine), the last software control bit is the software trigger. The selection of these trigger signals can be done by setting the registers on the right side of the table. If you use the library function, you only need to give a parameter to a function.


4. Data alignment

Our ADC here is 12-bit, and its conversion result is a 12-bit data, but the data register is 16-bit, so there is a data alignment problem. Complement high bits with 0
1. Data is right-aligned
insert image description here
2. Data is left-aligned.
insert image description here
Generally, right-aligned is selected, so that reading the 16-bit register is directly the conversion result. If it is left-aligned and read directly, the obtained data will be larger than the actual one. Shifting four bits to the left is equal to Multiply by 16 times.
The purpose of left alignment is: if you don’t want such a high resolution and feel that 0~4095 is too large, just make a simple judgment. If you don’t need such a high resolution, you can choose left alignment, and then set the height of this data to 8 The bit is taken out, so that the accuracy of the next 4 bits is discarded, and it degenerates into an 8-bit ADC. In this way, you can also use right alignment to take out the 12 bits for processing, but there is one more step.


5. Conversion time

We are generally not sensitive to this parameter, because the AD conversion speed is very fast. If a very high conversion frequency is not required, the conversion time can be ignored.
The steps of AD conversion: sampling, holding, quantization, encoding.
Sampling and holding can be put together, quantization coding can be put together, a total of two steps. Quantization coding is a process of successive comparisons by the ADC. This takes time, and the more bits, the longer the time; why sample and hold? Because AD conversion, that is, quantization and encoding, takes time, if the input voltage is still changing during this period, it is impossible to locate where the input voltage is. Therefore, before quantization and encoding, it is necessary to set a sampling switch. First open the sampling switch to collect the external voltage. For example, a small-capacity capacitor can be used to store this voltage. After storage, disconnect the sampling switch and perform AD conversion. , the voltage clock remains unchanged, so that the position of the unknown voltage can be precisely located, which is the so-called sample and hold circuit. The sampling time will be generated here, so it can be obtained:
2、
the time spent on sampling and holding can be configured in the program. The larger the sampling time, the more interference from some glitch signals can be avoided, but the conversion time is correspondingly extended. 12.5 ADC cycles are the time required for quantization and encoding. The ADC is 12 bits, so it takes 12 cycles. The extra 0.5 cycles may be to do other things. The ADC cycle is the ADCCLK frequency-divided from the RCC. The maximum ADCCLK is 14MHz. The example is the fastest conversion time. In fact, it can be overclocked (>14MHz), but the stability is not strong.


6. Calibration

The ADC has a built-in self-calibration mode. Calibration greatly reduces quasi-accuracy errors due to variations in the internal capacitor bank. During calibration, an error correction code (digital value) is calculated on each capacitor, and this code is used to cancel the error generated on each capacitor in subsequent conversions.
It is recommended to perform a calibration after each power-up. The ADC must be powered down for at least two ADC clock cycles before initiating calibration.
Since the calibration process is fixed, users only need to add a few codes after initialization!


7. Hardware circuit

The following three circuit diagrams are given for the design of the peripheral circuit of the ADC:
insert image description here
Figure 1 shows an adjustable voltage generated by the potentiometer. One end of the two fixed ends of the potentiometer is connected to 3.3V, and the other end is connected to GND, so that the middle sliding end can output a 0. ~3.3V adjustable voltage output, here can be connected to the ADC input channel PA0 port as shown in the figure. The resistance value of the resistor should not be too small. If it is too small, it will consume more electricity. If it is too small, it may generate heat and smoke. Generally, it is of KΩ level.
Figure 2 is the circuit for the output voltage of the sensor. Generally, photoresistors, thermistors, infrared receiving tubes, microphones, etc. can be equivalent to a variable resistor N1, which can be divided in series with a fixed resistor to obtain a voltage that reflects the resistance value. circuit. The fixed resistance is generally chosen to be a resistance close to the resistance of the sensor, so that a better output in the middle voltage area can be obtained.
Figure 3 is a simple voltage conversion circuit. For example, you want to measure a VIN voltage of 0~5V, but the ADC can only receive a voltage of 0-3.3V, and use resistors to divide the voltage. For example, the voltage at the input point of PA2 is VIN/50Kx33K. If the voltage is too high, it is not recommended to use this circuit. It may be dangerous. It is best to use a dedicated chip for high voltage acquisition, such as an isolation amplifier, to achieve high and low voltage isolation to ensure circuit safety.
More content is in Chapter 11 of the chip manual!


3. Practical cases

1. AD single channel

xxxxx
Here, according to the pin definition table, the ten pins from PA0 to PB1 are 10 channels of the ADC, and any one of these 10 pins can be selected, and the others cannot be connected to analog voltage. This code is single channel single conversion non-scanning mode.

//AD.c
#include "stm32f10x.h"                  // Device header
//根据ADC基本结构图,打通它即可:
//1、开启RCC时钟,包括ADC和GPIO的时钟;ADCCLK的分频器也需要配置下
//2、配置GPIO,把需要用的GPIO配置为模拟输入模式
//3、配置多路开关,把左边的通道接入到右边的规则组列表里(“点菜”)
//4、配置ADC转换器,利用库函数里的结构体,可配置包括AD转换器和AD数据寄存器在内的一大块的电路
   //(包括ADC是单次还是连续、扫描还是非扫描、几个通道、触发源是什么、数据对齐是左or右对齐)
//其他的,如果需要模拟看门狗,会有几个函数用来配置阈值和监测通道。
//如果想开启中断,可在中断输出函数控制里用ITConfig函数开启对应的中断输出,然后在NVIC里配置下优先级就可触发中断。
//实例代码中暂未用到模拟看门狗和中断。
//5、开关控制,ADC_Cmd()函数开启ADC。
//6、根据手册建议,开启后还可对其进行下校准,可减小误差。
void AD_Init(void){
    
    
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//6分频
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;//选择模拟输入模式即AIN
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//一个口非扫描模式,点一个菜。“1”表示序列1的位置,加上Channel1表示在序列1处写入通道1,第四个参数与采样时间有关根据需要。
	//ADC_RegularChannelConfig(ADC1,ADC_Channel_3,2,ADC_SampleTime_55Cycles5);//多个序列可在后面加,此处就一个输入口PA0
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode= ADC_Mode_Independent;//独立模式,ADC1和ADC2各转换各的。其他为双ADC模式较复杂
	ADC_InitStructure.ADC_DataAlign= ADC_DataAlign_Right;//数据对齐:右对齐
	ADC_InitStructure.ADC_ExternalTrigConv= ADC_ExternalTrigConv_None;//触发源:软件触发
	ADC_InitStructure.ADC_ContinuousConvMode= DISABLE;//转换模式:单次转换
	ADC_InitStructure.ADC_ScanConvMode= DISABLE;//转换模式:非扫描
	ADC_InitStructure.ADC_NbrOfChannel= 1;//通道数目:
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1);//校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
}

uint16_t AD_GetValue(void){
    
    
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//ADC转换需要一定时间
	return ADC_GetConversionValue(ADC1);//获取转换值
}
//main.c
#include "stm32f10x.h"   // Device header
#include "Delay.h"   
#include "OLED.h"
#include "AD.h"

uint16_t ADValue;
float Voltage;

int main(void){
    
    
	OLED_Init();
    AD_Init();
	OLED_ShowString(1,1,"ADValue:");
	OLED_ShowString(3,1,"Voltage:0.00V");
	while(1){
    
    
		ADValue = AD_GetValue();
		Voltage = (float)ADValue/4095*3.3;//数字与电压映射关系,ADValue为uint16类型除以4095会舍弃小数部分,先强转为float
		OLED_ShowNum(1,9,ADValue,4);
		//目前的OLED没有显示浮点数的功能,但可用显示整数的借用
		OLED_ShowNum(2,9,Voltage,1);//显示整数部分
		OLED_ShowNum(2,11,(uint16_t)(Voltage*100)%100,2);//显示小数部分,浮点数不可%取余所以先强转为整型
		Delay_ms(20);//限制OLED刷新速度
	}
}

If single-channel continuous conversion non-scanning mode is required, then:
Change 1 : AD_ContinuousConvMode = ENABLE ;
Change 2 : Continuous conversion only needs to be triggered once at the very beginning, and the software triggers ADC_SoftwareStartConvCmd(ADC1, ENABLE); move it to the initialization function. while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET); There is no need to judge the flag bit.


2. AD multi-channel

xxxxx
This practice uses 4 AD conversion channels, the first channel (green) is still connected to the potentiometer PA0, and the other three (yellow) are three sensor modules: photosensitive, thermal, reflective infrared sensors PA1, PA2, PA3 . Note that the sensor AO is an analog output, and DO is a digital output.
"Multi-channel first thought of the previous scanning mode, which is a good method, but DMA is used to solve the problem of data coverage, and I haven't learned DMA yet.
"There is another idea that after a channel conversion is completed, it is not enough to manually transfer the data. Why do you need DMA? It seems simple, but the actual operation will encounter problems. Problem 1: In scan mode, after starting the list, each individual channel in it will not generate any flags after the conversion is completed, and will not trigger an interrupt. It is impossible to know a certain channel Whether the conversion is complete, the EOC flag will be generated only after the entire list conversion is completed, and the interrupt can be triggered; Question 2: AD conversion is very fast (several us/channel), and manual transfer is difficult. However, it does not mean that it must not work, you can use the intermittent mode, and pause once every time a channel is converted during scanning, which is not recommended for low efficiency.
》How to demonstrate the code: Based on the above single conversion and non-scanning mode, before each trigger conversion, manually change the channel at the first position in the list below, for example, write to the channel first for the first conversion, and then trigger , wait, read value; the second conversion changes channel 0 to channel 1....
Change 1:

//删除AD_Init()里的
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);

Change 2:

//下面的AD_GetValue()函数变化为可改变通道的:
uint16_t AD_GetValue(uint8_t ADC_Channel){
    
    
	ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);//通道可改
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//ADC转换需要一定时间
	return ADC_GetConversionValue(ADC1);//获取转换值
}

Change 3:

//main.c
#include "stm32f10x.h"   // Device header
#include "Delay.h"   
#include "OLED.h"
#include "AD.h"

uint16_t AD0,AD1,AD2,AD3;//表示四个ADC输入通道的转换结果的接收变量

int main(void){
    
    
	OLED_Init();
    AD_Init();
	OLED_ShowString(1,1,"AD0:");
	OLED_ShowString(2,1,"AD1:");
	OLED_ShowString(3,1,"AD2:");
	OLED_ShowString(4,1,"AD3:");
	while(1){
    
    
		AD0 = AD_GetValue(ADC_Channel_0);
		AD1 = AD_GetValue(ADC_Channel_1);
		AD2 = AD_GetValue(ADC_Channel_2);
		AD3 = AD_GetValue(ADC_Channel_3);
		//根据需要也可设置映射关系,再进行显示
		
		OLED_ShowNum(1,5,AD0,4);
		OLED_ShowNum(2,5,AD1,4);
		OLED_ShowNum(3,5,AD3,4);
		OLED_ShowNum(4,5,AD3,4);
		
		Delay_ms(100);
	}
}

Summarize

When you encounter setbacks, you must have the courage to move forward, act immediately, stick to the end, and never give up. Those who succeed will never give up, and those who give up will never succeed. On the road to success, there will definitely be failures; for failures, we must treat and treat them correctly, those who are not afraid of failures will surely succeed; those who are afraid of failures will be useless and will fail even more.
This is the end of today's learning sharing, see you next time! !
insert image description herePrevious highlights:
STM32 timing interrupt
STM32 external interrupt
STM32GPIO intensive lecture
...

Guess you like

Origin blog.csdn.net/weixin_51658186/article/details/129638031