需求

使用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);
}

定义可变参数,获取可变参数个数(这个是在运行时阶段获取的,跟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
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);
}

总结

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

© 2025 hywing 使用 Stellar 创建
总访问 113701 次 | 本页访问 326