日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 嵌入式 > 嵌入式大雜燴
[導讀]關注「嵌入式大雜燴」,選擇「星標公眾號」一起進步!作者?|?Alicedodo狀態(tài)機是一種思想,事件驅動也是一種思想。狀態(tài)機推文:干貨|嵌入式之狀態(tài)機編程改變嵌軟開發(fā)思維方式之:狀態(tài)機的三種實現方法本篇來一起學習事件驅動。事件驅動的概念生活中有很多事件驅動的例子,上自習瞞著老師偷...

關注「嵌入式大雜燴」,選擇「星標公眾號」一起進步!




作者 | Alicedodo


狀態(tài)機是一種思想,事件驅動也是一種思想。


狀態(tài)機推文:


干貨 | 嵌入式之狀態(tài)機編程


改變嵌軟開發(fā)思維方式之:狀態(tài)機的三種實現方法


本篇來一起學習事件驅動。


事件驅動的概念

生活中有很多事件驅動的例子,上自習瞞著老師偷睡覺就是很生動的一個。


我們都是從高中時代走過來的,高中的學生苦啊,覺得睡覺是世界上最奢侈的東西, 有時候站著都能睡著?。±蠋熆吹膰?,上課睡覺不允許 啊,要挨批??!有木有!相比而言,晚自習是比較寬松的,老師只是不定時來巡視,還是有機會偷偷睡一會兒的。


現在的問題是,怎么睡才能既睡得好又不會讓老師發(fā)現呢? 晚自習是比較寬松的,老師只是不定時來巡視,還是有機會偷偷睡一會兒的?,F在的問題是,怎么睡才能既睡得好又不會讓老師發(fā)現呢?


我們現在有三種睡覺方案:


  • 方案 A:倒頭就睡,管你三七二十一,睡夠了再說,要知道有時候老師可能一整晚上都不來的。
  • 方案 B:間歇著睡,先定上鬧鐘, 5 分鐘響一次,響了就醒,看看老師來沒來,沒來的話定上鬧鐘再睡,如此往復。
  • 方案 C:睡之前讓同桌給放哨,然后自己睡覺,什么也不用管,什么時候老師來了,就讓同桌戳醒你。
不管你們選擇的是哪種方案,我高中那會兒用的可是方案 C,安全又舒服。


方案 C 是很有特點的:本來自習課偷睡覺是你自己的事兒, 有沒有被老師抓著也是你自己的事兒,這些和同桌是毫無利害關系的,但是同桌這個環(huán)節(jié)對方案 C 的重要性是不言而喻的,他肩負著監(jiān)控老師巡視和叫醒睡覺者兩項重要任務,是事件驅動機制實現的重要組成部分 。


在事件驅動機制中,對象對于外部事件總是處于“休眠” 狀態(tài)的,而把對外部事件的檢測和監(jiān)控交給了第三方組件。


一旦第三方檢測到外部事件發(fā)生, 它就會啟動某種機制, 將對象從“休眠” 狀態(tài)中喚醒, 并將事件告知對象。對象接到通知后, 做出一系列動作, 完成對本次事件響應,然后再次進入“休眠” 狀態(tài),如此周而復始。


有沒有發(fā)現,事件驅動機制和單片機的中斷原理上很相似 。


事件驅動與單片機編程

在我們再回到單片機系統(tǒng)中來,看看事件驅動思想在單片機程序設計中的應用。當我還是一個單片機菜鳥的時候(當然,我至今也沒有成為單片機高手),網絡上的大蝦們就諄諄教導:一個好的單片機程序是要分層的。曾經很長一段時間, 我對分層這個概念完全沒有感覺。


  • 什么是程序分層?
  • 程序為什么要分層?
  • 應該怎么給程序分層?
隨著手里的代碼量越來越多,實現的功能也越來越多,軟件分層這個概念在我腦子里逐漸地清晰起來,我越來越佩服大蝦們的高瞻遠矚。


單片機的軟件確實要分層的,最起碼要分兩層:驅動層和應用層。應用是單片機系統(tǒng)的核心,與應用相關的代碼擔負著系統(tǒng)關鍵的邏輯和運算功能,是單片機程序的靈魂。


硬件是程序感知外界并與外界打交道的物質基礎,硬件的種類是多種多樣的,各類硬件的操作方式也各不相同,這些操作要求嚴格、精確、瑣細、繁雜。


與硬件打交道的代碼只鐘情于時序和寄存器,我們可以稱之為驅動相關代碼;與應用相關的代碼卻只專注于邏輯和運算, 我們可稱之為應用相關代碼。


這種客觀存在的情況是單片機軟件分層最直接的依據,所以說,將軟件劃分為驅動層和應用層是程序功能分工的結果。那么驅動層和應用層之間是如何銜接的呢?


在單片機系統(tǒng)中,信息的流動是雙向的,由內向外是應用層代碼主動發(fā)起的,實現信息向外流動很簡單, 應用層代碼只需要調用驅動層代碼提供的 API 接口函數即可, 而由外向內則是外界主動發(fā)起的, 這時候應用層代碼對于外界輸入需要被動的接收, 這里就涉及到一個接收機制的問題,事件驅動機制足可勝任這個接收機制。


外界輸入可以理解為發(fā)生了事件,在單片機內部直接的表現就是硬件生成了新的數據,這些數據包含了事件的全部信息, 事件驅動機制的任務就是將這些數據初步處理(也可能不處理),然后告知應用層代碼, 應用代碼接到通知后把這些數據取走, 做最終的處理, 這樣一次事件的響應就完成了。


說到這里,可能很多人突然會發(fā)現,這種處理方法自己編程的時候早就用過了,只不過沒有使用“事件驅動” 這個文縐縐的名詞罷了。其實事件驅動機制本來就不神秘, 生活中數不勝數的例子足以說明它應用的普遍性。下面的這個小例子是事件驅動機制在單片機程序中最常見的實現方法,假設某單片機系統(tǒng)用到了以下資源:


  • 一個串口外設 Uart0,用來接收串口數據;
  • 一個定時器外設 Tmr0,用來提供周期性定時中斷;
  • 一個外部中斷管腳 Exi0,用來檢測某種外部突發(fā)事件;
  • 一個 I/O 端口 Port0,連接獨立式鍵盤,管理方式為定時掃描法,掛載到 Tmr0 的 ISR;
這樣,系統(tǒng)中可以提取出 4 類事件,分別是 UART、 TMR、 EXI、 KEY ,其中 UART 和KEY 事件發(fā)生后必須開辟緩存存儲事件相關的數據。所有事件的檢測都在各自的 ISR 中完成,然后 ISR 再通過事件驅動機制通知主函數處理。


為了實現 ISR 和主函數通信, 我們定義一個數據類型為INT8U的全局變量 g_u8EvntFlgGrp,稱為事件標志組,里面的每一個 bit 位代表一類事件,如果該 bit 值為 0,表示此類事件沒有發(fā)生,如果該 bit 值為 1,則表示發(fā)生了此類事件,主函數必須及時地處理該事件。圖 5 所示為g_u8EvntFlgGrp 各個 bit 位的作用 。



程序清單 List9 所示就是按上面的規(guī)劃寫成的示例性代碼 。


程序清單List9:


#define FLG_UART 0x01
#define FLG_TMR 0x02
#define FLG_EXI 0x04
#define FLG_KEY 0x08
volatile INT8U g_u8EvntFlgGrp = 0; /*事件標志組*/
INT8U read_envt_flg_grp(void);
/***************************************
*FuncName : main
*Description : 主函數
*Arguments : void
*Return : void
*****************************************/

void main(void)
{
INT8U u8FlgTmp = 0;
sys_init();
while(1)
{
u8FlgTmp = read_envt_flg_grp(); /*讀取事件標志組*/
if(u8FlgTmp ) /*是否有事件發(fā)生? */
{
if(u8FlgTmp 
本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯系該專欄作者,如若文章內容侵犯您的權益,請及時聯系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關閉