我正在嘗試設計一個數據結構(爲了節省空間,我認爲它更簡短,但我認爲您有這個想法)用於字節級通信:初始化,構造並將結構轉換爲字節數組會導致錯位
/* PACKET.H */
#define CM_HEADER_SIZE 3
#define CM_DATA_SIZE 16
#define CM_FOOTER_SIZE 3
#define CM_PACKET_SIZE (CM_HEADER_SIZE + CM_DATA_SIZE + CM_FOOTER_SIZE)
// + some other definitions
typedef struct cm_header{
uint8_t PacketStart; //Start Indicator 0x5B [
uint8_t DeviceId; //ID Of the device which is sending
uint8_t PacketType;
} CM_Header;
typedef struct cm_footer {
uint16_t DataCrc; //CRC of the 'Data' part of CM_Packet
uint8_t PacketEnd; //should be 0X5D or ]
} CM_Footer;
//Here I am trying to conver a few u8[4] tp u32 (4*u32 = 16 byte, hence data size)
typedef struct cm_data {
union {
struct{
uint8_t Value_0_0:2;
uint8_t Value_0_1:2;
uint8_t Value_0_2:2;
uint8_t Value_0_3:2;
};
uint32_t Value_0;
};
//same thing for Value_1, 2 and 3
} CM_Data;
typedef struct cm_packet {
CM_Header Header;
CM_Data Data;
CM_Footer Footer;
} CM_Packet;
typedef struct cm_inittypedef{
uint8_t DeviceId;
CM_Packet Packet;
} CM_InitTypeDef;
typedef struct cm_appendresult{
uint8_t Result;
uint8_t Reason;
} CM_AppendResult;
extern CM_InitTypeDef cmHandler;
這裏的目標是爲通過USB接口傳輸數據建立可靠的結構。最後CM_Packet
應該被轉換爲一個uint8_t
數組,並被賦予一個單片機(stm32)的數據發送寄存器。
在main.c
文件我嘗試初始化結構,以及與此相關的包中一些其他的東西:
/* MAIN.C */
uint8_t packet[CM_PACKET_SIZE];
int main(void) {
//use the extern defined in packet.h to init the struct
cmHandler.DeviceId = 0x01; //assign device id
CM_Init(&cmHandler); //construct the handler
//rest of stuff
while(1) {
CM_GetPacket(&cmHandler, (uint8_t*)packet);
CDC_Transmit_FS(&packet, CM_PACKET_SIZE);
}
}
這裏是packet.h
它搞砸了一切,所以不好實現。我添加了packet[CM_PACKET_SIZE]
來觀看,但它就像是隨機生成的。有時候通過純粹的運氣,我可以在這個數組中看到我感興趣的一些值!但它就像1%的時間!
/* PACKET.C */
CM_InitTypeDef cmHandler;
void CM_Init(CM_InitTypeDef *cm_initer) {
cmHandler.DeviceId = cm_initer->DeviceId;
static CM_Packet cmPacket;
cmPacket.Header.DeviceId = cm_initer->DeviceId;
cmPacket.Header.PacketStart = CM_START;
cmPacket.Footer.PacketEnd = CM_END;
cm_initer->Packet = cmPacket;
}
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier,
uint8_t *data){
CM_AppendResult result;
switch(identifier){
case CM_VALUE_0:
handler->Packet.Data.Value_0_0 = data[0];
handler->Packet.Data.Value_0_1 = data[1];
handler->Packet.Data.Value_0_2 = data[2];
handler->Packet.Data.Value_0_3 = data[3];
break;
//Also cases for CM_VALUE_0, 1 , 2
//to build up the CM_Data sturct of CM_Packet
default:
result.Result = CM_APPEND_FAILURE;
result.Reason = CM_APPEND_CASE_ERROR;
return result;
break;
}
result.Result = CM_APPEND_SUCCESS;
result.Reason = 0x00;
return result;
}
void CM_GetPacket(CM_InitTypeDef *handler, uint8_t *packet){
//copy the whole struct in the given buffer and later send it to USB host
memcpy(packet, &handler->Packet, sizeof(CM_PACKET_SIZE));
}
所以,問題是這個代碼給了我99%的時間隨機的東西。它從不具有CM_START
這是數據包的開始指示符到我想要的值。但大多數情況下,它的字節都是CM_END
!我很困惑,找不到原因。正在一個難以調試的嵌入式平臺上工作,我有點迷失在這裏...
提示:在沒有USB代碼的情況下(使用管道或套接字)測試您的代碼,並打包所有結構以避免類型對齊問題。使用代碼來避免字節順序問題(用文字)也是明智的。 – Gil
@Gil檢查了所有函數中的'handler' ...它永遠不會正確對齊,我不認爲這是因爲USB堆棧。因爲它甚至在進入USB傳輸緩衝區之前就已經完成了...... –
這正是我的觀點:如果問題不在USB com中,那麼它就在您的代碼中。然後,printf()和hexdump()是你的朋友,可以找到你做錯的地方。 – Gil