色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

英創:經典的DOS程序框架流程圖分析

英創信息技術 ? 作者:英創信息技術 ? 2019-10-17 11:23 ? 次閱讀

本文介紹以英創公司嵌入式PC模塊為平臺,以事件驅動為特色的一種通用的嵌入式系統應用程序方案,該方案滿足大多數中、低端嵌入式系統需求,可廣泛應用于智能測控設備、POS終端產品工業自動化網絡通訊管理等領域。采用英創嵌入式網絡模塊的客戶,更是可以此為基礎,直接進入應用功能的軟件規劃及實現,從而大大節省應用程序的開發時間,同時保證應用程序的高穩定性。本應用程序方案的核心是通過對一個簡單的任務命令隊列進行操作,來實現各個不同的應用程序功能。下圖是本方案的典型流程框圖。

1、系統流程概述

在上圖中表示了3種不同的流程,它們是程序代碼流程、任務命令(也稱為事件)流程、以及數據的流程,以下對這三種流程做一簡要介紹。

程序流程

應用程序啟動后,首先進行必要的程序初始化配置,便進入系統核心代碼,核心程序將依次讀取系統任務隊列中的事件代碼,并根據代碼內容轉入相應的程序功能模塊。不同的程序功能模塊對應著不同的任務,即圖中所標注的任務1、任務2、任務n等等,這些任務代碼的特點之一是通過內部的狀態機機制來避免程序阻塞,使得程序能快速返回系統任務調度單元,從而實現任務間的切換。

任務劃分的原則一般是按照應用功能或層次來劃分,如任務1對原始數據進行處理,任務2對處理的結果數據進行網絡傳送,任務3對數據進行文件備份。為了提高系統對事件的響應速度,每個任務不宜設計得過長,就大多數嵌入式系統應用來看,可以把任務的執行時間控制在100ms之內,對需要更長執行時間的功能,可以通過內部設置狀態機的方式來化解。

命令流程

系統命令,通常也稱為系統事件,可由系統中多個單元產生,這些單元可以是系統的定時中斷程序,與應用相關的硬件中斷程序以及各個任務功能程序模塊,它們根據自身的運行狀況,生成必要的事件并把這些事件推入系統任務隊列。進入系統任務隊列的事件是完全異步的,它們按照時間順序排列,統一由系統核心代碼讀取,并啟動相應的任務模塊對該事件進行處理,這就是所謂的事件驅動機制。在程序設計中采用事件驅動的一個直接的好處是降低了各任務間的耦合性,提高了代碼的可靠性及可維護性。

命令通常可定義成枚舉變量,另可考慮命令參數段,可存放若干參數或字符串。系統任務隊列是一個典型的FIFO數據結構,系統為中斷程序和普通的任務模塊提供了發送事件的API函數。定時任務發生器是一段加載到系統定時中斷中的代碼,在DOS系統中一般可提秒級以上的定時事件,更小時間間隔的事件,可通過系統的其他定時器中斷實現,對于一般的嵌入式應用,最小定時事件不宜小于5ms,否則會無為增加CPU的開銷,降低系統性能。在命令定義中,一般會定義IDLE或NOP命令,在IDLE任務中可以放常規的數據處理,也可以放檢查是否有鍵盤、是否有網絡數據來等等,并可形成必要的事件發送到系統任務隊列,以啟動相應的處理。

數據流程

各個任務模塊的主要功能之一就是對各級應用數據進行必要的加工,并形成新的數據。典型的數據加工可以是:

對串口來的數據進行幀格式分析,提取相關數據,即通常的通訊規約分析;

AD采集的原始數據進行某種統計處理,提取特征數據;

讀取數字輸入狀態,進行必要處理;

讀取網絡報文,進行必要的應用層規約解析

應用數據存文件,文件數據處理等等

由于每個任務的執行機會具有一定的不確定性,因此需要對數據開設一定的緩沖區,對一般的應用來說,數據處理通常都是順序進行的,所以數據緩沖區的結構通常采用FIFO數據結構,緩沖區的數據單元即可是簡單的字節、字,也可以是復合的數據結構。在英創提供的程序中,串口的數據緩沖區就是采用的FIFO數據結構,數據單元為一個字節,FIFO結構的數據緩沖區也稱為環型buffer。

可以由一個任務作數據處理,另一個任務作數據傳送,對多任務共享的單一數據單元,可通過設置信號燈的方法來確保數據單元的完整性,對多個數據單元,同樣可考慮采用FIFO數據結構。對數據響應時間有嚴格要求的應用,也可以用一個任務實現數據采集處理和網絡通訊全過程。

以下具體介紹實現上述方案的主要代碼。建議用戶在閱讀本文之前,已對英創嵌入式模塊的功能測試程序有了基本了解。

2、主要程序代碼分析

主控流程與應用任務

#include < stdio.h > // 包含所需的C運行庫

#include < dos.h >

#include “etr_tcp.h” // 英創TCP/IP庫

#include “cmdrive.h” // 事件驅動API定義

int SysInit( ); // 系統初始化函數定義

void SysExit( ); // 系統退出處理

int main( )

{

int i1, len, State, ExitFlag; // 局部變量

CMD CmdCode; // 系統命令枚舉變量

char CmdPar[20]; // 系統命令所帶參數

i1 = SysInit( ); // 首先進行初始化

for( ExitFlag=0; ; ) // 系統主循環

{

ReloadWDT( ); // 加載watchdog

State = NET_Running( ); // 網絡鏈路管理

CmdCode = CmdQueue.GetCmd( CmdPar ); // 從系統任務隊列讀取命令

switch( CmdCode )

{

case NOP: // 進行常規處理,如檢查鍵盤、網絡、串口等

NetPackagePro( ); // 做必要的網絡低層處理

// 若網絡接收到數據,則啟動相應任務進行處理

if( NetHasData( ) ) CmdQueue.PushCmd( TASK1 );

break;

case TASK1:

i1 = Task1.Do ( ); // 也可以是普通C函數

break;

case TASK2:

i1 = Task2. Do ( );

if( i1 ) CmdQueue.PushCmd( TASK2 ); // 發送命令,以繼續任務處理

break;

case TASK3:

i1 = Task3.Do ( );

break;

default: ExitFlag =1; // 非法命令,退出

}

if( ExitFlag ) break;

}

SysExit( );

return 0;

}

系統初始化程序SysInit( ),首先是對系統提供的資源進行初始化,如網絡初始化、串口初始化、LCD顯示初始化等等,然后是對應用定義的功能對象進行初始化,最后是安裝中斷服務程序,啟動定時任務發生器。相應地,SysExit( )函數則主要是卸載中斷,釋放在初始化中分配的動態buffer。

在主循環中的NOP處理,是以網絡通訊為例,客戶在實際應用程序設計中可以安排其他需要的處理,如處理鍵盤、處理串口數據等等。對應用級任務,建議采用C++的類來實現,每個類對象應至少有2個公共函數:Init( )和Do( )函數,主控程序可以通過Do( )函數的返回值來判斷處理已完成或未完成,若未完成,可發命令再啟動本函數進行后續處理,在上面的程序中任務TASK2的處理就是這樣做的。用C++的類對象來實現應用功能,可通過私有變量來定義處理的狀態,在進行交互式的通訊處理時,如操作串口設備,FTP文件上傳等,特別有用,一旦需要處理程序等待對端響應,程序就返回系統控制進行其他處理,等下次再進入該任務模塊時,程序可根據當前狀態繼續相應的處理,這就是所謂的狀態機機制。下面是應用任務的類定義:

#define ST0 0

#define ST1 1

#define ST2 2

#define ST3 3

class AppTASK

{

int State; // 私有的狀態變量

int DoST0( ); // 各個分步處理

int DoST1( );

int DoST2( );

int DoST3( );

public:

int Init( ); // 對包括State在內的變量進行初始化

int Do( ); // 任務處理函數

};

在類成員函數Do( )中實現具體的狀態轉移:

int AppTASK::Do( )

{

int i1;

i1 = 1; // 返回值 = 1:處理未完成;=0:處理完成

switch( State )

{

case ST0:

DoST0( );

State = ST1; // 前進到下一狀態

break;

case ST1:

DoST1( );

State = ST2; // 前進到下一狀態

break;

case ST2:

DoST2( );

State = ST3; // 前進到下一狀態

break;

case ST3:

DoST3( );

State = ST0; // 返回初始狀態

I1 = 0; // 處理完成!

break;

}

return i1;

}


整個程序方案中,核心的代碼是實現系統的事件驅動功能,被定義成一個C++類如下:

#if !defined(_CMDRIVE_H)

#define _CMDRIVE_H

#ifdef __cplusplus

#define __CPPARGS ...

#else

#define __CPPARGS

#endif

#include < dos.h >

enum CMD { NOP, TASK1, TASK2, TASK3, EXIT }; // 可以根據應用定義更多的命令

#define MaxCmdStack 400 // 定義系統任務隊列的長度

#define PARLEN 14 // 每個命令所帶參數的長度

class TaskQueue

{

static unsigned int PutIdx; // 通過2個index的操作,使CmdBuf[ ]成為

static unsigned int GetIdx; // 邏輯上的環型buffer,即FIFO數據結構

static CMD CmdBuf[MaxCmdStack];

static char CmdPar[MaxCmdStack][PARLEN];

static struct time OldTime;

static struct date OldDate;

static unsigned int TickCount; // 定時計數

static unsigned int TickSize; // 確定最小的定時間隔,可變,初值為0

static void interrupt INT1C_Handler(__CPPARGS); // 通過INT 1C實現定時任務發生器

static int ISR_PushCmd( CMD NewCmd, char* pPar=NULL ); // 中斷程序中使用

public:

TaskQueue( );

~TaskQueue( );

CMD GetCmd( char* pPar=NULL ); // 讀取當前隊列中的命令

int PushCmd( CMD NewCmd, char* pPar=NULL ); // 填入新的命令到系統任務隊列

void StartQueue( ); // 啟動定時任務發生器

void StopQueue( ); // 關閉定時任務發生器

};

extern class TaskQueue CmdQueue; // 在cmdrive.cpp中定義的類變量實例

#endif

在TaskQueue類的定義中有3個核心API函數,用于實現任務隊列和定時任務發生:

CMD TaskQueue::GetCmd( char* pPar ) // 從FIFO讀取命令

{

CMD CmdCode;

if( GetIdx != PutIdx )

{

disable( );

CmdCode = (CMD)CmdBuf[GetIdx];

if( pPar != NULL ) memcpy( pPar, CmdPar[GetIdx], PARLEN );

GetIdx = ( GetIdx + 1 ) % MaxCmdStack;

enable( );

return CmdCode;

}

return NOP;

}

// return = -1: command aborted

// = 0: command pushed

int TaskQueue::PushCmd( CMD NewCmd, char* pPar ) // 把命令填入任務隊列

{

unsigned int Idx;

if( GetIdx == 0 ) Idx = MaxCmdStack - 1;

else Idx = GetIdx - 1;

disable( );

if( PutIdx == Idx ) return -1; // 表明隊列已滿

CmdBuf[PutIdx] = NewCmd; // 填入命令碼

if( pPar == NULL ) memset( CmdPar[PutIdx], 0, PARLEN ); // 填入參數

else memcpy( CmdPar[PutIdx], pPar, PARLEN );

PutIdx = ( PutIdx + 1 ) % MaxCmdStack; // 序號按模加1

enable( );

return 0;

}

環形緩沖區的核心是使用了一塊連續的內存,并定義了兩個Index序號:一個是記錄往緩沖區填數的PutIdx;一個是記錄從緩沖區取數的GetIdx。置數和取數是兩個完全異步的過程,所以PutIdx和GetIdx移動的瞬時速度不一定相同,但平均速度一致,當PutIdx==GetIdx表明緩沖區是空的,已經無數可取,而當PutIdx-GetIdx=1時,表明緩沖區已滿,不允許再存數。

void interrupt TaskQueue::INT1C_Handler(__CPPARGS) // 定時任務發生器

{

int i1;

struct time t;

struct date d;

enable( );

TickCount++; // x86的系統時鐘大約55ms中斷一次

if( TickCount >= TickSize )

{

GetSystime( &t ); // get current time

if( t.ti_sec != OldTime.ti_sec ) // 作整秒檢查

{

ISR_PushCmd( TASK1 ); // 每秒執行一次TASK1

TickSize = 18; // 整秒對齊

TickCount = 0;

OldTime.ti_sec = t.ti_sec;

if( t.ti_min != OldTime.ti_min ) // 作整分檢查

{

ISR_PushCmd( TASK2 ); // 每分鐘執行一次TASK2

OldTime.ti_min = t.ti_min; // update minute then

if( OldTime.ti_hour != t.ti_hour ) // processing hour data

{

ISR_PushCmd( TASK3 ); // 每小時執行一次TASK3

OldTime.ti_hour = t.ti_hour; // update hour then

}

}

}

}

}

按照上述代碼實現的方法,用戶很容易實現其他時間間隔的定時任務。

3、程序程序運行測試分析

建議每個任務的每次執行時間控制在100ms,以便系統合理的分配各任務的執行時間,節約系統的數據buffer開銷。對大多數應用來說,這一要求很容易得到滿足。本應用程序方案首先在NetBox-II(CPU主頻24MHz)進行了測試,其任務調度的時間在90us水平,對100ms的任務間隔,系統占用時間小于1%,是完全可以接受的。

對于網絡應用,由于存在與對端的交互式操作,所以其整個通訊過程會超過100ms,這時合理的安排是利用等待對端響應的時間來處理系統的其它任務,因此需要在相應的任務中采用狀態機的方式來實現,具體的實現會在后續的應用程序方案中介紹。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式系統
    +關注

    關注

    41

    文章

    3587

    瀏覽量

    129436
收藏 人收藏

    評論

    相關推薦

    程序流程圖

    這個程序流程圖,請大神們幫幫我#include"config.h"/*************************clock data*************************************/#define c_ox 63#define c_oy
    發表于 07-05 11:07

    Labview流程圖

    Labview能夠生成流程圖嗎,Labview的程序能畫流程圖嗎?
    發表于 07-21 10:09

    visio畫程序流程圖

    弄清圖形符號: 運行Visio,新建一個基本流程圖。在形狀窗口中用基本流程圖的圖形符號來表示程序算法。表1給出了較常用的“流程圖”所用的基本符號。 舉例使用: 一、制作順序結構
    發表于 07-03 00:19

    怎樣繪制流程圖

    流程圖進行新建使用。3.在左側面板中選擇我們需要的流程圖圖形,移動至右面面板中進行使用,然后會用線段將搭建的流程圖圖形進行連接,這樣框架就算搭建完成。4.現在就是對內容進行輸入,雙擊
    發表于 01-15 11:38

    Sop流程圖操作規范

    流程圖符號 流程圖結構說明 流程圖繪制原則
    發表于 08-27 17:57 ?42次下載

    化工工藝流程圖閥門程序設計

    化工工藝流程圖閥門程序設計提要:本文針對化工工藝流程圖CAD閥門繪制程序設計,探討CAD在化工工藝設計中的運用。文后提供的程序清單可在Au
    發表于 02-14 17:06 ?3119次閱讀

    8253中斷服務程序流程圖

    8253中斷服務程序流程圖 希望發電機P =
    發表于 05-03 00:12 ?4922次閱讀
    8253中斷服務<b class='flag-5'>程序</b><b class='flag-5'>流程圖</b>

    IC設計流程圖

    IC設計流程圖 ?
    發表于 02-06 16:22 ?5235次閱讀
    IC設計<b class='flag-5'>流程圖</b>

    JF24C程序流程圖

    JF24C程序流程圖,很好的學習資料,快來下載吧
    發表于 02-16 16:34 ?16次下載

    流程圖設計器簡介

    本視頻介紹了Flow Graph Designer工具,該工具可用于使用英特爾?線程構建模塊(英特爾?TBB)流程圖界面創建和分析應用程序
    的頭像 發表于 10-30 06:19 ?3138次閱讀

    項目流程圖怎么畫?項目流程圖經典免 費模板分享

    ????? 流程圖是一種用于描述事件流程的符號化的圖形語言,涵蓋了流進系統的信息流、觀點流和部件流等信息。而項目流程圖,顧名思義,就是表述整個項目流程的一種圖形展示,用于給團隊項目各部
    的頭像 發表于 07-28 11:58 ?3285次閱讀

    NS流程圖是什么?用這款軟件輕松畫NS流程圖

    NS流程圖,又被稱為N-S,或者是盒。它的結構分為圖形、流程線和文字,NS流程圖是一種可視化建模的結構化編程。實際上,NS
    的頭像 發表于 07-28 11:59 ?1.4w次閱讀
    NS<b class='flag-5'>流程圖</b>是什么<b class='flag-5'>圖</b>?用這款軟件輕松畫NS<b class='flag-5'>流程圖</b>

    直流無刷電機控制器程序流程圖

    直流無刷電機控制器程序流程圖(新型電源技術論文)-直流無刷電機控制器程序流程圖? ? ? ? ? ? ? ? ? ? ? ? ?
    發表于 09-18 18:02 ?127次下載
    直流無刷電機控制器<b class='flag-5'>程序</b><b class='flag-5'>流程圖</b>

    27個非常經典的設備工作流程圖

    今天給大家分享27個非常經典的設備工作流程圖解。
    的頭像 發表于 06-02 17:16 ?1756次閱讀
    27個非常<b class='flag-5'>經典</b>的設備工作<b class='flag-5'>流程圖</b>解

    fpc流程圖.zip

    fpc流程圖
    發表于 03-01 15:37 ?2次下載
    主站蜘蛛池模板: 欧洲另类一二三四区| 挺进老师的紧窄小肉六电影完整版 | 豆奶视频在线高清观看| 国产麻豆精品久久一二三| 精品人妻一区二区三区视频53 | 日本久久免费大片| 亚洲视频免费在线观看| chinese帅哥gv在线看| 国产亚洲精品久久久久久久软件| 麻豆久久婷婷五月国产| 歪歪爽蜜臀AV久久精品人人槡| 伊人激情综合网| 港台三级大全| 狂野欧美性猛XXXX乱大交| 天天操人人射| 99re久久超碰视频精品| 国产午夜免费视频片夜色| 欧美亚洲精品一区二三区8V| 亚洲精品不卡视频| xxx动漫xxx在线观看| 亚洲乱亚洲乱妇在线观看| 中文中幕无码亚洲在线| 国产精人妻无码一区麻豆| 女教师の诱惑| 一二三四在线播放免费观看中文版视频| 纯肉高H放荡受BL文库| 伦理79电影网在线观看| 亚洲AV国产国产久青草| 扒开屁股眼往里面夹东西| 久久视热频国只有精品| 校花娇喘呻吟校长陈若雪视频| 99久久免热在线观看6| 九九在线精品视频| 婷婷四房播客五月天| 凹凸精品视频分类视频| 毛片手机在线| 一道本无吗d d在线播放| 国产精品伊人| 日韩中文字幕亚洲无线码| 999精品在线| 口工漫画r18全彩啪啪|