嵌入式C语言中常量的应用实例(c语言嵌入式是什么意思)
常量,我们都知道,就是数值保持不变的量。
在C语言中,常量一旦初始化了,它的值将在整个程序运行周期内,不允许发生任何变化。常量与变量是相对的,我们实际项目中经常会用到它。
定义常量的两种方式
C语言中主要有两种方式定义常量:一种是define,一种是const。define是宏定义,const是常量限定符。
比如,定义一些通用常量,
#ifndef true
#define true (1)
#endif
#ifndef false
#define false (0)
#endif
#ifndef NULL
#define NULL (0)
#endif
时间常量
#define TIME_BASE 10
#define TIME_10MS (10/TIME_BASE)
#define TIME_20MS (20/TIME_BASE)
#define TIME_30MS (30/TIME_BASE)
#define TIME_40MS (40/TIME_BASE)
#define TIME_50MS (50/TIME_BASE)
#define TIME_60MS (60/TIME_BASE)
#define TIME_70MS (70/TIME_BASE)
#define TIME_80MS (80/TIME_BASE)
#define TIME_100MS (100/TIME_BASE)
电压常量
#define LV_18 216
#define LV_17 204
#define LV_16 192
#define LV_15 180
#define LV_14 168
#define LV_13 156
#define LV_12 144
#define LV_11 132
#define LV_10 120
#define LV_9 108
#define LV_8 96
以上都是用的define,有人会说用const更好。比如,
const bool true = 1;
const bool false = 0;
理由是,const这种定义方式如果出现错误了,编译器会容易指出错误的具体位置。而不像define这种定义方式,报错都报得不直接,毕竟要考虑宏替换之后的情况。
其实,我觉得还好。在我看来,define就是为了给常数起名字。在实际编程过程中,我们应该尽量避免在程序中出现一些奇怪的数字,因为如果时间久了我们回头再来看这些程序,这些突兀的数字对于我们来说代表什么,很难一时半会弄清楚。
而const更适合定义常量数组,
const t_uint32 C_RM_ID[TOTAL_C_RM] =
{
C_MID_ICM_TSCO,
C_MID_EMS_EEC,
C_MID_EMS_CCVS,
C_MID_ABM,
C_MID_APM,
C_MID_TESTER_BCM,
C_MID_TESTER_FUN
};
特别是比较大的数组,一定要定义常量数组,因为单片机的RAM空间是非常有限的,如果不加const限定,编译器就会将其分配到RAM空间中;只有加上了const,编译器才会将其分配到ROM中。普通单片机的RAM空间是要远远少于其ROM空间的。
还是举个例子,前面我有介绍的高频接收模块ATA5781,关于它的配置信息就有1K的字节,
const uint8_t ATA5781_config_data[1024]=
{
0x32,0x06,0x03,0x68,0xDD,0x72,0x01,0xC7,0x00,0x02,0x00,0x00,0x00,0xD9,0x2C,0x88,
0x03,0x40,0x00,0x59,0x01,0x03,0x00,0x10,0x03,0x24,0x40,0x10,0x00,0x85,0xC8,0x00,
0x07,0x0C,0x0E,0x0F,0x0E,0x0C,0x09,0x05,0x01,0xFC,0xF7,0xF3,0xEF,0xEB,0xE9,0xE8,
0xE9,0xEC,0xF0,0xF7,0x01,0x0D,0x00,0xFF,0xFF,0xFF,0xFF,0x83,0x00,0x00,0x00,0x00,
0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,
0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x80,0x00,0x00,0x00,0x00,0x46,0x00,0x80,0xBF,0xC3,0x14,0x20,0x40,0x00,0x50,0x03,
0x60,0x00,0x01,0x00,0x11,0x00,0x21,0x00,0x01,0x00,0x11,0x00,0x21,0x00,0x01,0x00,
0x11,0x00,0x21,0x00,0x01,0x00,0x11,0x00,0x21,0x00,0x01,0x02,0x03,0x14,0x86,0x86,
0xA5,0xA5,0x46,0x46,0xC8,0x08,0x1F,0x1F,0x1F,0x1F,0x0F,0x0F,0x00,0x07,0x3C,0x10,
0x07,0xAF,0x01,0x1B,0x02,0xD8,0x00,0x68,0x00,0x64,0x00,0x90,0x0A,0x08,0x00,0x00,
0x51,0x00,0x50,0x10,0x20,0xA9,0xAA,0xAA,0xAA,0xA9,0xAA,0xAA,0xAA,0x87,0x87,0x08,
0x08,0xAF,0xAF,0x0F,0x0F,0xD3,0xC9,0xB2,0xB5,0x00,0x00,0x96,0x06,0x3B,0x01,0x2F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
......
};
有的单片机总共才2k的RAM空间,如果不加const,你这一个数组就占用去了一半。其他的程序整个挤在剩下的空间里,除开其他变量不说,还有堆栈什么的,肯定不够用了。
const更多的是提供锁保护功能,除了像上面这些在定义中“锁变量”,还可以在函数中“锁参数”。
uint8 CAN_TxBufConfig(const CAN_TX_CFG *txConfig)
{
uint8 result = CAN_FAIL;
/* Write TX CMD Register */
CY_SET_REG32(CAN_TX_CMD_PTR(txConfig->txmailbox), (txConfig->txcmd | CAN_TX_WPN_SET));
if ((CY_GET_REG32(CAN_TX_CMD_PTR(txConfig->txmailbox)) &
CAN_TX_READ_BACK_MASK) == (txConfig->txcmd & CAN_TX_WPN_CLEAR))
{
/* Write TX ID Register */
CY_SET_REG32(CAN_TX_ID_PTR(txConfig->txmailbox), txConfig->txid);
if (CY_GET_REG32(CAN_TX_ID_PTR(txConfig->txmailbox)) == txConfig->txid)
{
result = CYRET_SUCCESS;
}
}
return (result);
}
const在这里例子中,实际上就保护了CAN发送的配置不会被篡改。
小结
在常量定义中,define只适合给常量命名,const则适合更复杂的常量结构的定义,还能实现锁保护的功能。