目录
一、编译器预定义的宏
二、c语言内置宏
三、实用宏定义
在stm32系列单片机里的core_cmx.h(x:0/3/4/7)头文件里有如下一段宏定义:
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
#define __STATIC_INLINE static inline
#elif defined ( __TMS470__ )
#define __ASM __asm /*!< asm keyword for TI CCS Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __CSMC__ )
#define __packed
#define __ASM _asm /*!< asm keyword for COSMIC Compiler */
#define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */
#define __STATIC_INLINE static inline
#endif
在嵌入式开发中,单片机可以在不同的平台上进行使用,例如stm32单片机可以在IAR平台上进行开发,也可以在KEIL平台上开发。不同的开发平台有不同的编译器,不同的编译器所使用的工具链也不同。在不同的工具链中,c文件和汇编文件中inline和asm关键字的写法也不同。为了兼容不同平台,增强代码的可移植性,在代码里使用宏定义替代,这样就能在不同编译器预处理时产生适用于该工具链的代码。
PS: __CC_ARM // ARM编译器预定义宏
__GNUC__ // GNU 编译器的预定义宏
__ICCARM__ // IAR编译器预定义宏
__TMS470__ // CCS编译器预定义宏
__TASKING__ // TASKING编译器预定义宏
__CSMC__ // COSMIC编译器预定义宏
C语言中有许多内置宏,在嵌入式开发中,这些内置宏常用在代码的跟踪调试,输入日志或者版本控制等等,下面列举一些常用的内置宏:
__DATE__ 当前日期,输出格式为 "MMM DD YYYY"
__TIME__ 当前时间,输出格式为 "HH:MM:SS"
__FILE__ 当前文件名
__LINE__ 当前行号
__STDC__ 当编译器以 ANSI 标准编译时,则输出 1
__FUNCTION__(或者__func__ ) 所在函数名的字符串
其中,__DATE__ 和__TIME__常用来输出软件版本信息。
#include
const char Version[]="Version 0.0.1 ";
int main(void)
{
printf("%s,%s,%s",Version,__DATE__,__TIME__);
return 0;
}
__FILE__和__LINE__常用来定位,跟踪调试。
//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 /* USE_FULL_ASSERT */
//stm32f10x_adc.c
void ADC_DeInit(ADC_TypeDef* ADCx)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
...
}
上面两个代码片段只是简单的说明内置宏的用法,在实际的项目开发中,灵活地去运用这些内置宏对我们在调试阶段有很大帮助。
1.最大值和最小值
#define MAX(x, y) (((x)>(y))?(x):(y))
#define MIN(x, y) (((x)<(y))?(x):(y))
2.交换两个变量的值
//加减法实现
#define SWAP(x, y)\
do\
{\
x = x + y;\
y = x - y;\
x = x - y;\
}while(0)
3.数组元素个数
#define ARRAY_SIZE(array) (sizeof((array))/sizeof((array[0])))
4.位操作
//将data的第bit位置为1
#define SET_BIT(data,bit) ((data) |= (1<<(bit)))
//将data的第bit位清零
#define CLR_BIT(data,bit) ((data) &= (~(1<<(bit))))
//将data的第bit位取反
#define CPL_BIT(data,bit) ((data) ^= ((1<<(bit))))
//获取data的第bit位
#define GET_BIT(data,bit) ((data) & (1<<(bit)))