[英]How can I pass a struct in a function with input argument unsigned 32 bit array?
我想計算STM32 micro controller中一些數據的CRC值。 用於計算 CRC 的 HAL function 具有以下占用空間:
uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength);
我的數據存儲在一個結構中:
struct caldata_tag {
float K_P_Htng;
uint16_t K_I_Htng;
uint16_t K_D_Htng;
uint16_t K_P_Coolg; } caldata;
誰是將結構傳遞給 HAL_CRC_Calculate() function 的最安全和最合適的方法?
我正在考慮這個:
#define U32BUFFERSIZE sizeof(struct caldata_tag)/sizeof(uint32_t)
uint32_t buffer[U32BUFFERSIZE];
uint32_t crcValue;
/* calculate the crc value of the data */
memcpy(buffer,&localStruct,U32BUFFERSIZE);
crcValue = HAL_CRC_Calculate(&CrcHandle,buffer,U32BUFFERSIZE);
但我認為這是一種丑陋的方式,你能告訴我是否可以嗎? 或者如果你有更好的主意?
誰是將結構傳遞給
HAL_CRC_Calculate()
function 的最安全和最合適的方法?
挑戰:
HAL_CRC_Calculate()
顯然想根據uint32_t
的倍數計算 CRC。
struct caldata_tag
的大小可能不是uint32_t
大小的倍數。
struct caldata_tag
可能包含 caldata 中未知caldata
的填充。
使用struct caldata_tag
和足夠大的uint32_t
數組的union
。 將其歸零,復制成員,然后計算 CRC。
我認為這是一種丑陋的方式,你能告訴我是否可以嗎? 或者如果你有更好的主意?
形成一個助手function。
// Find the quotient of sizeof caldata_tag / sizeof(uint32_t), rounded up
#define U32BUFFERSIZE ((sizeof(struct caldata_tag) + sizeof(uint32_t) - 1)/sizeof(uint32_t))
uint32_t caldata_CRC(CRC_HandleTypeDef *hcrc, const struct caldata_tag *p) {
// u's size will be a multiple of sizeof uint32_t
union {
uint32_t u32[U32BUFFERSIZE];
struct caldata_tag tag;
} u = { {0} }; // zero every thing
// copy the members, not the padding
u.tag.K_P_Htng = p->K_P_Htng;
u.tag.K_I_Htng = p->K_I_Htng;
u.tag.K_D_Htng = p->K_D_Htng;
u.tag.K_P_Coolg = p->K_P_Coolg;
return HAL_CRC_Calculate(hcrc, u.u32, U32BUFFERSIZE);
}
利用
uint32_t crcValue = caldata_CRC(&CrcHandle, &caldata);
[更新]
進一步研究表明, BufferLength
是uint8_t, uint16_t, uint32_t
的計數,具體取決於hcrc->InputDataFormat.
OP 沒有提供,但如果可以將其設置為uint8_t
。 那么代碼只需要擔心struct caldata
中的填充。
#define U8BUFFERSIZE sizeof(struct caldata_tag)
uint32_t caldata8_CRC(CRC_HandleTypeDef *hcrc, const struct caldata_tag *p) {
// u's size will be a multiple of sizeof uint32_t
union {
uint32_t u32[U32BUFFERSIZE];
struct caldata_tag tag;
} u = { {0} }; // zero every thing
// copy the members, not the padding
u.tag.K_P_Htng = p->K_P_Htng;
u.tag.K_I_Htng = p->K_I_Htng;
u.tag.K_D_Htng = p->K_D_Htng;
u.tag.K_P_Coolg = p->K_P_Coolg;
return HAL_CRC_Calculate(hcrc, u.u32, U8BUFFERSIZE);
}
如果編譯器允許__attribute__((__packed__))
,@sephiroth 答案是go的好方法。
您可以使用直接指向結構開頭的指針,而無需使用支持緩沖區:
uint32_t *p = (uint32_t*)&localStruct;
這有兩個問題:
第一個是如果編譯器在結構上進行填充,你可能會得到意想不到的結果; 您可以通過向結構添加 (packed) 屬性來告訴編譯器不要做任何填充來解決這個問題
struct __attribute__((__packed__)) caldata_tag {
//...
}
另一個問題是您的結構大小不是 32 的倍數,因此如果在最后一個元素的末尾沒有 16 個隨機位,就無法在 uint32_t 數組中表示它。 您的示例也是如此,bur 我認為在這種情況下您將丟棄buffer
的最后一個元素,因為U32BUFFERSIZE
應該等於 2,因此您在計算 crc 時忽略K_P_Coolg
及其旁邊的 16 個隨機位。
在使用 crc 和類似的東西時,我的建議是使用 8 位緩沖區而不是 32 位緩沖區,因為它完全消除了后一個問題。
不需要解決方法。 According to the documentation for the function HAL_CRC_Calculate: "By default, the API expects a uint32_t pointer as input buffer parameter. Input buffer pointers with other types simply need to be cast in uint32_t and the API will internally adjust its input data processing based on the處理字段 hcrc->InputDataFormat。”
因此在第一個參數中正確設置該字段,您可以將指向字節的指針傳遞給 function。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.