stm32 keil宏定义的使用

18 篇文章 0 订阅

常用宏定义

在编写代码的时候经常会用到一些宏定义,使用宏定义可以使我们的代码更加规范,而且使用选择类型的宏定义还可以使我们编写出来的代码更小,也更利于程序的移植与修改。
常用的一些宏定义有#define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif,还有一个找了好久才找到的defined,没错,这个前面没有加#。

#define 定义一个预处理宏
#undef 取消宏的定义
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined  与#if, #elif配合使用,判断某个宏是否被定义

使用方式

一、预编译

预编译一般使用的是#define,可以定义一些常量,也可以直接定义一个对象,或者是一个函数,与之相对应的就是#undef,就是将#define定义的宏定义进行取消,我一般在调试代码的时候会用到。

//#define
// 常量定义
#define MCU_ID_ADDR 0x1FFFF7AC
// 标识重定义
#define SYS_LED_Pin GPIO_PIN_3
// 预编译宏
#define _DEBUG
// 最小值函数
#define MIN(a,b) ((a)>(b)? (a):(b))
//#undef可以取消宏定义,与#define对应
// 预编译宏
#undef _DEBUG

二、条件编译

1、使用#ifdef和#endif来灵活定义变量,注意每个#ifdef后面都必须有一个#endif结尾

//hal库中定义包含.h文件的宏定义
#ifdef HAL_RCC_MODULE_ENABLED
  #include "stm32f4xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */

#ifndef使用方式类似

//定义头文件常用的方式
#ifndef __STM32F4xx_HAL_CONF_H
#define __STM32F4xx_HAL_CONF_H

#endif

2、#ifdef、#ifndef、#else、#endif
条件编译中相对常用的预编译指令

#ifdef ABC
// ... codes while definded ABC
#elif (CODE_VERSION > 2)
// ... codes while CODE_VERSION > 2
#else
// ... remained cases
#endif // #ifdef ABC 

#ifndef使用方式类似,这里就不举例了
3、#if、#elif、#else、#endif
#if可支持同时判断多个宏的存在,与常量表达式配合使用

#if 常量表达式1
// ... some codes
#elif 常量表达式2
// ... other codes
#elif 常量表达式3
// ...
...
#else
// ... statement
#endif

常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,如果常量表达式为一个未定义的宏, 那么它的值被视为0

在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。

#ifdef __cplusplus
 extern "C" {
#endif

注意: #if、#elif之后的宏只能是对象宏。如果宏未定义,或者该宏是函数宏,则编译器可能会有对应宏未定义的警告。
4、defined
defined用来测试某个宏是否被定义。defined(name): 若宏被定义,则返回1,否则返回0。
它与#if、#elif、#else结合使用来判断宏是否被定义,乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef。defined可用于在一条判断语句中声明多个判别条件;#ifdef和#ifndef则仅支持判断一个宏是否定义。

#define STM31F4

#if defined STM32F0
#define MCU_ID_ADDR 0x1FFFF7AC
#elif defined STM32F1
#define MCU_ID_ADDR 0x1FFFF7E8
#elif defined STM32F2
#define MCU_ID_ADDR 0x1FFF7A10
#elif defined STM32F3
#define MCU_ID_ADDR 0x1FFFF7AC
#elif defined STM32F4
#define MCU_ID_ADDR 0x1FFF7A10
#elif defined STM32F7
#define MCU_ID_ADDR 0x1FF0F420
#elif defined STM32L0
#define MCU_ID_ADDR 0x1FF80050
#elif defined STM32L1
#define MCU_ID_ADDR 0x1FF80050
#elif defined STM32L4
#define MCU_ID_ADDR 0x1FFF7590
#elif defined STM32H7
#define MCU_ID_ADDR 0x1FF0F420
#endif

还有就是在defined前面加一个!的,表示没有定义,和取反的意思一样

#if !defined  (HSE_VALUE)
  #define HSE_VALUE    8000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
内置 "cmd-list" 命令获取所有命令列表 支持 tab 键补全命令 支持 backspace 回退,这个在 putty 上有 bug ,还没修复。在secureCRT正常。 支持上下箭头回溯历史,这个功能没有做的很好; 支持左右箭头编辑当前命令行输入; 提供 shell_cmdparam()函数转换命令后所跟的数字参数(字符串转整型),详见 demo 提供 shell_option_suport() 函数,使命令行支持 getopt()函数,详见 demo 系统共有9个文件,全部与硬件无关,编译语言要在 C99 以上(keil 在 project -> Options .. -> c/c++ -> C99 勾上) kernel.h // 一些必要的宏定义 shell.c,shell.h //具体的命令行解释的实现 ustdio.c,ustdio.h //非标准输出文件,重新链接 printf ,并提供一个小巧型的 printk 函数 avltree.c,avltree.h //平衡二叉树支持,shell 默认用链表建立查询机制,有必要可在shell.h 中开启二叉树 getopt.c,getopt.h //网上找的 getopt() 源码 除了 getopt.c,getopt.h 两个文件是我从网上找的源码,主要实现命令行的 getopt()解析,其他的都是笔者所写。 使用: 1,首先把 shell.c ustdio.c 加入工程,这两个文件是必须的。 如果不用 getopt()函数可以不添加getopt.c文件。 shell默认使用链表来构建查询系统,但也提供了平衡二叉树的方式,在shell.h中有开启的开关,如不需要可以不添加avltree.c。 include "shell.h" 2,先对硬件进行基本的初始化。 撰写串口发送函数,形如 void usart_puts(char * str , uint16_t len) ; 调用函数 shell_init("shell >",usart_puts); //初始化shell的输入标志和默认输出指向 串口接收以包为单位。 3,新建全局变量 struct shell_input serial_shell ; 并初始化 SHELL_INPUT_INIT(&serial;_shell ,usart_puts);初始化输入缓存和输出交互; 4,串口接收到一整包函数后,调用 shell_input(&serial;_shell , packet , pktlen) ;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

k-kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值