欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6731|回復(fù): 12
收起左側(cè)

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

  [復(fù)制鏈接]
ID:446156 發(fā)表于 2021-11-15 13:29 | 顯示全部樓層 |閱讀模式
開(kāi)始本篇之前我想先談一下為什么要把一個(gè)ModBus主機(jī)分成4篇來(lái)寫(xiě),一是代碼的分層理念,隨著工作時(shí)間的增長(zhǎng)以及工作的深入你會(huì)發(fā)現(xiàn)分層是那么的至關(guān)重要不僅僅是代碼的可讀性更重要的是更方便的維護(hù)。初期寫(xiě)代碼一個(gè)文件中甚至一個(gè)函數(shù)中既有功能代碼又有底層代碼,當(dāng)增刪功能或者平臺(tái)移植的時(shí)候都不知道去哪里哭,分層也許在初期會(huì)增加代碼量顯得很麻煩但是當(dāng)你的架構(gòu)建立起來(lái)之后會(huì)變得十分方便,解決問(wèn)題得心應(yīng)手。操作系統(tǒng)幫你做好了底層的分層和軟件層面的任務(wù)調(diào)度,但是應(yīng)用層面依然需要個(gè)人來(lái)做好。分層理念需要時(shí)時(shí)有處處有。二是ModBus的一對(duì)多特性,當(dāng)一個(gè)主機(jī)任務(wù)讀取某個(gè)從機(jī)的數(shù)據(jù)并等待從機(jī)應(yīng)答時(shí),必須保證別的主機(jī)任務(wù)不要來(lái)動(dòng)ModBus總線,如果有個(gè)不長(zhǎng)眼的主機(jī)任務(wù)過(guò)來(lái)咔咔操作了總線那么之前等待從機(jī)應(yīng)答的任務(wù)就崩潰了。可能有人說(shuō)了等待應(yīng)答的時(shí)候我直接while死等不就行了,直接斷了別的主機(jī)任務(wù)的念想,當(dāng)然這樣是可以解決問(wèn)題的不過(guò)要是某個(gè)從機(jī)不在線就會(huì)導(dǎo)致整個(gè)系統(tǒng)卡死一段時(shí)間,要是你用了操作系統(tǒng)還好如果是裸機(jī)那就非常影響用戶體驗(yàn)并且會(huì)使其他任務(wù)比如刷屏按鍵出現(xiàn)一些莫名其妙的問(wèn)題,我們都知道人的新陳代謝越快身體越強(qiáng)壯,同樣任務(wù)輪詢?cè)娇煜到y(tǒng)也越強(qiáng)壯。無(wú)論你使用操作系統(tǒng)還是裸機(jī)都要避免使用阻塞式的寫(xiě)法。所以我們才大費(fèi)周章分4層來(lái)解決一個(gè)ModBus主機(jī)問(wèn)題。本篇調(diào)度篇內(nèi)容很少但是整個(gè)ModBus主機(jī)系統(tǒng)的重中之重。
我們先來(lái)看代碼。
  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ù)制代碼
通過(guò)代碼可以看到該層引用了任務(wù)篇?jiǎng)?chuàng)建的"THP.h"和"EPC.h",在這里我們要對(duì)三個(gè)主機(jī)任務(wù)進(jìn)行調(diào)度。
首先來(lái)看函數(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ù)使能信號(hào)(uint8_t En)、任務(wù)主體(uint8_t (Task)(void))、設(shè)備名稱(void *Dev)、是誰(shuí)在使用總線(uint8_t *BusTake)、任務(wù)編號(hào)(uint8_t TaskID)、總線靜默時(shí)間控制(uint16_t *DelayTime);
該函數(shù)邏輯很簡(jiǎn)單,就是判斷任務(wù)使能信號(hào)是否置位了并查看總線被哪個(gè)任務(wù)占用,若總線空閑或者被自己占用就去占用總線去執(zhí)行任務(wù)主體函數(shù),若任務(wù)主體函數(shù)返回0說(shuō)明正在等待從機(jī)應(yīng)答接著占用總線并返回1告知調(diào)度器我還沒(méi)用完,否則說(shuō)明任務(wù)完成了釋放總線并給總線插入10ms的靜默時(shí)間然后返回0告訴調(diào)度器我完事了讓別人來(lái)吧。
函數(shù)“void RS485Device1Handle(void)”就是最終的調(diào)度器它在main函數(shù)的while循環(huán)中被執(zhí)行,它首先實(shí)現(xiàn)10ms的總線靜默然后挨個(gè)詢問(wèn)主機(jī)任務(wù)的當(dāng)前狀態(tài)并滿足他們的需求。
至此,我的ModBus主機(jī)就完結(jié)了。



回復(fù)

使用道具 舉報(bào)

ID:939553 發(fā)表于 2021-11-20 09:49 | 顯示全部樓層
謝謝分享,能否提供一些關(guān)于分層的思想的文章,學(xué)習(xí)。
回復(fù)

使用道具 舉報(bào)

ID:1005484 發(fā)表于 2022-2-16 21:05 | 顯示全部樓層

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

使用道具 舉報(bào)

ID:97078 發(fā)表于 2022-3-9 08:33 | 顯示全部樓層
mark,標(biāo)記學(xué)習(xí)下
回復(fù)

使用道具 舉報(bào)

ID:1012071 發(fā)表于 2022-3-21 22:25 | 顯示全部樓層
mark,標(biāo)記學(xué)習(xí)下
回復(fù)

使用道具 舉報(bào)

ID:195496 發(fā)表于 2022-5-7 14:38 | 顯示全部樓層
上的操作系統(tǒng)?
回復(fù)

使用道具 舉報(bào)

ID:434978 發(fā)表于 2022-5-20 12:10 | 顯示全部樓層
謝謝分享,能否提供一些關(guān)于分層的思想的文章,學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

ID:1056996 發(fā)表于 2022-12-11 15:36 | 顯示全部樓層
mark,標(biāo)記學(xué)習(xí)下
回復(fù)

使用道具 舉報(bào)

ID:821429 發(fā)表于 2023-4-16 09:43 | 顯示全部樓層
,標(biāo)記學(xué)習(xí)一下,感謝分享
回復(fù)

使用道具 舉報(bào)

ID:27536 發(fā)表于 2023-5-12 16:42 | 顯示全部樓層

mark,標(biāo)記學(xué)習(xí)下
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

ID:939553 發(fā)表于 2023-8-15 14:34 來(lái)自觸屏版 | 顯示全部樓層
思路清晰,程序扎實(shí)
回復(fù)

使用道具 舉報(bào)

ID:446156 發(fā)表于 2024-10-30 16:59 | 顯示全部樓層
大漠落日 發(fā)表于 2022-5-7 14:38
上的操作系統(tǒng)?

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

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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