在STM32 HAL庫開發中,我們經常會看到__weak這個關鍵字,到底是什么意思呢?出于這個好奇心我們來打開KEIL的幫助手冊找到它的出處:
意思就是,它是一個弱符號,可以用于修飾變數和函式;不過我們經常看到的是對函式的修飾,所以這里我們僅討論下函式的修飾就可以了,也就是說,當一個函式前面加上__weak這樣的修飾符以后,允許用戶在其它檔案中定義一個和__weak修飾過的一模一樣的函式,最終當編譯器編譯的時候,會選擇用戶定義的函式,如果用戶沒有重新實作這個函式,則編譯器就會去執行帶__weak修飾的函式,
所以在HAL庫里,比如我們經常會看到像下面這樣的函式:
__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
}
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
}
....等等....
通常HAL庫原始碼里帶__weak這個弱函式很多內部都沒有實作,它把主動權讓給用戶自己根據自己的需要去定義一個一模一樣的函式,然后去做自己想做的事情,這里的UNUSED起到一個防止編譯器報警告的作用,原型如下:
#define UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
這樣就非常好了,我們可以用這樣的機制輕松實作程式模塊的相互獨立,如何來實作呢?我把我最近做的專案做一個分享,我完成的是一個金屬檢測傳感器的模塊框架,為了未來能夠不費吹灰之力移植到別的STM32的平臺,我是這么來做的:
Metal.h
#define UNUSED_METAL(X) (void)X
/*金屬傳感器資料采集結構體*/
typedef struct
{
int Serial_Number ; /*流水號*/
uint16_t Heating_Value ; /*加熱值*/
uint16_t Heating_Signal_Value ; /*信號值*/
uint16_t Devalue ; /*差值*/
} Metal_Sensor ;
extern Metal_Sensor Metal_Sensor_Device ;
extern Metal_Sensor Meatl_Sensor_Parse ;
/*注冊金屬傳感器*/
void Register_Metal_Sensor(void);
/*獲取并決議傳感器資料*/
void Get_Metal_Sensor_Data(char *data, Metal_Sensor *sensor_data);
Metal.c
/*決議金屬資料格式結構體*/
typedef struct
{
int Para1 ;
int Para2 ;
int Para3 ;
int Para4 ;
} Parse_Metal_Passage_Value ;
Metal_Sensor Meatl_Sensor_Parse ;
Metal_Sensor Metal_Sensor_Device ;
__weak void __Register_Metal_Sensor(void);
__weak void CallBack_Metal_Logic(Metal_Sensor *sensor_data);
/*決議傳感器資料*/
void Split_Sensor_Metal_Data(char *Data, Parse_Metal_Passage_Value *Sensor_Data_Info)
{
char *temp = NULL ;
Sensor_Data_Info->Para1 = atoi(Data);
temp = strstr(Data, " ");
Sensor_Data_Info->Para2 = atoi(temp + 1);
temp = strstr(temp + 1, " ");
Sensor_Data_Info->Para3 = atoi(temp + 1);
temp = strstr(temp + 1, " ");
Sensor_Data_Info->Para4 = atoi(temp + 1);
temp = strstr(temp + 1, " ");
}
/*金屬傳感器注冊*/
void Register_Metal_Sensor(void)
{
__Register_Metal_Sensor();
}
void Get_Metal_Sensor_Data(char *data, Metal_Sensor *sensor_data)
{
Parse_Metal_Passage_Value para_0 ;
Split_Sensor_Metal_Data(data, ¶_0);
sensor_data->Serial_Number = para_0.Para1 ;
sensor_data->Heating_Value = para_0.Para2 ;
sensor_data->Devalue = para_0.Para3 ;
sensor_data->Heating_Signal_Value = para_0.Para4 ;
CallBack_Metal_Logic(sensor_data);
}
__weak void __Register_Metal_Sensor(void)
{
UNUSED_METAL(NULL);
}
__weak void CallBack_Metal_Logic(Metal_Sensor *sensor_data)
{
UNUSED_METAL(sensor_data);
}
這里提供給外面應用邏輯兩個介面,一個是用戶需要提供注冊金屬傳感器的邏輯,他只需要實作__Register_Metal_Sensor函式就可以完成金屬傳感器的注冊了;另一個是用戶拿到決議金屬傳感器的資料以后去做他自己要做的事情,那么他只需要實作CallBack_Metal_Logic這個函式就可以了,
然后在另一個metal_detect_app.c檔案中,直接實作這兩個與Metal.c中一模一樣的函式即可:
/*注冊金屬傳感器*/
void __Register_Metal_Sensor(void)
{
HAL_UART_DMAStop(&huart6);
memset(Metal_Sensor_Handler.SensorU6Buffer, 0, SENSOR_U6_BUFFER_SIZE);
HAL_UART_Receive_DMA(&huart6, (uint8_t*)Metal_Sensor_Handler.SensorU6Buffer, SENSOR_U6_BUFFER_SIZE);
//開啟空閑中斷
__HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
}
/*呼叫具體的應用邏輯*/
void CallBack_Metal_Logic(Metal_Sensor *sensor_data)
{
/*在不同的頁面執行不同的邏輯*/
switch(Flow_Cursor.flow_cursor)
{
case MAIN_PAGE:
//實作應用業務邏輯
break ;
case METAL_TEST_PAGE:
//實作應用業務邏輯
break ;
default:
break ;
}
/*重新開啟串口DMA接收*/
memset(Metal_Sensor_Handler.SensorU6Buffer, 0, SENSOR_U6_BUFFER_SIZE);
HAL_UART_Receive_DMA(&huart6, (uint8_t*)Metal_Sensor_Handler.SensorU6Buffer, SENSOR_U6_BUFFER_SIZE);
}
最后,在我的任務中做如下呼叫:
/* 金屬傳感器執行緒入口函式 */
static void metal_thread_entry(void *parameter)
{
static rt_err_t result;
/* 創建一個動態信號量,初始值是 0 */
metal_sem = rt_sem_create("mt_sem", 0, RT_IPC_FLAG_FIFO);
if (metal_sem == RT_NULL)
{
rt_kprintf("create mt_sem failed.\n");
return ;
}
/*注冊金屬傳感器*/
Register_Metal_Sensor();
while (1)
{
/*獲取金屬傳感器信號量*/
result = rt_sem_take(metal_sem, RT_WAITING_FOREVER);
if (RT_EOK == result)
Get_Metal_Sensor_Data((char *)Metal_Sensor_Handler.SensorU6Buffer, &Meatl_Sensor_Parse);
}
}
這樣,就輕松的實作了模塊的相互獨立了,
往期精彩
如何優雅地列印 HEX 資料?
讓傳感器資料更直觀之LCD曲線顯示
專案資源太緊張了,如何根據map資訊進行功能裁剪和優化?
整理了很久之前在碼云/Github/CSDN上收藏的嵌入式產品級專案分享開源
覺得本次分享的文章對您有幫助,隨手點[在看]并轉發分享,也是對我的支持,
CSDN認證博客專家
嵌入式硬體
單片機
arm開發
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/238009.html
標籤:AI
