需求

使用C语言发送任意个通道的波形数据,要求:接口固定,但参数个数不固定,DSP的开发环境只能用C语言

实现

stdarg是C语言标准库的一部分,我们通过它来实现类似C++的函数模板

1
#include <stdarg.h>

比如给上位机发送数据,一个通道为一个float,可变参数num代表可以发n个通道的波形数据

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
// 发送可变参数float帧(JustFloat格式,无帧头帧尾)
void SCIA_sendFrame_JustFloat(int num, ...)
{
while(isTransmitting) { }

txBufferIndex = 0;
txDataCount = 0;

va_list args;
va_start(args, num);

int i;
for(i = 0; i < num; i++)
{
float value = (float)va_arg(args, double);
FloatUnion data;
data.DataFloat = value;
txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[0] & 0xFF);
txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[0] >> 8) & 0xFF);
txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[1] & 0xFF);
txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[1] >> 8) & 0xFF);
}
va_end(args);

// 添加JustFloat帧尾(原来用过的: 0x00 0x00 0x80 0x7F)
txBuffer[txDataCount++] = 0x00;
txBuffer[txDataCount++] = 0x00;
txBuffer[txDataCount++] = 0x80;
txBuffer[txDataCount++] = 0x7F;

isTransmitting = true;
txBufferIndex = 0;
SCI_enableInterrupt(SCIA_BASE, SCI_INT_TXFF);
}

va_arg的基类型可以是任意的,但是必须要和转换后的类型兼容、匹配,比如double ➡ float,否则结果未知

1
float value = (float)va_arg(args, double); 

定义可变参数,获取可变参数个数(这个是在运行时阶段获取的,跟C++的模板函数不一样)

1
2
3
4
5
6
va_list args;
va_start(args, num);

......

va_end(args);

参数的访问和使用:从0-num遍历可变参数列表,float在可变参数中提升为double,遍历动作要在va_startva_end之内,va_arg是一个出栈动作,并不是基于索引的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
va_start(args, num);

int i;
for(i = 0; i < num; i++)
{
float value = (float)va_arg(args, double);
FloatUnion data;
data.DataFloat = value;
txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[0] & 0xFF);
txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[0] >> 8) & 0xFF);
txBuffer[txDataCount++] = (uint8_t)(data.DataUint16[1] & 0xFF);
txBuffer[txDataCount++] = (uint8_t)((data.DataUint16[1] >> 8) & 0xFF);
}
va_end(args);

总结

  • 可变参数列表是一个数据栈,C语言函数运行调用时,参数从右到左压栈,取参数是从左到右出栈,跟函数参数调用的顺序保持一致
  • C++的函数模板是编译时确定的,通常会生成多份代码实例,但C语言的可变参数模板只有一份实例
  • C语言可以通过宏来实现C++那样的模板

『 下里巴人 』
海纳百川,文以载道
hywing技术自留地
总访问 113701 次 | 本页访问 326