我正在尝试构建 RTCM SC104 v3 消息。该标准仅要求使用最少的位数将数据传输到它可能定义的最大范围。所以为了加入数据,我打算使用 union 。但是如何将奇数大小的 union 体连接到以前的奇数大小的 union 体呢?例如,消息 1002 需要每个卫星 74 位。没有填充位,直到消息完成并包含 View 中 n 个卫星的所有数据。我可以只建立以前 union 的 union 吗?
typedef union headerGPS
{
struct
{
unsigned int msgNo :12; // creates a 12 bit wide integral field
unsigned int baseID :12; //base index number
unsigned int tow :30; //time of measurement
unsigned int syncFlg :1; //1 if all GNSS readings same time
unsigned int no_gps :5; //number of gps readings
unsigned int smoothInd :1; //smoothing indicator
unsigned int smoothInt :3; //smoothing int rep
} fields;
unsigned char header[8];
} headerGPS;
typedef union data1002
{
struct //74 bits / 9.25 bytes per SV
{
INT8U satID :6; //sat ID 6 bit
INT8U L1ind :1; //L1 indicator 1 bit set 1
INT32U L1range :24; //L1 psuedorange uint24
int diff :20; //L1 phaserange - psuedorange int20
INT8U lockInd :7; //L1 locktime indicator uint7
INT8U ambi :8; //L1 int ambiguity uint8
INT8U cnr :8; //L1 CNR uint8
}fields;
INT8U data[];
}data1002;
bool encode1002( int baseNumber, int gpsEpoch , int numberGpsSV, int numberGloSV, int numberGalSV )
{
std::string message1002;
headerGPS h1002; //create header object
h1002.fields.msgNo = 1002;
h1002.fields.baseID = baseNumber;
h1002.fields.tow = gpsEpoch;
if(numberGloSV > 0 || numberGalSV > 0)
{
h1002.fields.syncFlg = 1;
}
else
{
h1002.fields.syncFlg = 0;
}
h1002.fields.no_gps = numberGpsSV;
h1002.fields.smoothInd = 0;
h1002.fields.smoothInt = 0;
for(int n=0; n<8; n++)
{
message1002 += h1002.header[n];
}//1002 header is complete
return true;
}
好的,所以我正在尝试设置一个位集来准备要发送的数据。我正在使用这种 staement 以所需的顺序填充位集,而无需添加额外的填充位。这是在“for”语句和“if channel data good”语句中。
for(varPos = 0; varPos < 6; varPos ++) //start on 0, end on 5
{
data_1002.set(bitPos,datastream[baseNumber].channel[n].satID & (1<<varPos)); //test bit
bitPos++;
}
data_1002.set(bitPos,1);
bitPos++;
for(varPos = 0; varPos < 24; varPos ++) //start on 0, end on 5
{
data_1002.set(bitPos,codeRange & (1<<varPos)); //test bit
bitPos++;
}
我想将位集中的所有位值复制到字节数组,以使用以下命令发送 TCP/IP 端口:
int noBytes = (bitPos+7)/8; //number of data bytes to copy to array
if(noBytes <=0)
{
noBytes = 0;
}
cout << "number of bytes to process= " << noBytes <<endl;
cout <<"completed bitset size= " << bitPos << endl;
//convert bits to bytes
bitPos = 0;
int byteCount;
for (int w=0; w<noBytes; w++) //bitPos/8 = number of bytes; w+8 because 8 bytes in header
{
for(int q=0; q<8; q++)
{
if(data_1002.test(bitPos+q) == 1)
{
BUFFER[(w+8)] = BUFFER[(w+8)] | (1<<q);
}
else
{
BUFFER[(w+8)] = BUFFER[(w+8)] & (0xFF & (0<<q));
}
}
bitPos = bitPos +8;
byteCount = w+8;
}
cout << "bytecounter= " << byteCount << endl;
cout<<"number btes processed plus header= "<< noBytes+8 <<endl;
for(int w=0; w<noBytes+8; w++)
{
output += BUFFER[w];
}
这看起来应该可以正常工作,但是如果我在编码过程中遗漏了一个错误,我将不胜感激任何帮助。还有没有更简单的方法可以将位集传输到字节数组中发送出去?我阅读并尝试在 stringstream 中插入一个位集,但它会将每个位作为 char 而不是位插入。
最佳答案
您写道,您希望通过创建另一个奇数结构的 union 来连接数据?这将导致 2 个奇数大小的结构引用相同的二进制数据。我想你想要的是追加,比如创建一个包含 2 个 union 的新结构;你想要的是将它们夹在一起而不用填充位?
奇数大小的位压缩结构将始终按字节、字或编译器选择的任何内容对齐。如果将其中两个放在另一个结构中,它们将被填充。你必须换一种方式。
那么,为什么不将所有声明打包到一个结构中呢?可能是因为您多次出现 headerGPS 和 data1002?如果是这样的话,一个解决方案可能是:(尽管我发现预处理器宏是一种 hack,但有时它是唯一的方法)。
#define headerGPS(n) \
unsigned int msgNo_##n :12; \
unsigned int baseID_##n :12; \
unsigned int tow_##n :30; \
unsigned int syncFlg_##n :1; \
unsigned int no_gps_##n :5; \
unsigned int smoothInd_##n :1; \
unsigned int smoothInt_##n :3
#define data1002(n) \
INT8U satID_##n :6; \
INT8U L1ind_##n :1; \
INT32U L1range_##n :24;\
int diff_##n :20;\
INT8U lockInd_##n :7; \
INT8U ambi_##n :8; \
INT8U cnr_##n :8
union gpsdata {
struct {
headerGPS(1);
data1002(1);
data1002(2);
};
INT8U data[];
};
请注意附加运算符 ##
的用法,因此您可以添加唯一的扩展名,使名称变为 satID_1
和 satID_2
。
虽然这个解决方案有点 hack,它可能会混淆您的 IDE 解析器;当我测试时,Eclipse 确实正确地为我建议了成员。
关于c++ - 使用奇数位大小的 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18114712/