阻塞式程式設計和非阻塞式程式設計區別
很多微控制器的初學者容易掉入阻塞式程式設計的陷阱.因為阻塞式程式設計符合我們對現實世界的理解,一個人在一段時間內,只能做一件事情.例如要是實現1Hz的閃燈程式,那麼先讓微控制器埠拉高500ms,然後再拉低500ms,然後迴圈.因為等待時間太長了,沒有開啟看門狗.
下面是阻塞式程式設計的例子:
#include "extern.h"
/*埠定義*/
BIT LED : PA.3;
BIT LED1 : PA.4;
/*相應於main函式*/
void FPPA0 (void)
{
/*微控制器內部RC震動時鐘為 IHRC預設為16M,因此,IHRC/2=8M,系統時鐘為8M*/
.ADJUST_IC SYSCLK=IHRC/2
/*埠設定為輸出 低*/
$ LED out ,low;
$ LED1 out ,low;
/*主迴圈*/
while (1)
{
/*埠置高*/
LED=1;
/*延時單位1T(1個時鐘週期),延時8000=1ms,一共延時500ms*/
.delay 8000*500;
/*埠置低*/
LED=0;
/*延時500ms*/
.delay 8000*500;
}
}
OK 完美執行.
但是,當要你再加上一個指示燈,要2Hz閃爍,也就是250ms關,250ms開,然後迴圈,那要怎麼辦了.
OK繼續,剛剛辛辛苦苦寫好的程式得重新寫了.
/*相應於main函式*/
void FPPA0 (void)
{
/*微控制器內部RC震動時鐘為 IHRC預設為16M,因此,IHRC/2=8M,系統時鐘為8M*/
.ADJUST_IC SYSCLK=IHRC/2
/*埠設定為輸出 低*/
$ LED out ,low;
$ LED1 out ,low;
/*主迴圈*/
while (1)
{
/*埠置高*/
LED=1;
LED1=1;
/*延時單位1T(1個時鐘週期),延時8000=1ms,一共延時250ms*/
.delay 8000*250;
LED=1;
LED1=0;
/*延時單位1T(1個時鐘週期),延時8000=1ms,一共延時250ms*/
.delay 8000*250;
LED=0;
LED1=1;
/*延時單位1T(1個時鐘週期),延時8000=1ms,一共延時250ms*/
.delay 8000*250;
LED=0;
LED1=0;
/*延時單位1T(1個時鐘週期),延時8000=1ms,一共延時250ms*/
.delay 8000*250;
}
}
OK,完美執行,要加上按鍵呢?怎麼辦,感覺越來越麻煩了.
其實,微控制器幹起事情來比我們想象得要快得多.例如8M的主頻,1T的微控制器,在1S鍾之內就可以執行8,000,000條指令.在很多時候,我們幾乎可以忽略微控制器在執行兩條指令的時間差,也就是說雖然微控制器程式是順序執行的,在人看來效果和並行執行沒有任何差別.不能讓微控制器在等待.LED開/關其實就是一條指令的事.做好定時就OK了.
下面來個非阻塞式程式的案例.
#include "extern.h"
#define HIGH 1
#define LOW 0
#define DISABLE 0
#define ENABLE 1
#define EMPTY 0
#define FULL 1
#define ON 1
#define OFF 0
/*燈*/
BIT LED : PA.3;
/*按鍵*/
BIT LED1 : PA.4;
word usLedTmrCnt;
word usLedTmrCnt1;
/*定時時間是否到了cinit*/
bit FLAG_NMS;
/*計數值cinit*/
byte count;
/*定時器初始化cinit*/
word T16COUNTER;
/***************************************/
void TIME16_Init(void)
{
/*計數值清零*/
T16COUNTER =488;
/*ms標記reset*/
FLAG_NMS =0;
/*使能定時器*/
$ INTEN T16;
/*關中斷*/
INTRQ = 0;
/*停止定時器*/
T16M.5 =0;
STT16 T16COUNTER;
/*計算方法16M/*/
$ T16M IHRC,/1,BIT11;
}
void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=3.5V,init_ram;
$ CLKMD IHRC/2,En_IHRC,En_ILRC,En_WatchDog;
$ LED OUT,LOW;
$ LED1 OUT,LOW;
TIME16_Init();
engint;
while (1)
{
wdreset;
/*1ms定時時間到*/
if ( FLAG_NMS )
{
usLedTmrCnt++;
if(usLedTmrCnt>500)
{
usLedTmrCnt=0;
/*類似Led=~Led*/
if(LED)
{
LED=0;
}
else
{
LED=1;
}
}
#if 1
usLedTmrCnt1++;
if(usLedTmrCnt1>250)
{
usLedTmrCnt1=0;
/*類似Led1=~1Led*/
if(LED1)
{
LED1=0;
}
else
{
LED1=1;
}
}
#endif
/*清除標記*/
FLAG_NMS=0;
}
}
}
void Interrupt ( void )
{
pushaf;
if ( Intrq.T16 )
{
Intrq.T16 = 0;
STT16 T16COUNTER;
if ( count>0 )
{
count--;
}
else
{
count = 9;
/*1ms*/
FLAG_NMS= 1;
}
}
popaf;
}
給LED 和LED1各分配一個計數器,可以設定1-65535ms的翻轉時間.LED亮/滅只需要一條指令.其他的時候就查詢一下1ms標記有沒有,有就計數,當計數值溢位的時候就把LED進行翻轉.就這麼簡單.各自獨立,沒有長時間的等待,看門狗也開啟了.在埠和記憶體允許的情況下還可以新增N個.在這個框架下,還可以擴充套件按鍵,顯示.....
這裡並不是說阻塞式的程式不好,而是有一定的侷限性.在寫簡單的應用中也很好用.很直觀.
相關文章
- Java 網路程式設計 —— 非阻塞式程式設計Java程式設計
- [譯] 非同步程式設計:阻塞與非阻塞非同步程式設計
- linux非阻塞式socket程式設計之select()用法Linux程式設計
- Socket程式設計中的同步、非同步、阻塞和非阻塞(轉)程式設計非同步
- NIO非阻塞程式設計小案例程式設計
- Java 網路程式設計 —— 實現非阻塞式的伺服器Java程式設計伺服器
- 玩轉 PHP 網路程式設計全套阻塞與非阻塞 IOPHP程式設計
- FastAPI之阻塞式io和非阻塞式ioASTAPI
- python 網路程式設計----非阻塞或非同步程式設計Python程式設計非同步
- 併發程式設計之臨界區\阻塞\非阻塞\死鎖\飢餓\活鎖程式設計
- Linux裝置驅動程式設計之阻塞與非阻塞(轉)Linux程式設計
- Java NIO 阻塞式與非阻塞式Java
- IO multiplexing 與 非阻塞網路程式設計程式設計
- 阻塞/非阻塞讀寫總結、tcp網路程式設計的本質、muduo::Buffer設計簡介TCP程式設計
- 【網路程式設計】阻塞IO程式設計的坑程式設計
- Linux核心程式設計(阻塞程式)(轉)Linux程式設計
- 同步、非同步、阻塞、非阻塞的區別非同步
- IO模式設定網路程式設計常見問題總結—IO模式設定,阻塞與非阻塞模式程式設計
- 分散式系統關注點(20)——阻塞與非阻塞有什麼區別?分散式
- Linux核心模組程式設計--阻塞程式(轉)Linux程式設計
- 基於promise的阻塞式佇列設計Promise佇列
- IO - 同步 非同步 阻塞 非阻塞的區別非同步
- 【進階之路】併發程式設計(三)-非阻塞同步機制程式設計
- Java併發程式設計:阻塞佇列Java程式設計佇列
- Java併發程式設計——阻塞佇列Java程式設計佇列
- 《JAVA併發程式設計實戰》原子變數和非阻塞同步機制Java程式設計變數
- C++ 之Socket 程式設計 send rev 阻塞設定 阻塞超時時間C++程式設計
- 一文徹底搞定(阻塞/非阻塞/同步/非同步)網路IO、併發程式設計模型、非同步程式設計模型的愛恨情仇非同步程式設計模型
- Java網路程式設計和NIO詳解5:Java 非阻塞 IO 和非同步 IOJava程式設計非同步
- 一直讓 PHP 程式設計師懵逼的同步阻塞非同步非阻塞,終於搞明白了PHP程式設計師非同步
- 用fcntl()設定阻塞函式的阻塞性質函式
- 同步、非同步、阻塞和非阻塞非同步
- 怎樣理解阻塞非阻塞與同步非同步的區別?非同步
- 阻塞程式函式 wait()和waitpid()函式AI
- GPU程式設計--CPU和GPU的設計區別GPU程式設計
- 函式程式設計函式程式設計
- 阻塞式IO
- 揚帆起航:從指令式程式設計到函式響應式程式設計程式設計函式