www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 電源 > 數(shù)字電源
[導讀]系統(tǒng)設置容量為8個任務,用戶實際可用任務為7個,能夠滿足一般需求,也達到了在小容量芯片中應用的開發(fā)要求。由于沒有采用占先式的任務調(diào)度,除開全程相關的個別任務的一些局部變量外,其他局部變量已經(jīng)不存在覆蓋關系,由于是任務主動放棄CPU控制權,對于個別需要保護的變量單獨進行處理也變得容易。在系統(tǒng)中,全程不需要反復地開關中斷,實時性能也很好。

目前,大多數(shù)的產(chǎn)品開發(fā)是在基于一些小容量的單片機上進行的。51系列單片機,是我國目前使用最多的單片機系列之一,有非常廣大的應用環(huán)境與前景,多年來的資源積累,使51系列單片機仍是許多開發(fā)者的首選。針對這種情況,近幾年涌現(xiàn)出許多基于51內(nèi)核的擴展芯片,功能越來越齊全,速度越來越快,也從一個側面說明了51系列單片機在國內(nèi)的生命力。

  多年來我們一直想找一個合適的實時操作系統(tǒng),作為自己的開發(fā)基礎。根據(jù)開發(fā)需求,整合一些常用的嵌入式構件,以節(jié)約開發(fā)時間,盡最大可能地減少開發(fā)工作量;另外,要求這個實時操作系統(tǒng)能非常容易地嵌入到小容量的芯片中。畢竟,大系統(tǒng)是少數(shù)的,而小應用是多數(shù)而廣泛的。顯而易見,μC/OS—II是不太適合于以上要求的,而Keil C所帶的RTX Tiny不帶源代碼,不具透明性,至于其FULL版本就更不用說了。

  1 Keil C51與重入問題

  說到實時操作系統(tǒng),就不能不考慮重入問題。對于PC機這樣的大內(nèi)存處理器而言,這似乎并不是一個很麻煩的問題,借用μC/OS—II RTOS的說法,即要求在重入的函數(shù)內(nèi),使用局部變量。但5l系列單片機堆??臻g很小,僅局限在256字節(jié)之內(nèi),無法為每個函數(shù)都分配一個局部堆空間。正是由于這個原因,Keil C51使用了所謂的可覆蓋技術:

  ①局部變量存儲在全局RAM空間(不考慮擴展外部存儲器的情況);

 ?、谠诰幾g鏈接時,即已經(jīng)完成局部變量的定位;

 ?、廴绻骱瘮?shù)之間沒有直接或間接的調(diào)用關系,則其局部變量空間便可覆蓋。

  正是由于以上的原因,在Keil C51環(huán)境下,純粹的函數(shù)如果不加處理(如增加一個模擬棧),是無法重人的。那么在Keil C5l環(huán)境下,如何使其函數(shù)具有可重人性呢?下面分析在實時操作系統(tǒng)下面,任務的基本結構與模式:

  vold TaskA(void*ptr){

  UINT8 vaL_a;

 ?。渌恍┳兞慷x

  do{

 ?。瘜嶋H的用戶任務處理代碼

  }while(1);

  }

  void TaskB(void*ptr){

  UINT8 vaLb;

 ?。渌恍┳兞慷x

  do{

  Funcl();

 ?。渌麑嶋H的用戶任務處理代碼

 ?。﹚hile(1);

  void Funcl(){

  UlNT8 v al_fa;

  //其他變量的定義

 ?。瘮?shù)的處理代碼

  }

  在上面的代碼中,TaskA與TaskB并不存在直接或間接的調(diào)用關系,因而其局部變量val_a與val_b便是可以被互相覆蓋的,即其可能都被定位于某一個相同的RAM空間。這樣,當TaskA運行一段時間,改變了val_a后,TaskB取得CPU控制權并運行時,便可能會改變val_b。由于其指向相同的RAM空間,導致TaskA重新取得CPU控制權時,val—a的值已經(jīng)改變,從而導致程序運行不正確,反過來亦然。另一方面,F(xiàn)uncl()與TaskB有直接的調(diào)用關系,因而其局部變量val_fa與val_b不會被互相覆蓋,但也不能保證其局部變量val_fa不會與TaskA或其他任務的局部變量形成可覆蓋關系。

  將val_a、val_b以及val_fa等局部變量定義為靜態(tài)變量(加上static指示符)可以解決這一問題。但問題是,定義大量的static類型變量,將導致RAM空間的大量占用,有可能直接導致RAM空間不夠用。尤其是在一些小容量的單片機內(nèi),一般只有128或256字節(jié),大量的靜態(tài)變量定義,在如此小的RAM資源狀況下顯然就不太合適了。由此而有了另一種的解決方法,如下代碼所示:

  void TaskC(void){

  UINT8 x,v;

  whlk(1){

  OS_ENTER_CRITICAL();

  x=GetX(); (1)

  y=GetY(); (2)

  //任務的其他代碼

  OS_EXIT_CRITICAL(); (3)

  0SSleep(100); (4)

  }

  }

  以上代碼TaskC中使用了臨界保護的方法來保護代碼不被中斷占先,確實有效地解決了RAM空間太小,不宜大量定義靜態(tài)變量的問題。然而如果每個任務都采用此種結構,任務一開始,就關閉中斷,將使實時性得不到保證。事實證明,這種延時是相當可觀的。用一個實例來說明,如果想在系統(tǒng)中使用一個動態(tài)刷新的LED顯示器,就難以保證顯示的穩(wěn)定與連續(xù),哪怕在系統(tǒng)中是使用一個單獨的定時器來做這一工作(進入臨界區(qū)后,EA=0)。其次,這種結構事實上將占先的任務調(diào)度轉化為非占先的任務調(diào)度。實際上如果在(3)與(4)之間沒有碰巧發(fā)生中斷并導致一個任務調(diào)度,那就可以理解為是任務主動放棄CPU的控制。如果在(3)和(4)之間碰巧產(chǎn)生了一個中斷并導致了一個任務調(diào)度,只是執(zhí)行了一次多余的任務調(diào)度而已,而且并不希望在(3)之后發(fā)生2次甚至多次的任務調(diào)度,相信讀者也有這一愿望。

  除此之外,還可以發(fā)現(xiàn)任務的一個特點:當任務從(1)重新開始時,局部變量x和y是一個什么值并不在乎,即x和y即使在(3)之后改變了,也已經(jīng)不再重要,不會影響程序的正確性。其實這一特點也是大部分任務,至少是太部分任務的大部分局部變量的一個共性——如果任務在整個執(zhí)行過程中,不會(被占先)放棄CPU控制權,則其局部變量大多數(shù)并不需要進行特別的保護,即其作用域只是任務的當次執(zhí)行,針對上面的代碼,就是臨界保護區(qū)內(nèi)的代碼區(qū)域。

  目前,大多數(shù)的產(chǎn)品開發(fā)是在基于一些小容量的單片機上進行的。51系列單片機,是我國目前使用最多的單片機系列之一,有非常廣大的應用環(huán)境與前景,多年來的資源積累,使51系列單片機仍是許多開發(fā)者的首選。針對這種情況,近幾年涌現(xiàn)出許多基于51內(nèi)核的擴展芯片,功能越來越齊全,速度越來越快,也從一個側面說明了51系列單片機在國內(nèi)的生命力。

  多年來我們一直想找一個合適的實時操作系統(tǒng),作為自己的開發(fā)基礎。根據(jù)開發(fā)需求,整合一些常用的嵌入式構件,以節(jié)約開發(fā)時間,盡最大可能地減少開發(fā)工作量;另外,要求這個實時操作系統(tǒng)能非常容易地嵌入到小容量的芯片中。畢竟,大系統(tǒng)是少數(shù)的,而小應用是多數(shù)而廣泛的。顯而易見,μC/OS—II是不太適合于以上要求的,而Keil C所帶的RTX Tiny不帶源代碼,不具透明性,至于其FULL版本就更不用說了。

  1 Keil C51與重入問題

  說到實時操作系統(tǒng),就不能不考慮重入問題。對于PC機這樣的大內(nèi)存處理器而言,這似乎并不是一個很麻煩的問題,借用μC/OS—II RTOS的說法,即要求在重入的函數(shù)內(nèi),使用局部變量。但5l系列單片機堆??臻g很小,僅局限在256字節(jié)之內(nèi),無法為每個函數(shù)都分配一個局部堆空間。正是由于這個原因,Keil C51使用了所謂的可覆蓋技術:

 ?、倬植孔兞看鎯υ谌諶AM空間(不考慮擴展外部存儲器的情況);

 ?、谠诰幾g鏈接時,即已經(jīng)完成局部變量的定位;

  ③如果各函數(shù)之間沒有直接或間接的調(diào)用關系,則其局部變量空間便可覆蓋。

  正是由于以上的原因,在Keil C51環(huán)境下,純粹的函數(shù)如果不加處理(如增加一個模擬棧),是無法重人的。那么在Keil C5l環(huán)境下,如何使其函數(shù)具有可重人性呢?下面分析在實時操作系統(tǒng)下面,任務的基本結構與模式:

  vold TaskA(void*ptr){

  UINT8 vaL_a;

 ?。渌恍┳兞慷x

  do{

 ?。瘜嶋H的用戶任務處理代碼

  }while(1);

  }

  void TaskB(void*ptr){

  UINT8 vaLb;

  //其他一些變量定義

  do{

  Funcl();

 ?。渌麑嶋H的用戶任務處理代碼

 ?。﹚hile(1);

  void Funcl(){

  UlNT8 v al_fa;

 ?。渌兞康亩x

  //函數(shù)的處理代碼

  }

  在上面的代碼中,TaskA與TaskB并不存在直接或間接的調(diào)用關系,因而其局部變量val_a與val_b便是可以被互相覆蓋的,即其可能都被定位于某一個相同的RAM空間。這樣,當TaskA運行一段時間,改變了val_a后,TaskB取得CPU控制權并運行時,便可能會改變val_b。由于其指向相同的RAM空間,導致TaskA重新取得CPU控制權時,val—a的值已經(jīng)改變,從而導致程序運行不正確,反過來亦然。另一方面,F(xiàn)uncl()與TaskB有直接的調(diào)用關系,因而其局部變量val_fa與val_b不會被互相覆蓋,但也不能保證其局部變量val_fa不會與TaskA或其他任務的局部變量形成可覆蓋關系。

  將val_a、val_b以及val_fa等局部變量定義為靜態(tài)變量(加上static指示符)可以解決這一問題。但問題是,定義大量的static類型變量,將導致RAM空間的大量占用,有可能直接導致RAM空間不夠用。尤其是在一些小容量的單片機內(nèi),一般只有128或256字節(jié),大量的靜態(tài)變量定義,在如此小的RAM資源狀況下顯然就不太合適了。由此而有了另一種的解決方法,如下代碼所示:

  void TaskC(void){

  UINT8 x,v;

  whlk(1){

  OS_ENTER_CRITICAL();

  x=GetX(); (1)

  y=GetY(); (2)

 ?。蝿盏钠渌a

  OS_EXIT_CRITICAL(); (3)

  0SSleep(100); (4)

  }

  }

  以上代碼TaskC中使用了臨界保護的方法來保護代碼不被中斷占先,確實有效地解決了RAM空間太小,不宜大量定義靜態(tài)變量的問題。然而如果每個任務都采用此種結構,任務一開始,就關閉中斷,將使實時性得不到保證。事實證明,這種延時是相當可觀的。用一個實例來說明,如果想在系統(tǒng)中使用一個動態(tài)刷新的LED顯示器,就難以保證顯示的穩(wěn)定與連續(xù),哪怕在系統(tǒng)中是使用一個單獨的定時器來做這一工作(進入臨界區(qū)后,EA=0)。其次,這種結構事實上將占先的任務調(diào)度轉化為非占先的任務調(diào)度。實際上如果在(3)與(4)之間沒有碰巧發(fā)生中斷并導致一個任務調(diào)度,那就可以理解為是任務主動放棄CPU的控制。如果在(3)和(4)之間碰巧產(chǎn)生了一個中斷并導致了一個任務調(diào)度,只是執(zhí)行了一次多余的任務調(diào)度而已,而且并不希望在(3)之后發(fā)生2次甚至多次的任務調(diào)度,相信讀者也有這一愿望。

  除此之外,還可以發(fā)現(xiàn)任務的一個特點:當任務從(1)重新開始時,局部變量x和y是一個什么值并不在乎,即x和y即使在(3)之后改變了,也已經(jīng)不再重要,不會影響程序的正確性。其實這一特點也是大部分任務,至少是太部分任務的大部分局部變量的一個共性——如果任務在整個執(zhí)行過程中,不會(被占先)放棄CPU控制權,則其局部變量大多數(shù)并不需要進行特別的保護,即其作用域只是任務的當次執(zhí)行,針對上面的代碼,就是臨界保護區(qū)內(nèi)的代碼區(qū)域。

  2 實時操作系統(tǒng)要不要占先

  由上面的分析,如果要保持一個函數(shù)可重人,就得使用靜態(tài)變量,系統(tǒng)的RAM資源將是一個嚴峻的考驗;如果使用臨界區(qū)來保護運行環(huán)境,系統(tǒng)的實時性又得不到保證,而且有將占先式任務調(diào)度轉為非占先任務調(diào)度之虞。顯然,使用靜態(tài)變量簡單,但有更多的不適用性,對將來功能的調(diào)整也是一個阻礙,一般不被采用。那么,就只能從環(huán)境保護上來下功夫了,但是果真只能以進入臨界區(qū)犧牲系統(tǒng)的實時性來保證任務不被占先?下面看看臨界保護這一方法的基本思路:

 ?、僭谝粋€任務中,如果局部變量在其作用域內(nèi)不被占先切換,則這些變量在任務被剝奪了CPU控制權后,不關心其值也不會影響任務的正確執(zhí)行;

 ?、谑褂门R界區(qū)保護,可以達到上面所提到的要求;

 ?、塾纱藢е碌膶崟r性能與占先切換的減弱可以接受。由此可知,不被占先是任務保護局部變量的關鍵。既然如此,何不舍棄占先式的任務調(diào)度?這不失為一個好的出發(fā)點。針對Keil C51,非占先式任務調(diào)度,可能是一種更好的方法,更能協(xié)調(diào)51系列單片機的既定資源。下面編寫這樣一個系統(tǒng):

 ?、偈褂梅钦枷仁饺蝿照{(diào)度;

 ?、诳梢栽谛∪萘康男酒惺褂茫_發(fā)目標是,即使是8051這樣小的芯片,也可使用這個實時操作系統(tǒng);

 ?、壑С謨?yōu)先級調(diào)度,盡可能保證其實時性。

 

  3 實時操作系統(tǒng)的實現(xiàn)

 

  基于以上的分析與目的,近日完成了這個操作系統(tǒng)。在堆棧上借用RTx的管理方法,即當前任務使用全部的堆空間,如圖1所示。

 

  

 

  3.1 堆棧的初始化與任務的創(chuàng)建

  堆棧的初始化實際是初始化0STaskStackBotton數(shù)組,并將當前任務指定為空閑任務,下一個運行任務指定為最高優(yōu)先級任務,即優(yōu)先級為零的任務。初始化時,將SP的值存人OSTaslkStackBotton[O],SP+2的值存入OSTaskStacKBotton[1],依此類推。而任務是調(diào)用0STa-skCreate函數(shù)建立的。實際上只是將任務(假設為n號任務)的地址填人到對應OSTaskStackBotton[n]所指向的位置,并將SP向后移動2個字節(jié),如圖2所示。

 

  

 

  為什么要以這樣一種規(guī)律而不是其他的方式呢?這是由于在任務建立后,還未進行任務調(diào)度之前,各任務的堆棧實際上是它們自身的地址,因而其堆棧深度為2,為了程序的簡便而直接填入。

  void main(void){

  OSInit(); /*初始化OSTaskStackBcBotton隊列*/

  TMOD=(TMOD&0XFO)│ 0XOl;

  TL0=0xBF;

  TH0=0xFC;

  TRO=1;

  ETO=1;

  TFO=O:

  OSTaskCreate(TaskA,NULL,0);

  OSTaskCreate(TaskB.NULL,1);

  OSTaskCreate(TaskC,NULL,2);

  OSStart();

  上面這段代碼中,所有任務建立后,便調(diào)用OSStart()開始任務調(diào)度。OSStart()是一個宏定義,如下所示:

  #deflne OSStart() d0{\

  OSTaskCreate(TaskIdle,NULL,OS_MAX_TASKS);\

  EA=l:\

  return;\

  }while(O)

  首先,它創(chuàng)建了一個空閑任務并打開中斷,然后便返回。返回到哪里了呢?我們知道,空閑任務是優(yōu)先級最低的任務,當調(diào)OSTaskCreate建立時,會將其地址填人到SP的位置,并把SP向后移動2個字節(jié)(見圖2及說明),因而此時處在堆棧頂端的,一定是空閑任務Taslddle。這就使得這里的return一定會返回到空閑任務。至此,系統(tǒng)進入正常運行狀態(tài)。

  3.2 任務的切換

  任務的切換分兩種情況,在當前任務優(yōu)先級低于下一個取得CPU控制權的任務時,將下一個取得CPU控制權的任務的棧頂?shù)疆斍叭蝿盏臈m斨g的內(nèi)容向RAM空間的高端搬移,以空出全部的RAM空間作下一個任務的堆空間,同時更新對應的OSTaskStackBotton,使其指向新的正確任務的堆棧棧底。如果當前任務的優(yōu)先級高于下一個任務的優(yōu)先級,則作相反的搬移,如圖3與圖4所示。

 

  

 

  所有任務必須主動調(diào)用OSSleep,放棄CPU的控制權。任務調(diào)用OSSleep后,將選擇優(yōu)先級最高的就緒任務運行。

  結 語

  系統(tǒng)完成后,內(nèi)核的代碼量在400多個字節(jié)左右,占用1個定時器中斷及小量的內(nèi)存空間。系統(tǒng)設置容量為8個任務,用戶實際可用任務為7個,能夠滿足一般需求,也達到了在小容量芯片中應用的開發(fā)要求。由于沒有采用占先式的任務調(diào)度,除開全程相關的個別任務的一些局部變量外,其他局部變量已經(jīng)不存在覆蓋關系,由于是任務主動放棄CPU控制權,對于個別需要保護的變量單獨進行處理也變得容易。在系統(tǒng)中,全程不需要反復地開關中斷,實時性能也很好。對個別時序要求嚴格的外設(如DSl8820)除外。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉