送藥小車代碼倉庫:https://gitee.com/lcsc/medical_car
送藥小車數據的發布與訂閱
既然使用了RTOS,就不能像以前裸機一樣全局變量滿天飛了(當然裸機也不能全局變量滿天飛)。
在實時操作系統(RTOS)中,不推薦或不建議使用全局變量來傳遞信息的原因主要有以下幾點:
競爭條件:在多任務環境下,全局變量會面臨競爭條件的問題。當多個任務同時讀寫同一個全局變量時,會導致數據的不一致性和錯誤的結果。這是因為任務的執行是并發的,無法控制它們的執行順序。
數據共享和保護:全局變量被所有任務共享,這意味著多個任務可以同時訪問和修改該變量。如果沒有正確的數據保護機制,可能會導致數據損壞或沖突。
可維護性和調試困難:使用全局變量傳遞信息可能導致代碼的可維護性和調試的困難。由于全局變量可以被任何任務修改,追蹤問題的根源和調試錯誤可能會變得更加困難。
為了避免上述問題,RTOS提供了一些機制來進行任務間的通信和數據傳遞,例如:
消息隊列:任務可以通過消息隊列來發送和接收消息。每個任務有自己的私有消息隊列,通過發送和接收消息來進行通信,避免了全局變量的競爭條件和數據共享問題。
信號量:信號量可以用于同步任務的執行和共享資源的訪問。任務可以通過申請和釋放信號量來控制對共享資源的訪問,并確保任務之間的互斥性和同步性。
事件標志組:事件標志組可以用于任務之間的通知和事件觸發。一個任務可以等待一個或多個事件標志的狀態變化,并在事件發生時被喚醒執行相應的操作。
通過使用這些RTOS提供的通信機制,可以更安全地在任務之間傳遞信息,避免競爭條件和數據共享問題,并提高代碼的可維護性和調試效率。
在送藥小車這個工程中采用RT-Thread軟件包uMCN,uMCN (Micro Multi-Communication Node) 提供了一種基于發布/訂閱模式的安全跨線程/進程的通信方式。在系統中,uMCN 被廣泛應用于任務和模塊間的數據通信。使用發布-訂閱(Publish-Subscribe)機制可以提供更靈活和高效的任務間通信方式,支持一對一、一對多、多對一和多對多的通信模式。這種機制可以解決使用全局變量傳遞信息可能帶來的競爭條件和數據共享問題。
發布-訂閱機制基于事件驅動的思想,其中包含兩個角色:發布者(Publisher)和訂閱者(Subscriber)。發布者負責發布事件或消息,而訂閱者則注冊對感興趣的事件或消息進行訂閱。他提供了一種松散耦合的通信方式,允許任務或模塊之間通過發布和訂閱消息來進行通信,而不需要直接知道彼此的存在。
在使用發布-訂閱模式獲取數據時,通常涉及以下角色和操作:
發布者(Publisher):負責生成和發布數據或事件。發布者將數據發送到一個或多個特定的主題(Topic),而不關心具體的訂閱者。
訂閱者(Subscriber):訂閱者對特定的主題感興趣,并通過訂閱該主題來接收與之相關的數據或事件。
主題(Topic):主題是數據或事件的分類或標識符,發布者根據主題將數據發送到相應的通道,而訂閱者根據主題來選擇訂閱的數據源。
使用發布-訂閱模式獲取數據的好處在于,系統中的任務或模塊之間解耦合,發布者和訂閱者之間不直接依賴于彼此的存在,從而提高了系統的可擴展性和靈活性。此外,發布-訂閱模式還能夠支持多對多的通信,允許多個訂閱者同時接收相同的數據或事件,實現了信息的分發和共享。
他的優勢如下:
松耦合性:發布-訂閱機制使任務之間的通信更加松耦合。發布者不需要直接知道訂閱者的存在,也不需要關心具體的訂閱者數量和位置。訂閱者只需要訂閱感興趣的事件或消息,從而實現任務之間的解耦。
靈活性:發布-訂閱機制支持多對多的通信模式,一個發布者可以有多個訂閱者,一個訂閱者也可以訂閱多個發布者的事件或消息。這種靈活性使得任務之間可以方便地建立復雜的通信關系。
擴展性:通過發布-訂閱機制,可以方便地擴展系統,添加新的發布者或訂閱者,而不需要修改現有的任務邏輯。這種擴展性使得系統更具可維護性和可擴展性。
將各個數據發布,并對接上echo輸出函數后,就可以在RT-Thread的Finsh控制臺獲取到數據信息了(下面是通過uMCN獲取電機編碼器1的數據):
具體使用參考uMCN的倉庫:
添加新主題
為了添加新的主題 (topic),你需要先創建一個主題內容。例如:
typedef struct {
rt_uint32_t a;
float b;
int8_t c[4];
} data_content;
uMCN對主題內容的長度和類型沒有限制,所以理論上可以用來傳輸任何類型的消息。
然后你需要使用宏
MCN_DEFINE(name, size)
來定義主題。一般在發布主題的源文件的頂部定義主題。例如:
MCN_DEFINE(my_topic, sizeof(data_content));
uMCN 支持一個主題擁有多個發布者和訂閱者。注意同一個主題名字不同被重復定義,不然編譯器會報錯。
mcn_advertise(MCN_ID(my_topic), my_topic_echo);
MCN_ID()
宏根據主題名獲得樞紐節點。my_topic_echo
是一個回調函數,用來打印主題的數據。
static int my_topic_echo(void* param)
{
data_content data;
if(mcn_copy_from_hub((McnHub*)param, &data) == FMT_EOK){
printf("a:%d b:%f c:%c %c %c %cn", data.a, data.b, data.c[0], data.c[1], data.c[2], data.c[3]);
return 0;
}
return -1;
}
發布主題
可以在系統的任意位置使用函數
mcn_publish()
來發布一個主題。例如:
data_content my_data = {50, -2.0, {1,2,3,4}};
mcn_publish(MCN_ID(my_topic), &my_data);
審核編輯 黃宇
-
數據
+關注
關注
8文章
7085瀏覽量
89214 -
RTOS
+關注
關注
22文章
817瀏覽量
119725 -
開發板
+關注
關注
25文章
5082瀏覽量
97720
發布評論請先 登錄
相關推薦
評論