嵌入式开发技巧汇总
宏定义相关
#error
error 可以直接在编译器中打出error,用于必须的配置文件中使用。例如
1
| #error "please select device name"
|
嵌入式中实现配置文件的方法(工程文件的方式)
首先建立一个扩展名文件 DEVINFO.txt,扔进文件夹
1 2 3 4 5
|
#define DEV_NAME DEFAULT
#define DEV_ID 0
|
在.h文件中声明
1 2 3 4 5 6 7 8 9 10 11
| #ifndef _DEVICE_H #define _DEVICE_H
#ifndef DEVINFO_FILENAME #define DEVINFO_FILENAME DEVINFO.txt #endif
void Device_printfMsg(void);
#endif
|
就可以在.c文件中使用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include "device.h" #include <stdint.h> #include <stdio.h>
#define _STR(s) #s #define MollocDefineToStr(mal) _STR(mal)
#include MollocDefineToStr(DEVINFO_FILENAME)
static const char devType[] = MollocDefineToStr(DEV_NAME); static uint32_t devID = DEV_ID; static const char devDName[] = MollocDefineToStr(DEV_NAME) "_" MollocDefineToStr(DEV_ID) ".local";
void Device_printfMsg(void){ printf("Device: %s\r\n" , devType); printf("DevID: %u\r\n" , devID); printf("DomainName: %s\r\n" , devDName); }
|
在.c文件中最重要的是这样一句话
1
| #include MollocDefineToStr(DEVINFO_FILENAME)
|
这句话在经过编译器编译后会变成 #include “DEVINFO.txt”。这种成组绑定,固定的配置信息很适合用这种方式耦合进不同的配置文件中去。
一些比较奇特的宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <assert.h>
#define __JOIN(x,y) x##y #define __CHAR(x) #@x #define __S(x) #x #define __ST(x) _T(#x) #define _S(x) __S(x) #define _ST(x) __ST(x) #define _TO_STR(x, y) _S(x) "" _S(y) #define _TO_STRT(x, y) _T( _S(x) "" _S(y) )
bool testStrMacro() { int ab = 12; assert(__JOIN(1, 2) == 12); assert(__JOIN("a", "b") == "ab"); assert(__JOIN(a, b) == 12);
auto a = __CHAR(65); assert(a == '65'); assert(__CHAR(中国) == '中国'); auto cc = __CHAR(PNG); assert(__CHAR(PNG) == 0x504e47);
assert(__S(65) == "65"); assert(__ST(65) == _T("65"));
#define test a #define test_s "a" assert(__S(test) == "test"); assert(__ST(test) == _T("test"));
assert(_S(test) == "a"); assert(_ST(test) == _T("a")); assert(_TO_STRT(test, 123) == _T("a123")); assert(_TO_STR(test, 123) == "a123");
auto b = _TO_STR(__S(test), 123); assert(_TO_STR(__S(test), 123) == "\"test\"123"); auto c = _TO_STR(_S(test), 123); assert(_TO_STR(_S(test), 123) == "\"a\"123"); assert(_TO_STR(_S(test), _TO_STR(123, 456)) == "\"a\"\"123\" \"\" \"456\""); return true; }
|
print是否输出设置
1 2 3 4 5 6 7 8 9 10 11 12 13
| #ifndef _DEBUG_MSG_H #define _DEBUG_MSG_H #include <stdio.h> #ifdef _DEBUG #define _dbg_printf0(format) ((void)printf(format)) #define _dbg_printf1(format,p1) ((void)printf(format,p1)) …… #else #define _dbg_printf0(format) #define _dbg_printf1(format,p1) …… #endif #endif
|
这样,只要在各个模块中引用这个文件就可以用统一的接口输出调试信息。在主配置文件中定义_DEBUG 所有的调试printf就是真实的printf,否则作为空语句无意义。
1 2 3 4 5 6 7
| #include "DebugMsg.h" void Device_printfMsg(void){ _dbg_printf0("Device_printfMsg called.\r\n"); printf("Device: %s\r\n" , devType); printf("DevID: %u\r\n" , devID); printf("DomainName: %s\r\n" , devDName); }
|