找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6583|回復(fù): 12
打印 上一主題 下一主題
收起左側(cè)

我的ModBus主機-調(diào)度篇

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
#
ID:446156 發(fā)表于 2021-11-15 13:29 | 只看該作者 回帖獎勵 |正序瀏覽 |閱讀模式
開始本篇之前我想先談一下為什么要把一個ModBus主機分成4篇來寫,一是代碼的分層理念,隨著工作時間的增長以及工作的深入你會發(fā)現(xiàn)分層是那么的至關(guān)重要不僅僅是代碼的可讀性更重要的是更方便的維護。初期寫代碼一個文件中甚至一個函數(shù)中既有功能代碼又有底層代碼,當增刪功能或者平臺移植的時候都不知道去哪里哭,分層也許在初期會增加代碼量顯得很麻煩但是當你的架構(gòu)建立起來之后會變得十分方便,解決問題得心應(yīng)手。操作系統(tǒng)幫你做好了底層的分層和軟件層面的任務(wù)調(diào)度,但是應(yīng)用層面依然需要個人來做好。分層理念需要時時有處處有。二是ModBus的一對多特性,當一個主機任務(wù)讀取某個從機的數(shù)據(jù)并等待從機應(yīng)答時,必須保證別的主機任務(wù)不要來動ModBus總線,如果有個不長眼的主機任務(wù)過來咔咔操作了總線那么之前等待從機應(yīng)答的任務(wù)就崩潰了?赡苡腥苏f了等待應(yīng)答的時候我直接while死等不就行了,直接斷了別的主機任務(wù)的念想,當然這樣是可以解決問題的不過要是某個從機不在線就會導致整個系統(tǒng)卡死一段時間,要是你用了操作系統(tǒng)還好如果是裸機那就非常影響用戶體驗并且會使其他任務(wù)比如刷屏按鍵出現(xiàn)一些莫名其妙的問題,我們都知道人的新陳代謝越快身體越強壯,同樣任務(wù)輪詢越快系統(tǒng)也越強壯。無論你使用操作系統(tǒng)還是裸機都要避免使用阻塞式的寫法。所以我們才大費周章分4層來解決一個ModBus主機問題。本篇調(diào)度篇內(nèi)容很少但是整個ModBus主機系統(tǒng)的重中之重。
我們先來看代碼。
  1. #ifndef __RS485_H
  2. #define __RS485_H

  3. #include "Header.h"
  4. #include "THP.h"
  5. #include "EPC.h"
  6. #include "Delay.h"

  7. extern uint16_t RS485BusSilentTime1;

  8. void RS485Device1Init(void);
  9. void RS485Device1Handle(void);

  10. #endif
復(fù)制代碼
  1. #include "RS485Device.h"

  2. uint16_t RS485BusSilentTime1;

  3. void RS485Device1Init(void)
  4. {
  5.         THPInit();
  6.         EPCInit();
  7. }

  8. static uint8_t TaskHandle(uint8_t En, uint8_t (*Task)(void*), void *Dev, uint8_t *BusTake, uint8_t TaskID, uint16_t *DelayTime)
  9. {
  10.         if((En!=0) && ((*BusTake==0)||(*BusTake==TaskID)))
  11.         {
  12.                 if(Task(Dev) != 0)
  13.                 {
  14.                         /*釋放總線*/
  15.                         *BusTake = 0;
  16.                         Set_Delay_Time(10,DelayTime);
  17.                 }
  18.                 else
  19.                 {
  20.                         /*占用總線*/
  21.                         *BusTake = TaskID;
  22.                         return 1;
  23.                 }
  24.         }
  25.         return 0;
  26. }
  27. void RS485Device1Handle(void)
  28. {
  29.         static uint8_t BusTake=0;
  30.        
  31.         if(CheckDelay(&RS485BusSilentTime1) == 0)
  32.         {
  33.                 if(TaskHandle(EPC1.S_P_En,SetPreVal,&EPC1,&BusTake,1,&RS485BusSilentTime1) != 0)
  34.                 {
  35.                         return;
  36.                 }
  37.                 if(TaskHandle(THP1.Enable,ReadTHP,&THP1,&BusTake,2,&RS485BusSilentTime1) != 0)
  38.                 {
  39.                         return;
  40.                 }
  41.                 if(TaskHandle(EPC1.R_En,ReadEPC,&EPC1,&BusTake,3,&RS485BusSilentTime1) != 0)
  42.                 {
  43.                         return;
  44.                 }
  45.         }
  46. }
復(fù)制代碼
通過代碼可以看到該層引用了任務(wù)篇創(chuàng)建的"THP.h"和"EPC.h",在這里我們要對三個主機任務(wù)進行調(diào)度。
首先來看函數(shù)“static uint8_t TaskHandle(uint8_t En, uint8_t (Task)(void), void *Dev, uint8_t *BusTake, uint8_t TaskID, uint16_t *DelayTime)”;
該函數(shù)參數(shù)比較多,分別為任務(wù)使能信號(uint8_t En)、任務(wù)主體(uint8_t (Task)(void))、設(shè)備名稱(void *Dev)、是誰在使用總線(uint8_t *BusTake)、任務(wù)編號(uint8_t TaskID)、總線靜默時間控制(uint16_t *DelayTime);
該函數(shù)邏輯很簡單,就是判斷任務(wù)使能信號是否置位了并查看總線被哪個任務(wù)占用,若總線空閑或者被自己占用就去占用總線去執(zhí)行任務(wù)主體函數(shù),若任務(wù)主體函數(shù)返回0說明正在等待從機應(yīng)答接著占用總線并返回1告知調(diào)度器我還沒用完,否則說明任務(wù)完成了釋放總線并給總線插入10ms的靜默時間然后返回0告訴調(diào)度器我完事了讓別人來吧。
函數(shù)“void RS485Device1Handle(void)”就是最終的調(diào)度器它在main函數(shù)的while循環(huán)中被執(zhí)行,它首先實現(xiàn)10ms的總線靜默然后挨個詢問主機任務(wù)的當前狀態(tài)并滿足他們的需求。
至此,我的ModBus主機就完結(jié)了。



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏14 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報

12#
ID:446156 發(fā)表于 2024-10-30 16:59 | 只看該作者
大漠落日 發(fā)表于 2022-5-7 14:38
上的操作系統(tǒng)?

裸機,我自己的框架
回復(fù)

使用道具 舉報

11#
ID:939553 發(fā)表于 2023-8-15 14:34 來自手機 | 只看該作者
思路清晰,程序扎實
回復(fù)

使用道具 舉報

10#
ID:1045571 發(fā)表于 2023-8-6 14:58 | 只看該作者
moubus在工作中我遇到了,也看了大概的基本原理,但程序?qū)懖怀鰜,借鑒一下樓主的
回復(fù)

使用道具 舉報

9#
ID:27536 發(fā)表于 2023-5-12 16:42 | 只看該作者

mark,標記學習下
回復(fù)

使用道具 舉報

8#
ID:821429 發(fā)表于 2023-4-16 09:43 | 只看該作者
,標記學習一下,感謝分享
回復(fù)

使用道具 舉報

7#
ID:1056996 發(fā)表于 2022-12-11 15:36 | 只看該作者
mark,標記學習下
回復(fù)

使用道具 舉報

6#
ID:434978 發(fā)表于 2022-5-20 12:10 | 只看該作者
謝謝分享,能否提供一些關(guān)于分層的思想的文章,學習
回復(fù)

使用道具 舉報

5#
ID:195496 發(fā)表于 2022-5-7 14:38 | 只看該作者
上的操作系統(tǒng)?
回復(fù)

使用道具 舉報

地板
ID:1012071 發(fā)表于 2022-3-21 22:25 | 只看該作者
mark,標記學習下
回復(fù)

使用道具 舉報

板凳
ID:97078 發(fā)表于 2022-3-9 08:33 | 只看該作者
mark,標記學習下
回復(fù)

使用道具 舉報

沙發(fā)
ID:1005484 發(fā)表于 2022-2-16 21:05 | 只看該作者

謝謝分享,能否提供一些關(guān)于分層的思想的文章,學習。
回復(fù)

使用道具 舉報

樓主
ID:939553 發(fā)表于 2021-11-20 09:49 | 只看該作者
謝謝分享,能否提供一些關(guān)于分層的思想的文章,學習。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表