當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]關(guān)于結(jié)構(gòu)體對(duì)齊的設(shè)置,以GCC 32bit編譯為例,我們可以來(lái)看看下面這個(gè)例子: #include? ? //默認(rèn)情況下,結(jié)構(gòu)體一般在內(nèi)存中的自動(dòng)對(duì)齊格式是4個(gè)字節(jié)? ? //結(jié)構(gòu)體設(shè)置手動(dòng)對(duì)齊? //如果這里是4,那么下面的打印就是8????? //如果這里是2,那么下面的打

關(guān)于結(jié)構(gòu)體對(duì)齊的設(shè)置,以GCC 32bit編譯為例,我們可以來(lái)看看下面這個(gè)例子:

#include <stdio.h>
 
//默認(rèn)情況下,結(jié)構(gòu)體一般在內(nèi)存中的自動(dòng)對(duì)齊格式是4個(gè)字節(jié) 
 
//結(jié)構(gòu)體設(shè)置手動(dòng)對(duì)齊 
//如果這里是4,那么下面的打印就是8     
//如果這里是2,那么下面的打印就是6    
//如果這里是1,那么下面的打印就是5 
struct mystu
{
     char a ; 
     int  b ;
};


#pragma pack(4)
struct mystu0
{
     char a ; 
     int  b ;
};
#pragma pack()
 
#pragma pack(2)
struct mystu1
{
     char a ; 
     int  b ;
};
#pragma pack()

#pragma pack(1)
struct mystu2
{
     char a ; 
     int  b ;
};
#pragma pack() 
 
int main(void)
{
     printf("mystu:%d\n",sizeof(struct mystu));
     printf("mystu0:%d\n",sizeof(struct mystu0));
     printf("mystu1:%d\n",sizeof(struct mystu1));
     printf("mystu2:%d\n",sizeof(struct mystu2));
     return 0 ;
}

運(yùn)行結(jié)果:

根據(jù)這樣的原理,在MCU協(xié)議數(shù)據(jù)解析的時(shí)候就很有作用了,比如下面這個(gè)例子,目前在小車(chē)上用:

//結(jié)構(gòu)體,用于存儲(chǔ)解析的數(shù)據(jù)
typedef struct
{
 //幀頭(固定解析為FF)
    uint8_t frame_top ;   
 //版本 A1
    uint8_t version ;
 //方向 01(前進(jìn)) 02(后退) 03(左轉(zhuǎn)) 04(右轉(zhuǎn))
    uint8_t car_direction ;
 //速度 01(低速檔) 02(中速檔) 03(高速檔)
    uint8_t car_speed ;
 //炮臺(tái) 00(回到中間) 01(炮臺(tái)左轉(zhuǎn)) 02(炮臺(tái)右轉(zhuǎn))
    uint8_t car_fort_status ;
 //夾具 00(夾具夾緊) 01(夾具松開(kāi))
 uint8_t car_Fix_status ;
 //幀尾(固定解析為BB)
    uint8_t frame_tail ;
} Protocol;


//以下是串口回調(diào)的處理
/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
    /* USER CODE BEGIN USART1_IRQn 0 */
    /*自定義協(xié)議*/
    /*
     幀頭 版本 方向 速度 炮臺(tái) 夾具 幀尾
     ff   A1
    */
    uint8_t Res;

    if((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET))
    {
        HAL_UART_Receive(&huart1, &Res, 1, 1000);

        if(0xBB != Res)
        {
            rbBuf[rx_count++] = Res ;
        }
        else
        {
            rbBuf[rx_count] = 0xBB ;
            //接收到0xBB了,這時(shí)候認(rèn)為已經(jīng)接收到完整的一幀數(shù)據(jù),將接收標(biāo)志置1
            Recv_Flag = 1 ;
        }

        /* USER CODE END USART1_IRQn 0 */
        HAL_UART_IRQHandler(&huart1);
        /* USER CODE BEGIN USART1_IRQn 1 */

        /* USER CODE END USART1_IRQn 1 */
    }

    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */
}
//在主函數(shù)中,進(jìn)行數(shù)據(jù)解析
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    while (1)
    {
        if(1 == Recv_Flag)
        {
            Recv_Flag = 0 ;
            //將接收緩沖區(qū)的數(shù)組強(qiáng)制轉(zhuǎn)換為一個(gè)結(jié)構(gòu)體指針
            //通過(guò)結(jié)構(gòu)體指針可訪問(wèn)到每一個(gè)協(xié)議規(guī)格的數(shù)據(jù)
            Protocol *Car_Procol = (Protocol *)rbBuf;
            printf("幀頭:0x%x\n", Car_Procol->frame_top);
            printf("版本:0x%x\n", Car_Procol->version);
            printf("方向:0x%x\n", Car_Procol->car_direction);
            printf("速度:0x%x\n", Car_Procol->car_speed);
            printf("炮臺(tái):0x%x\n", Car_Procol->car_fort_status);
            printf("夾具:0x%x\n", Car_Procol->car_Fix_status);
            printf("幀尾:0x%x\n", Car_Procol->frame_tail);
            rx_count = 0 ;
        }
    }
}

從這里可以看到,串口接收的數(shù)據(jù)是一個(gè)字節(jié)一個(gè)字節(jié)進(jìn)行接收,所以接收的每個(gè)數(shù)據(jù)類(lèi)型一致,我們就可以直接定義一個(gè)結(jié)構(gòu)體,按照協(xié)議定義的順序,將數(shù)據(jù)緩沖區(qū)中的數(shù)據(jù)依次讀取出來(lái)。

在小熊派上的運(yùn)行結(jié)果:

我在寫(xiě)上位機(jī)涉及到與MCU進(jìn)行協(xié)議通信的時(shí)候,經(jīng)常都是這么干的,這個(gè)方法不得不說(shuō)真的超方便。

案例下載

公眾號(hào)后臺(tái)回復(fù):protocol 即可獲取本節(jié)案例的下載鏈接。

往期精彩

【為宏正名】本應(yīng)寫(xiě)入教科書(shū)的“世界設(shè)定”

【為宏正名】99%人都不知道的"##"里用法

學(xué)習(xí)嵌入式可以帶娃,不信你們看

ESP8266實(shí)戰(zhàn)貼:使用HTTP POST請(qǐng)求上傳數(shù)據(jù)到公有云OneNet

覺(jué)得本次分享的文章對(duì)您有幫助,隨手點(diǎn)[在看]并轉(zhuǎn)發(fā)分享,也是對(duì)我的支持。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉