▼點(diǎn)擊下方名片,關(guān)注公眾號(hào),獲取更多精彩內(nèi)容▼

歡迎關(guān)注【玩轉(zhuǎn)單片機(jī)與嵌入式】公眾號(hào),回復(fù)關(guān)鍵字獲取更多免費(fèi)視頻和資料
回復(fù)【加群】,【單片機(jī)】、【STM32】、【硬件知識(shí)】、【硬件設(shè)計(jì)】、【經(jīng)典電路】、【論文】、【畢業(yè)設(shè)計(jì)】、【3D封裝庫】、【PCB】、【電容】、【TVS】、【阻抗匹配】、【資料】、【終端電阻】、【Keil】、【485】、【CAN】、【振蕩器】、[USBCAN]、【PCB】、【智能手環(huán)】、【智能家居】、【智能小車】、【555】、【I2C】、【華為】、【中興】,等……

引言


結(jié)構(gòu)體對齊原理

3、結(jié)構(gòu)體對齊示例
// 結(jié)構(gòu)體定義struct Example {char a;int b;char c;};int main() {struct Example e;// 計(jì)算各成員的地址printf("Address of a: %p\n", &e.a);printf("Address of b: %p\n", &e.b);printf("Address of c: %p\n", &e.c);return 0;}
在這個(gè)示例中,我們定義了一個(gè)名為Example的結(jié)構(gòu)體,包含一個(gè)字符a、一個(gè)整數(shù)b和一個(gè)字符c。通過printf語句,我們可以查看不同對齊方式下各成員的地址。該結(jié)構(gòu)體在內(nèi)存中存儲(chǔ)的方式如下:

喜歡的讀者可以自行打印確定printf的輸出結(jié)果,觀察不同的地址有何規(guī)律。
4、結(jié)構(gòu)體對齊的影響
struct Example1 {char a;int b;char c;};struct Example2 {char a;char b;char c;};
在示例1中,int類型需要四字節(jié)對齊,因此struct Example1的大小為4字節(jié)。而在示例2中,所有成員都是字符類型,無需對齊,因此struct Example2的大小為3字節(jié)。這突顯了對齊規(guī)則如何影響內(nèi)存占用。
#include#include// 結(jié)構(gòu)體定義struct SensorData {uint16_t sensor1;uint32_t sensor2;} __attribute__((packed)); // 使用編譯器指令取消結(jié)構(gòu)體對齊int main() {struct SensorData data;data.sensor1 = 0x1234;data.sensor2 = 0x56789ABC;// 數(shù)據(jù)存儲(chǔ)到內(nèi)存中uint8_t buffer[sizeof(struct SensorData)];memcpy(buffer, &data, sizeof(struct SensorData));// 模擬傳輸過程// 接收端假設(shè)數(shù)據(jù)是按照雙字節(jié)對齊方式接收struct SensorData* receivedData = (struct SensorData*)buffer;printf("Received sensor1: 0x%04X\n", receivedData->sensor1);printf("Received sensor2: 0x%08X\n", receivedData->sensor2);return 0;}
在這個(gè)示例中,我們定義了一個(gè)SensorData結(jié)構(gòu)體,包含一個(gè)16位整數(shù)和一個(gè)32位整數(shù)。使用__attribute__((packed))編譯器指令取消了結(jié)構(gòu)體對齊,以確保數(shù)據(jù)在內(nèi)存中是連續(xù)存儲(chǔ)的。然后,我們將數(shù)據(jù)存儲(chǔ)到內(nèi)存中,并模擬了傳輸過程。接收端假設(shè)數(shù)據(jù)是按照雙字節(jié)對齊方式接收,但由于我們?nèi)∠藢R,需要進(jìn)行字節(jié)序轉(zhuǎn)換。

結(jié)構(gòu)體對齊在STM32中的體現(xiàn)

1、外設(shè)寄存器對齊要求
在STM32這樣的嵌入式系統(tǒng)中,外設(shè)寄存器通常要求雙字節(jié)或四字節(jié)對齊,以確保寄存器的訪問性能和正確性。不滿足對齊要求可能導(dǎo)致未定義的行為或性能問題。
在STM32中,可以使用編譯器指令來實(shí)現(xiàn)對齊設(shè)置。例如,在Keil工程中,可以使用__align()指令來指定對齊方式。例如,要將一個(gè)結(jié)構(gòu)體成員對齊到4字節(jié)邊界,可以這樣定義:
struct Example {char a;int b;char c;} __attribute__((aligned(4)));
2、內(nèi)存池分配
在嵌入式系統(tǒng)中,經(jīng)常使用內(nèi)存池來分配內(nèi)存。內(nèi)存池分配會(huì)確保分配的內(nèi)存塊是按照對齊要求進(jìn)行的,以滿足處理器的要求。這可以防止未對齊內(nèi)存訪問,提高代碼的穩(wěn)定性和可靠性。
在STM32中,常用的內(nèi)存池分配庫如FreeRTOS提供了對齊設(shè)置的選項(xiàng),以確保分配的內(nèi)存塊滿足處理器的要求。
3、DMA操作
嵌入式系統(tǒng)中常常使用DMA(直接內(nèi)存訪問)來進(jìn)行數(shù)據(jù)傳輸。DMA操作通常要求數(shù)據(jù)緩沖區(qū)是雙字節(jié)或四字節(jié)對齊的。不滿足對齊要求可能導(dǎo)致DMA傳輸失敗或性能下降。
在STM32中,配置DMA時(shí)可以使用寄存器來設(shè)置數(shù)據(jù)對齊方式,以確保DMA傳輸?shù)恼_性和性能。

結(jié)論

作為嵌入式工程師的我們。在編寫代碼時(shí),程序員需要根據(jù)目標(biāo)硬件平臺(tái)的對齊要求。
在本公眾號(hào)內(nèi)回復(fù)【STM32】可以獲取更多關(guān)于STM32的視頻教程和學(xué)習(xí)資料。
END


掃描上方二維碼加群,回復(fù)【加群】或掃碼加我好友,限時(shí)免費(fèi)進(jìn)入技術(shù)交流群。

推薦閱讀
【專輯】器件選型
【專輯】單片機(jī)
【專輯】經(jīng)驗(yàn)分享
【專輯】STM32
【專輯】硬件設(shè)計(jì)
【專輯】軟件設(shè)計(jì)
【專輯】開源項(xiàng)目
【專輯】職業(yè)發(fā)展
感謝大家閱讀,如果喜歡
請點(diǎn)贊和“在看”吧,或者分享到朋友圈。
點(diǎn)擊跳轉(zhuǎn)到原文,限時(shí)優(yōu)惠加入我們的知識(shí)星球(加好友獲取免費(fèi)券)