STM32基础知识——位操作/宏定义/#ifdef/#if defined

STM32HAL库学习:位操作与条件编译详解,
本文介绍了STM32HAL库开发中的位操作技巧,包括位与、或、异或及取反的使用,以及宏定义和条件编译(#ifdef)在程序中的应用,帮助开发者理解和利用这些技术进行高效编程。

前言

很久没发博客了,最近的学习都写在了自己的文档中,在学习新的STM32HAL库开发,还有STM32Cubemx软件,以及imu知识学习,之后会逐一将自己的学习总结发出来供大家参考学习。

一、位操作

(一)简介

位运算符的优先级从高到低,依次为~、&、^、|,
取反是单目运算符,其余为双目运算符
在这里插入图片描述
1.按位与&
同1则1,有0 则0
2.按位或|
有1则1,同0则0
3.按位异或^
相同为1,不同为0
4.取反~,左移<<,右移>>

(二)位操作的妙用

1.不改变其他位置,对想要的某几个位设值
先&清零,再|值运算
如想让value的第4-7位为0100(假设32位)

Value&=0xFF0F;
Value|=0x0040;

2.将某位设置为1
先1左移,再|值运算
如将value第4位置1

Value|=1<<4

3.将某位置零
先1左移,取反相等
如将value第3位置0

Value=~1<<3);

二、宏定义

#define 标识符 字符串

三、#ifdef和#if defined

1. 单片机程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而
当条件不满足时则编译另一组语句。条件编译命令最常见的形式为:

#ifdef 标识符
程序段 1
#else
程序段 2
#endif
它的作用是:当标识符已经被定义过(一般是用#define 命令定义),则对程序段 1 进行编译,否则编译程序段 2。 其中#else 部分也可以没有,即:
#ifdef
程序段 1
#endif

2. #if defined使用就是和#elif、#endif使用
可以判断多个选择的定义

3. extern外部调用
在其他.c文件中使用后,再调用

c语言部分不再复习,优快云博客主页都有

/** ****************************************************************************** * @file stm32f1xx.h * @author MCD Application Team * @brief CMSIS STM32F1xx Device Peripheral Access Layer Header File. * * The file is the unique include file that the application programmer * is using in the C source code, usually in main.c. This file contains: * - Configuration section that allows to select: * - The STM32F1xx device used in the target application * - To use or not the peripheral's drivers in application code(i.e. * code will be based on direct access to peripheral's registers * rather than drivers API), this option is controlled by * "#define USE_HAL_DRIVER" * ****************************************************************************** * @attention * * Copyright (c) 2017-2021 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /** @addtogroup CMSIS * @{ */ /** @addtogroup stm32f1xx * @{ */ #define STM32F103x8//(实际改成6) #ifndef __STM32F1XX_H #define __STM32F1XX_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** @addtogroup Library_configuration_section * @{ */ /** * @brief STM32 Family */ #if !defined (STM32F1) #define STM32F1 #endif /* STM32F1 */ /* Uncomment the line below according to the target STM32L device used in your application */ #if !defined (STM32F100xB) && !defined (STM32F100xE) && !defined (STM32F101x6) && \ !defined (STM32F101xB) && !defined (STM32F101xE) && !defined (STM32F101xG) && !defined (STM32F102x6) && !defined (STM32F102xB) && !defined (STM32F103x6) && \ !defined (STM32F103xB) && !defined (STM32F103xE) && !defined (STM32F103xG) && !defined (STM32F105xC) && !defined (STM32F107xC) /* #define STM32F100xB */ /*!< STM32F100C4, STM32F100R4, STM32F100C6, STM32F100R6, STM32F100C8, STM32F100R8, STM32F100V8, STM32F100CB, STM32F100RB and STM32F100VB */ /* #define STM32F100xE */ /*!< STM32F100RC, STM32F100VC, STM32F100ZC, STM32F100RD, STM32F100VD, STM32F100ZD, STM32F100RE, STM32F100VE and STM32F100ZE */ /* #define STM32F101x6 */ /*!< STM32F101C4, STM32F101R4, STM32F101T4, STM32F101C6, STM32F101R6 and STM32F101T6 Devices */ /* #define STM32F101xB */ /*!< STM32F101C8, STM32F101R8, STM32F101T8, STM32F101V8, STM32F101CB, STM32F101RB, STM32F101TB and STM32F101VB */ /* #define STM32F101xE */ /*!< STM32F101RC, STM32F101VC, STM32F101ZC, STM32F101RD, STM32F101VD, STM32F101ZD, STM32F101RE, STM32F101VE and STM32F101ZE */ /* #define STM32F101xG */ /*!< STM32F101RF, STM32F101VF, STM32F101ZF, STM32F101RG, STM32F101VG and STM32F101ZG */ /* #define STM32F102x6 */ /*!< STM32F102C4, STM32F102R4, STM32F102C6 and STM32F102R6 */ /* #define STM32F102xB */ /*!< STM32F102C8, STM32F102R8, STM32F102CB and STM32F102RB */ /* #define STM32F103x6 */ /*!< STM32F103C4, STM32F103R4, STM32F103T4, STM32F103C6, STM32F103R6 and STM32F103T6 */ /* #define STM32F103xB */ /*!< STM32F103C8, STM32F103R8, STM32F103T8, STM32F103V8, STM32F103CB, STM32F103RB, STM32F103TB and STM32F103VB */ /* #define STM32F103xE */ /*!< STM32F103RC, STM32F103VC, STM32F103ZC, STM32F103RD, STM32F103VD, STM32F103ZD, STM32F103RE, STM32F103VE and STM32F103ZE */ /* #define STM32F103xG */ /*!< STM32F103RF, STM32F103VF, STM32F103ZF, STM32F103RG, STM32F103VG and STM32F103ZG */ /* #define STM32F105xC */ /*!< STM32F105R8, STM32F105V8, STM32F105RB, STM32F105VB, STM32F105RC and STM32F105VC */ /* #define STM32F107xC */ /*!< STM32F107RB, STM32F107VB, STM32F107RC and STM32F107VC */ #endif /* Tip: To avoid modifying this file each time you need to switch between these devices, you can define the device in your toolchain compiler preprocessor. */ #if !defined (USE_HAL_DRIVER) /** * @brief Comment the line below if you will not use the peripherals drivers. In this case, these drivers will not be included and the application code will be based on direct access to peripherals registers */ /*#define USE_HAL_DRIVER */ #endif /* USE_HAL_DRIVER */ /** * @brief CMSIS Device version number */ #define __STM32F1_CMSIS_VERSION_MAIN (0x04) /*!< [31:24] main version */ #define __STM32F1_CMSIS_VERSION_SUB1 (0x03) /*!< [23:16] sub1 version */ #define __STM32F1_CMSIS_VERSION_SUB2 (0x04) /*!< [15:8] sub2 version */ #define __STM32F1_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */ #define __STM32F1_CMSIS_VERSION ((__STM32F1_CMSIS_VERSION_MAIN << 24)\ |(__STM32F1_CMSIS_VERSION_SUB1 << 16)\ |(__STM32F1_CMSIS_VERSION_SUB2 << 8 )\ |(__STM32F1_CMSIS_VERSION_RC)) /** * @} */ /** @addtogroup Device_Included * @{ */ #if defined(STM32F100xB) #include "stm32f100xb.h" #elif defined(STM32F100xE) #include "stm32f100xe.h" #elif defined(STM32F101x6) #include "stm32f101x6.h" #elif defined(STM32F101xB) #include "stm32f101xb.h" #elif defined(STM32F101xE) #include "stm32f101xe.h" #elif defined(STM32F101xG) #include "stm32f101xg.h" #elif defined(STM32F102x6) #include "stm32f102x6.h" #elif defined(STM32F102xB) #include "stm32f102xb.h" #elif defined(STM32F103x6) #include "stm32f103x6.h" #elif defined(STM32F103xB) #include "stm32f103xb.h" #elif defined(STM32F103xE) #include "stm32f103xe.h" #elif defined(STM32F103xG) #include "stm32f103xg.h" #elif defined(STM32F105xC) #include "stm32f105xc.h" #elif defined(STM32F107xC) #include "stm32f107xc.h" #else #error "Please select first the target STM32F1xx device used in your application (in stm32f1xx.h file)" #endif /** * @} */ /** @addtogroup Exported_types * @{ */ typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; typedef enum { DISABLE = 0, ENABLE = !DISABLE } FunctionalState; #define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) typedef enum { SUCCESS = 0U, ERROR = !SUCCESS } ErrorStatus; /** * @} */ /** @addtogroup Exported_macros * @{ */ #define SET_BIT(REG, BIT) ((REG) |= (BIT)) #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) #define READ_BIT(REG, BIT) ((REG) & (BIT)) #define CLEAR_REG(REG) ((REG) = (0x0)) #define WRITE_REG(REG, VAL) ((REG) = (VAL)) #define READ_REG(REG) ((REG)) #define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) #define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) /* Use of CMSIS compiler intrinsics for register exclusive access */ /* Atomic 32-bit register access macro to set one or several bits */ #define ATOMIC_SET_BIT(REG, BIT) \ do { \ uint32_t val; \ do { \ val = __LDREXW((__IO uint32_t *)&(REG)) | (BIT); \ } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \ } while(0) /* Atomic 32-bit register access macro to clear one or several bits */ #define ATOMIC_CLEAR_BIT(REG, BIT) \ do { \ uint32_t val; \ do { \ val = __LDREXW((__IO uint32_t *)&(REG)) & ~(BIT); \ } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \ } while(0) /* Atomic 32-bit register access macro to clear and set one or several bits */ #define ATOMIC_MODIFY_REG(REG, CLEARMSK, SETMASK) \ do { \ uint32_t val; \ do { \ val = (__LDREXW((__IO uint32_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \ } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \ } while(0) /* Atomic 16-bit register access macro to set one or several bits */ #define ATOMIC_SETH_BIT(REG, BIT) \ do { \ uint16_t val; \ do { \ val = __LDREXH((__IO uint16_t *)&(REG)) | (BIT); \ } while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \ } while(0) /* Atomic 16-bit register access macro to clear one or several bits */ #define ATOMIC_CLEARH_BIT(REG, BIT) \ do { \ uint16_t val; \ do { \ val = __LDREXH((__IO uint16_t *)&(REG)) & ~(BIT); \ } while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \ } while(0) /* Atomic 16-bit register access macro to clear and set one or several bits */ #define ATOMIC_MODIFYH_REG(REG, CLEARMSK, SETMASK) \ do { \ uint16_t val; \ do { \ val = (__LDREXH((__IO uint16_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \ } while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \ } while(0) /** * @} */ #if defined (USE_HAL_DRIVER) #include "stm32f1xx_hal.h" #endif /* USE_HAL_DRIVER */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __STM32F1xx_H */ /** * @} */ /** * @} */ stm32f1xx.h
最新发布
07-16
STM32项目中更改宏定义主要涉及对编译器预处理阶段的配置调整,以适配不同的芯片型号或特定功能需求。STM32系列微控制器根据其容量、性能和外设配置的不同被划分为多个子系列,每个子系列都有对应的宏定义用于激活特定的头文件和寄存器定义。 ### 更改宏定义的方法 #### 1. 修改 `stm32f1xx.h` 中的宏定义 STM32F1系列的标准外设库(Standard Peripheral Library)中,芯片型号通过宏定义来指定,例如 `STM32F10X_LD` 表示小容量产品,`STM32F10X_MD` 表示中等容量,`STM32F10X_HD` 表示大容量产品。这些宏定义通常在 `stm32f1xx.h` 文件中定义[^1]。 打开该文件后,可以找到如下类似的宏定义: ```c #define STM32F10X_LD /*!< STM32F10X_LD: STM32 Low density devices */ //#define STM32F10X_MD /*!< STM32 Medium density devices */ //#define STM32F10X_HD /*!< STM32 High density devices */ ``` 将需要启用的宏定义前的注释符 `//` 删除即可生效。例如从 `STM32F10X_HD` 切换到 `STM32F10X_LD`,只需取消对应行的注释并注释掉其他不适用的宏定义。 #### 2. 在项目设置中添加宏定义 另一种常见方法是在开发环境(如 Keil uVision 或 STM32CubeIDE)的项目配置中直接添加宏定义。这样可以在不修改标准头文件的情况下完成配置。 - **Keil uVision**: - 打开项目后,右键点击目标,选择 "Options for Target"。 - 进入 "C/C++" 标签页,在 "Define" 输入框中添加所需的宏定义,例如 `STM32F10X_LD`。 - **STM32CubeIDE**: - 右键项目,选择 "Properties"。 - 进入 "C/C++ Build → Settings",在编译器选项中找到 "Preprocessor" 部分,添加相应的宏定义。 #### 3. 使用条件编译控制代码路径 宏定义不仅用于指定芯片类型,还可以用于启用或禁用特定的功能模块或代码段。例如: ```c #ifdef USE_USART1 void configure_usart1(void) { // USART1 初始化代码 } #endif ``` 在项目设置中定义 `USE_USART1` 宏后,上述函数将被包含在编译过程中;否则,该函数将被忽略。 #### 4. 自定义宏定义系统时钟配置 某些宏定义还用于控制系统时钟源和频率,例如 `HSE_VALUE` 和 `HSI_VALUE`,它们分别定义外部高速晶振和内部高速时钟的频率值。用户可以根据实际硬件配置修改这些宏定义,以确保系统时钟计算正确。 ```c #if !defined (HSE_VALUE) #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ ``` 如果使用了不同频率的外部晶振,应相应地修改此值。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值