When using the stm32 library function, you will almost always find the assert_param() function. This function is used to determine whether there is an error in the parameter. What is the specific error? I will post a picture later.
The assert_param() function is defined in stm32f10x_conf.h:
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif
The above code is part of stm32f10x_conf.h. Let's look at the following code:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);
This function enables the clocks of GPIOB and GPIOE ports. GPIOB and GPIOE belong to APB2 peripherals, so use the function RCC_APB2PeriphClockCmd (xxx, xxx) to enable them. Let's take a look at the RCC_APB2PeriphClockCmd (xxx, xxx) function:
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2ENR |= RCC_APB2Periph;
}
else
{
RCC->APB2ENR &= ~RCC_APB2Periph;
}
}
In this function, we can see the function we are going to learn today. Here we will analyze function 1 and use the point to lead the whole.
1. assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
2. assert_param(IS_FUNCTIONAL_STATE(NewState));
The parameter in function 1 is IS_RCC_APB2_PERIPH (RCC_APB2Periph). Let's enter this function and see:
This is a macro definition
#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00))
Let's calculate it. PERIPH is the parameter we passed RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE.
RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE = 0x00000008 | 0x00000040
(PERIPH) & 0xFFC00002 = 0x00, so ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00)) = 1
So it is equivalent to assert_param(1);
Let's look at the part of the stm32f10x_conf.h code in reverse. If USE_FULL_ASSERT is defined, then
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
If USE_FULL_ASSERT is not defined, then #define assert_param(expr) ((void)0) will be defined. Why is this? It is because users may enter wrong parameters during the code debugging phase and errors may occur. Generally, such errors are not detected. Therefore, when we want to check such errors, we define USE_FULL_ASSERT. When we complete the project and start production, the code will definitely not have such errors. We do not need the program to check our parameters, so we do not need to define USE_FULL_ASSERT. This will make our code smaller.
So we open the comments in stm32f10x_conf.h, so that we can check the parameters required to be checked in our code. When there is no error in our parameters, it is equivalent to assert_param(1);. Enter the function assert_param(); and observe that (void)0 will be executed, which means nothing will be executed, because there is no error in the parameters at this time.
We now need to create an error and observe how the function is executed.
Now we pass a wrong parameter
RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
Let's calculate, RCC_APB1Periph_TIM3 = 0x00000002
(PERIPH) & 0xFFC00002)! = 0x00
So IS_RCC_APB2_PERIPH(PERIPH) returns 0
So it is equivalent to assert_param(0);
Enter assert_param(); function observation
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
The function assert_failed((uint8_t *)__FILE__, __LINE__) will be executed. Let's explain what this function does. This function is for users to play with. You can do whatever you want in this function. Its prototype is not in the program. Anyway, I didn't find it. Later, I saw an article on the Internet. He said that he found it in the official example main.c, so I copied it to my main.c. The function prototype is as follows:
void assert_failed(u8* file, u32 line)
{
//User can add his own implementation to report the file name and line number,
// ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line)
//Users can add error information here: for example, print out the wrong file name and line number
// Infinite loop
while (1)
{
}
}
This function can print out the file and line number of our parameter errors when the program is running. I modified this function to:
void assert_failed(u8* file, u32 line)
{
printf("Wrong parameters value: file %s on line %d\r\n", file, line);
}
You can also add other functions. As long as the error message can be displayed, it is ok. It does not necessarily have to be displayed through the serial port.
If the parameters are wrong, the file and line number of the error will be printed to the serial port. The following figure shows the error information printed by the serial port:
The error file is stm32f10x_rcc.c line number 1098. Let's see if there is a parameter error in the program, as shown below:
There is indeed a parameter error here, because the parameter we passed is
RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
I have basically finished the introduction here, and will introduce a few points below.
1. The __FILE__ and __LINE__ parameters of the assert_failed((uint8_t *)__FILE__, __LINE__) function may be built-in to the C language. I don’t know how to get the file and line number of the error parameters.
2. Suppose the parameter we pass is RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); Although RCC_APB1Periph_TIM2 belongs to APB1, the error parameter cannot be printed when the program is running, because RCC_APB1Periph_TIM2 and RCC_APB2Periph_AFIO are both equal to 0x00000001. You can go to the stm32f10x_rcc.h file to see. So when you use the parameter check function, you have to pay attention to whether the parameters are wrong. The official error check function is not omnipotent.
Previous article:S3C2440 external SDRAM
Next article:STM32F103 analog IIC
Recommended ReadingLatest update time:2024-11-17 04:58
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- Rambus Launches Industry's First HBM 4 Controller IP: What Are the Technical Details Behind It?
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- Unboxing K210 & STM32F7508-DK
- Common problems and solutions of copper plating technology in PCB process
- Cheer for the Olympic athletes - Get the Tokyo Olympic medal table using STM32
- Hongmeng Development Board Neptune (V) - Source Code Compilation 2
- Download Ultra-Wideband (UWB) For Dummies
- Easy-to-use embedded operating system interface library——LittlevGL
- Photoelectric direct reading valve controlled water meter solution
- TMS320F2838x microcontroller with connection manager
- 17 MG6 smart key replaced with Maserati original shell (with keyless entry, one-button start)
- LSM6DSR iNEMO inertial module related information