Common C Language Knowledge Points in STM32

The C language is essential foundational knowledge in microcontroller development. This article lists some basic C language knowledge points encountered while learning STM32, hoping to be helpful to everyone.

01

Bit ManipulationNext, we will explain several bit operators and then discuss techniques for using bit manipulation. The C language supports the following six bit operations:Common C Language Knowledge Points in STM32Six Bit OperationsNext, we will focus on some practical techniques for bit manipulation in microcontroller development.1.1 Setting Specific Bits Without Changing OthersThis scenario is often used in microcontroller development. The method is to first clear the bits that need to be set using the & operator, and then set the value using the | operator.For example, to change the state of GPIOA, you can first clear the register value:Common C Language Knowledge Points in STM32Then perform the | operation with the value to be set:Common C Language Knowledge Points in STM321.2 Using Shift Operations to Improve Code ReadabilityShift operations are very important in microcontroller development. Below is a line of code from the delay_init function:

SysTick->CTRL |= 1 << 1;

This operation sets the 1st bit (counting from 0) of the CTRL register to 1. Why use a left shift instead of directly setting a fixed value?Actually, this is to improve code readability and reusability. This line of code clearly indicates that the 1st bit is being set to 1. If written as:

SysTick->CTRL |= 0X0002;

Although it achieves the same effect, its readability is slightly worse, and modifications can be cumbersome.1.3 Bitwise NOT Operation Usage TechniquesThe bitwise NOT operation is often used when setting registers, commonly used to clear one or more bits. Below is a line of code from the delay_us function:

SysTick->CTRL &= ~(1 << 0);    /* Disable SYSTICK */

This code can be interpreted as setting only the 0th bit (least significant bit) of the CTRL register to 0, while keeping the values of other bits unchanged.Similarly, if we do not use the bitwise NOT and write the code as:

SysTick->CTRL &= 0XFFFFFFFE;        /* Disable SYSTICK */

It is evident that the former is much better in terms of readability and maintainability than the latter.1.4 Bitwise XOR Operation Usage TechniquesThis function is very suitable for toggling a specific bit, a common application scenario is controlling an LED to blink, such as:

GPIOB->ODR ^= 1 << 5;

Executing this code will toggle the output state of PB5 once. If our LED is connected to PB5, we will see the LED blinking.

02

#define Macro Definitions#define is a preprocessor command in C language used for macro definitions (defining constants), which can improve the readability of source code and facilitate programming. The common format is:Common C Language Knowledge Points in STM32“Identifier” is the name of the defined macro. “String” can be a constant, expression, format string, etc. For example:Common C Language Knowledge Points in STM32Defines the value of the identifier HSE_VALUE as 8000000, where the U after the number indicates unsigned.As for other knowledge about #define macro definitions, such as macro definitions with parameters, we will not elaborate further here.

03

#ifdef Conditional CompilationDuring microcontroller program development, it is common to encounter a situation where a group of statements is compiled when a certain condition is met, and another group of statements is compiled when the condition is not met. The most common form of conditional compilation command is:

#ifdef Identifier    Code Segment 1#else    Code Segment 2#endif

Its function is: when the identifier has been defined (generally defined using the #define command), compile Code Segment 1; otherwise, compile Code Segment 2. The #else part can also be omitted, as follows:

  #ifdef    Code Segment 1    #endif

Conditional compilation is widely used in the HAL library, and you will often see such statements in the stm32mp1xx_hal_conf.h header file:

   #if !defined  (HSE_VALUE)      #define HSE_VALUE            24000000U    #endif

If the HSE_VALUE macro is not defined, it defines the HSE_VALUE macro with a value of 24000000U. Conditional compilation is also a fundamental knowledge of C language.It is worth mentioning that the U in 24000000U indicates an unsigned integer, while UL indicates an unsigned long integer, and F indicates a floating-point type.By adding U, the system will not perform type checking during compilation and will directly assign the value to the corresponding memory in the form of U. If it exceeds the defined variable range, it will be truncated.

04

extern Variable DeclarationIn C language, extern can be placed before a variable or function to indicate that the variable or function is defined in another file, prompting the compiler to look for its definition in other modules when encountering this variable and function.It is important to note that extern-declared variables can be declared multiple times, but defined only once. In our code, you will see statements like:

extern uint16_t g_usart_rx_sta;

This statement declares that the variable g_usart_rx_sta is defined in another file and is used here. Therefore, you can definitely find a definition statement for the variable somewhere:

 uint16_t g_usart_rx_sta;

The use of extern is relatively simple, but it is often used and needs to be mastered.

05

typedef Type Aliastypedef is used to create a new name for an existing type, also known as a type alias, to simplify variable definitions. typedef is most commonly used in the HAL library to define type aliases for structures and enumerations.

struct _GPIO    {        __IO uint32_t CRL;        __IO uint32_t CRH;        …    };

This defines a structure GPIO, allowing us to define a structure variable as follows:

struct  _GPIO  gpiox;       /* Define structure variable gpiox */

However, this is quite cumbersome, as the HAL library has many such structure variables to define. Here we can define an alias for the structure as GPIO_TypeDef, allowing us to define structure variables elsewhere using the alias GPIO_TypeDef as follows:

typedef struct    {            __IO uint32_t CRL;            __IO uint32_t CRH;            …    } GPIO_TypeDef;

Typedef creates an alias GPIO_TypeDef for the structure, allowing us to define structure variables using GPIO_TypeDef: GPIO_TypeDef gpiox;Here, GPIO_TypeDef serves the same purpose as struct _GPIO, but is much more convenient to use.

Source: Zhengdian Yuanzu

END

Community Topic

Discussion this time:

An 8-year veteran leaves for home, salary cut drastically. A colleague in Chengdu has a house with no mortgage, but after losing his job, he is thinking about how to start the next chapter. Summer is coming to an end, and this year it is clear that there is no shortage of people; companies are not hiring at all. Have you also felt the “chill”? How is the city and industry of the forum members?

All participants will receive: 20 E coins

Excellent answers will receive: 300 E coins

Welcome to join the Engineer Career Group

Common C Language Knowledge Points in STM32

Common C Language Knowledge Points in STM32Click to read the original text and participate in the discussion.

Leave a Comment