當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]本文檔包括單片機(jī)系統(tǒng)中常用到的時鐘中斷、通訊及鍵盤掃描等模塊(見所附源程序)的說明。這些模塊使用前后臺系統(tǒng)模型。為達(dá)到最大的靈活性,需要在用戶工程中定義config.h文件,在其中定義各模塊可選參數(shù)的設(shè)置 , 而不

本文檔包括單片機(jī)系統(tǒng)中常用到的時鐘中斷、通訊及鍵盤掃描等模塊(見所附源程序)的說明。這些模塊使用前后臺系統(tǒng)模型。為達(dá)到最大的靈活性,需要在用戶工程中定義config.h文件,在其中定義各模塊可選參數(shù)的設(shè)置 , 而不是直接更改源代碼。
這些可選內(nèi)容大部分為宏定義,如果不定義宏相應(yīng)的功能在編譯時被屏蔽,不會增加代碼長度。具體可選內(nèi)容見各模塊中的說明。
在Config.h文件中還要包含一個單片機(jī)硬件的資源頭文件。
各模塊使用了定義在Common.h中的一些數(shù)據(jù)類型。如 : BIT(bit)BYTE(unsignedchar)等,具體請參見源程序。

時鐘模塊
在單片機(jī)軟件設(shè)計(jì)中,時鐘是重要資源,為了充分利用時鐘資源,故設(shè)計(jì)本時鐘模塊。本模塊使用定時器0,在完成用戶指定功能的同時,還能夠自動處理一些其它模塊中與時鐘相關(guān)的信息。
時鐘模塊由聲明文件Timer.h以及實(shí)現(xiàn)文件Timer.c組成。
用戶應(yīng)該在Config.h中定義宏TIMER_RELOAD來設(shè)定定時器0的重裝載初值。推薦的定時器0的中斷時間大于1毫秒。

在程序的初始化階段調(diào)用時鐘模塊的初始化函數(shù)InitTimerModule()之后,就可以使用時鐘模塊所以支持的各種功能。具體描述如下:
延時:當(dāng)用戶需要進(jìn)行一定時間的延時時,可以通過調(diào)用Delay()來進(jìn)行,參數(shù)為時鐘中斷的次數(shù)。如時鐘中斷周期為1ms,想進(jìn)行100ms的延時,則可以調(diào)用Delay(100)。
注意:
如果延時的絕對時間小于時鐘中斷的周期,則不能夠用本方法做到延時。

定時:當(dāng)程序中需要使用定時功能時,如等待某外部事件,如果在一定時間內(nèi)發(fā)生則繼續(xù)執(zhí)行,如果在這段時間內(nèi)發(fā)生,則認(rèn)為出現(xiàn)錯誤,轉(zhuǎn)向錯誤處理機(jī)制。
在此推薦一種編程模式,但用戶可以用自己認(rèn)為更合理的方式處理此類問題。
這里簡單說明一下關(guān)于阻塞式函數(shù)及非阻塞式函數(shù)。簡單說,阻塞式函數(shù)就是當(dāng)檢測完成條件,如果不能夠完成則等待,如:
voidCheckSomething()
{
//gbitSuccessFlagisaglobalvariable
while(gbitSuccessFlag==FALSE)
{
//donothingbutwaiting
}
}
可以看到,當(dāng)bitSuccessFlag沒有被設(shè)置為TRUE時,函數(shù)保持等待狀態(tài)不返回,這樣就是阻塞式的函數(shù)。
另外一種情況:
BITCheckSomething()
{
if(gbitSuccessFlag==TRUE)
{
//…
returnTRUE;
}
returnFALSE;
}
在這里,如果所檢測的事件有沒有完成,函數(shù)進(jìn)行檢測之后,立刻返回,通過返回值報告完成情況,如果沒有完成,則等待調(diào)用者分配再次執(zhí)行的機(jī)會。這樣的函數(shù)就是非阻塞函數(shù)。
在應(yīng)用定時功能時,首先要將檢測函數(shù)定義成非阻塞函數(shù)。如上面的第二個版本的CheckSomething。
然后下面模式:
BITbitDone=FALSE;
ResetClock();//cleartimerinterrupttimescounter
while(GetClock(){
if(CheckSomething()==TRUE)
{
bitDone=TRUE;
break;
}
}
if(bitDone==FALSE)
{
//processtimeout
}

或者簡單寫成:
BITbitDone=FALSE;
ResetClock();
while(GetClock()if(bitDone==FLASE)
{
//…
}

軟件看門狗:實(shí)現(xiàn)具有局限性的看門狗功能。在程序中合適的地方加入對軟件看門狗的復(fù)位函數(shù)ResetWatchDog(),在Config.h中加入宏TIMER_WATCHDOGTIMEOUT。當(dāng)程序運(yùn)行時,如果在發(fā)生TIMER_WATCHDOGTIMEOUT次時鐘中斷之內(nèi)沒有復(fù)位軟件看門狗,則系統(tǒng)復(fù)位。
注意:
如果沒有加入TIMER_WATCHDOGTIMEOUT宏,程序中的ResetWatchDog沒有任何用處,不用刪除。
如果系統(tǒng)不能實(shí)現(xiàn)時鐘中斷,則軟件看門狗也同時失去功能。
目前版本的的時鐘模塊的復(fù)位功能并不是完全復(fù)位,主要表現(xiàn)在當(dāng)復(fù)位之后,系統(tǒng)將不再響應(yīng)任何中斷。所以軟件看門狗只是一個程序的調(diào)試功能,不應(yīng)該將它用于正式工作的程序,此時應(yīng)該使用硬件看門狗。

用戶自定義任務(wù):如果想在時鐘中斷內(nèi)執(zhí)行一些耗時較短的任務(wù),可以定義回調(diào)函數(shù)OnTimerInterrupt。函數(shù)原形為:voidOnTimerInterrupt();
如果想在發(fā)生時鐘中斷時執(zhí)行一些功能,而這些功能又耗時相對較長,不合適放在中斷響應(yīng)函數(shù)內(nèi)部,則可以在程序中的主循環(huán)中的任意地方添加:ImpTimerService(),同時提供原形為voidOnTimerEvent()的回調(diào)函數(shù)。具體的程序如下所示:
voidmain()
{
Initialize();
while(TRUE)
{
//…working
ImpTimerService();
//…working
}
}

voidOnTimerEvent()
{
//dosometask
}

對通訊模塊提供支持:如通訊中的各種超時等,見通訊模塊中的詳細(xì)說明。
對鍵盤掃描模塊提供支持:可以自動調(diào)用鍵盤掃描模塊,見鍵盤掃描模塊中的詳細(xì)說明。
對程序調(diào)試提供支持:在程序開發(fā)過程中,有時為了判斷程序是不是在工作,常用利用單片機(jī)系統(tǒng)的某一空閑引腳通過一個限流電阻接一個發(fā)光二極管,在程序中間隔固定時間交替控制發(fā)光管的明暗。實(shí)現(xiàn)這個功能只要在Config.h文件中定義TIMER_FLASHLED宏,如:
#defineTIMER_FLASHLEDP1_0
則當(dāng)時鐘中斷發(fā)生256次之后,改變發(fā)光管的狀態(tài)。

通訊模塊
串口資源做為單片機(jī)與外界通信的常用手段,通訊模塊提供了完全緩沖的串口通訊底層機(jī)制,適用于長度不大的數(shù)據(jù)包的發(fā)送及接收。如果處理關(guān)鍵數(shù)據(jù),需要用戶自己提供糾錯協(xié)議。
通訊模塊由聲明文件SComm.h及實(shí)現(xiàn)文件SComm.c組成。
初始化:調(diào)用函數(shù)InitSCommModule()來初始化通訊模塊:
voidInitSCommModule(BYTEbyTimerReload,BITbitTurbo)
參數(shù)說明:
byTimerReload:定時器1的重裝載初始值。
bitTurob:當(dāng)此參數(shù)為TRUE時,串行通訊在定時器1的溢出速率基礎(chǔ)上加倍。為FALSE時,串行通訊速率為定時器1的溢出速率。

緩沖區(qū):模塊使用了由宏SCOMM_SENDBUFSIZE、SCOMM_RECEBUFSIZE及SCOMM_PKGBUFSIZE所指定長度的三個緩沖區(qū),分別為發(fā)送、接收及數(shù)據(jù)包(用于處理接收到的數(shù)據(jù))緩沖區(qū)(如果沒有使用異步接收功能,則不需要使用數(shù)據(jù)包緩沖區(qū))。
在缺省時,這三個宏都被定義為10,但用戶可以自已按照系統(tǒng)的RAM資源占用情況在Config.h中重定義緩沖區(qū)的大小。需要注意的是,如果緩沖的長度不夠,當(dāng)發(fā)送或接收長數(shù)據(jù)包的時候可能會發(fā)生問題,關(guān)于數(shù)據(jù)緩沖區(qū)的最小值的設(shè)置可以參考下面的說明。
注意:需要盡快取出接收緩沖區(qū)中的數(shù)據(jù),否則當(dāng)緩沖區(qū)滿之后,新的數(shù)據(jù)將被簡單的丟掉。

字節(jié)級服務(wù)函數(shù):在Config.h文件中定義了宏SCOMM_DriverInterface(如:#defineSCOMM_DriverInterface),則可以使用字節(jié)級服務(wù)函數(shù),即通訊模塊的底層函數(shù)。
共有兩個函數(shù)可以使用:
voidSendByte(BYTEbyData);
發(fā)送一個字節(jié),如果當(dāng)前緩沖區(qū)滿,則等待。參數(shù)byData為要發(fā)送的數(shù)據(jù)。
BYTEReceByte();
接收一個字節(jié),如果當(dāng)前緩沖區(qū)中沒有數(shù)據(jù),則此函數(shù)阻塞,直到接收到數(shù)據(jù)為止。接收到數(shù)據(jù)通過返回值返回。
可以通過調(diào)用IsSendBufEmpty()IsSendBufFull()IsReceBufEmpty()IsReceBufFull()宏來判斷緩沖區(qū)的空或滿,以防系統(tǒng)阻塞。
不推薦直接使用這一級的服務(wù)函數(shù),應(yīng)該使用高層次上的服務(wù)函數(shù)或者在這一級服務(wù)函數(shù)的基礎(chǔ)上構(gòu)造自己的通訊函數(shù)。

數(shù)據(jù)包級服務(wù)函數(shù):在Config.h文件中定義宏SCOMM_PackageInterface(如:#defineSCOMM_PackageInterface)則可以使用數(shù)據(jù)包級服務(wù)函數(shù)。
共有兩個函數(shù)可以使用:
voidSendPackage(BYTE*pbyData,BYTEbyLen);
發(fā)送數(shù)據(jù)包,參數(shù)pbyData為將要發(fā)送的數(shù)據(jù)包緩沖區(qū)(數(shù)組)的指針,byLen為將要發(fā)送的數(shù)據(jù)包的長度。
當(dāng)沒有定義SCOMM_DriverInterface時,數(shù)據(jù)被完全緩沖。即不能夠發(fā)送長度超過發(fā)送緩沖區(qū)長度的數(shù)據(jù)包。當(dāng)定義了SCOMM_DriverInterface時,采用單字節(jié)發(fā)送,這時不限制需要發(fā)送的數(shù)據(jù)的長度。

BYTERecePackage(BYTE*pbyData,BYTEbyLen);
接收數(shù)據(jù)包,參數(shù)pbyData為存放將要接收的數(shù)據(jù)的緩沖區(qū),byLen為緩沖區(qū)長度。返回值為接收到的字節(jié)數(shù),當(dāng)模塊的接收緩沖區(qū)為空時,函數(shù)非阻塞,立即返回,返回值為零。

同步發(fā)送接收服務(wù)函數(shù):
比如在一個串行總線多機(jī)通訊系統(tǒng)中,主機(jī)需要定時循檢各從機(jī)的狀態(tài),往往是發(fā)一個包含從機(jī)地址及指令的數(shù)據(jù)包給從機(jī),之后等待一定的時間,從機(jī)需要在這段時間之內(nèi)給主機(jī)一個應(yīng)答,如果沒有這個應(yīng)答,則認(rèn)為從機(jī)工作狀態(tài)出錯,轉(zhuǎn)去進(jìn)行相應(yīng)的處理。在這個模型里,主機(jī)不能夠不進(jìn)行等待而給另一臺從機(jī)發(fā)送指令,也不能夠不管從機(jī)在很久沒有應(yīng)答的情況下繼續(xù)等待。還有一種情況,比如當(dāng)使用485總線進(jìn)行通信時,如果是兩條通訊線則系統(tǒng)只能工作在半雙工模式下,總線在同一時間內(nèi)只能工作在發(fā)送或接收,為了防止發(fā)送和接收相互干擾,這時的通訊常常需要使用同步發(fā)送和接收。
當(dāng)在Config.h文件中定義宏SCOMM_SyncInterface后,則可以使用通訊模塊提供同步發(fā)送接收函數(shù):
voidSendPackage(BYTE*pbyData,BYTEbyLen);
發(fā)送數(shù)據(jù)包,參數(shù)pbyData為將要改善的數(shù)據(jù)包的緩沖區(qū)指針,byLen為將要發(fā)送的數(shù)據(jù)包的長度。
這個函數(shù)可以保證等待一個完整的數(shù)據(jù)包完全發(fā)送出去之后,它才返回,在這段時間內(nèi),它會阻塞運(yùn)行。

BYTESyncRecePackage(BYTE*pbyBuf,BYTEbyBufLen,WORDwTimeout,BYTEbyParam);
接收數(shù)據(jù)包。返回值為接收到的數(shù)據(jù)包長度。參數(shù)pbyBuf為將要接收數(shù)據(jù)包的緩沖區(qū)的指針,byBufLen為提供的緩沖區(qū)的長度,wTimeout為通信超時值,如果在發(fā)生了由wTimeout所指定次數(shù)的時鐘中斷而還沒有接收到或沒有接收到完整的數(shù)據(jù)包時,函數(shù)返回零,最后一個參數(shù)byParam的含義見后面的解釋。

異步發(fā)送接收服務(wù)函數(shù):
在一個簡單的系統(tǒng)或多機(jī)通訊系統(tǒng)中的從機(jī)上,一般情況下不需要復(fù)雜的停等的工作模式,而且往往單片機(jī)需要對硬件進(jìn)行控制和檢測,不允許長時間的停下來檢測通訊,但又要求當(dāng)需要通訊時需要盡快的反應(yīng)速度,這時就需要使用異步發(fā)送和接收服務(wù)函數(shù)。
使用異步發(fā)送和接收服務(wù)函數(shù)需要在Config.h文件中定義SCOMM_AsyncInterface宏。
同樣提供兩個服務(wù)函數(shù):
voidSendPackage(BYTE*pbyData,BYTEbyLen);
發(fā)送數(shù)據(jù)包,參數(shù)pbyData為將要改善的數(shù)據(jù)包的緩沖區(qū)指針,byLen為將要發(fā)送的數(shù)據(jù)包的長度。
這里的函數(shù)的接口與同步發(fā)送和接收的服務(wù)函數(shù)相同。關(guān)于這里的細(xì)節(jié),見后面對同步和異步服務(wù)函數(shù)的說明。

voidAsyncRecePackage(BYTEbyParam);
接收數(shù)據(jù)包,參數(shù)byParam的意義見后面的描述。
使用異步通訊需要用戶定義一個回調(diào)函數(shù),原型如下:
voidOnRecePackage(BYTE*pbyData,BYTEbyBufLen);
當(dāng)異步接收服務(wù)函數(shù)接收到數(shù)據(jù)包之后,調(diào)用OnRecePackage回調(diào)函數(shù),在pbyData指定的緩沖區(qū)中存放數(shù)據(jù)包,byBufLen為數(shù)據(jù)包的長度。
在Config.h文件中定義宏SCOMM_TIMEOUT可以設(shè)定異步接收的超時值,當(dāng)開始接收數(shù)據(jù)包,但沒有收完數(shù)據(jù)而發(fā)生了SCOMM_TIMEOUT次時鐘中斷后,認(rèn)為接收超時,將已接收到的數(shù)據(jù)刪除。

同步和異步通訊服務(wù)函數(shù):
有些情況下,比如一個通訊系統(tǒng)中,由一臺計(jì)算機(jī)通過串口控制主機(jī),主機(jī)通過串口連接很多從機(jī),主機(jī)的串口采用分時復(fù)用,在這樣的模型中,主機(jī)和控制計(jì)算機(jī)之間的通訊可以使用,異步通訊方式,而主機(jī)與從機(jī)可以使用同步通訊方式。而同步和異步的發(fā)送函數(shù)接口是相同的,在這樣的情況下,發(fā)送都是同步的。在這樣的模型中,當(dāng)使用不同的接收函數(shù)之前,需要注意清除接收緩沖區(qū)中的內(nèi)容,通訊模塊提供函數(shù):ClearReceBuffer來做到這一點(diǎn),此函數(shù)原型如下:
voidClearReceBuffer();

通訊過程中,數(shù)據(jù)包往往是有固定的格式的,這種格式需要根據(jù)用戶所使用的協(xié)議的不同而不同。同步和異步接收服務(wù)函數(shù)支持從接收到的數(shù)據(jù)中識別出一定格式的數(shù)據(jù)包。
舉例說明:目前使用的協(xié)議決定數(shù)據(jù)包的格式為固定的包頭0xff,固定的長度4個字節(jié)。其它的細(xì)節(jié)在這里不重要,所以忽略掉。
為了能夠使用用SyncRecePackage或AsyncRecePackage函數(shù)從接收到的數(shù)據(jù)中識別出如上格式的數(shù)據(jù)包,有兩種方法:
第一種辦法是在Config.h文件中定義宏SCOMM_SimplePackageFormat,說明數(shù)據(jù)包為一種簡單格式,比如上面的協(xié)議。
之后還要定義兩個宏分別用來識別數(shù)據(jù)包頭和數(shù)據(jù)包尾,兩個宏分別是:
IsPackageHeader(x)和IsPackageTailer(x,y,z)
接收函數(shù)(SyncRecePackage和AsyncRecePackage)在沒有開始接收數(shù)據(jù)包(準(zhǔn)確的說是還沒有從接收到的數(shù)據(jù)包中找到包頭的時候),會對接收到的每一個字節(jié)的數(shù)據(jù)調(diào)用IsPackageHeader宏,將相應(yīng)的數(shù)據(jù)作為參數(shù),如果IsPackageHeader宏的結(jié)果為TRUE,則認(rèn)為找到了數(shù)據(jù)包頭,否則繼續(xù)對下一個字節(jié)進(jìn)行判斷。
上面的協(xié)議對應(yīng)的IsPackageHeader宏可以寫為:
#defineIsPackageHeader(x)((x)==0xff)
當(dāng)接收到包頭之后,接收函數(shù)會對接下來的每一個字節(jié)數(shù)據(jù)調(diào)用IsPackagTailer宏來判斷是不是已經(jīng)接收完數(shù)據(jù)包,三個參數(shù)分別為:
x:當(dāng)前判斷的數(shù)據(jù)。
y:從包頭開始到當(dāng)前被判斷的數(shù)據(jù)止的計(jì)數(shù)值,即當(dāng)前已經(jīng)接收到的字節(jié)數(shù)。
z:用戶在調(diào)用SyncRecePackage或AsyncRecePackage時指定的byParam參數(shù)。
與IsPackageHeader相似,如果宏IsPackageTailer的運(yùn)算結(jié)果為TRUE,則認(rèn)為接收到完整的數(shù)據(jù)包,則調(diào)用相應(yīng)的回調(diào)函數(shù)(對于異步接收函數(shù))或返回(對于同步接收函數(shù))。如果運(yùn)算結(jié)果為FALSE則繼續(xù)判斷下一個字節(jié)的數(shù)據(jù)。
上面的協(xié)議對應(yīng)的IsPackageTailer宏可以寫為:
#defineIsPackageTailer(x,y,z)((y)>=(z))
當(dāng)然,用戶也可以將IsPackageHeader和IsPackageTailer定義成為函數(shù),通過BIT類型的返回值來向調(diào)用者提供與相應(yīng)宏相同的信息。

另一種辦法需要在Config.h文件中定義宏SCOMM_ComplexPackageFormat。(需要注意的是,不能夠同時定義SCOMM_SimplePackageFormat和SCOMM_ComplexPackageFormat宏,否則會造成嚴(yán)重的不可預(yù)見性錯誤。
這時需要提供回調(diào)函數(shù)QueryPackageFormat,原形如下:
BYTEQueryPackageFormat(BYTEbyData,BYTEbyCount,BYTEbyParam);
函數(shù)中三個參數(shù)的含義與使用簡單數(shù)據(jù)包格式時判斷數(shù)據(jù)包尾的宏的參數(shù)相同。
函數(shù)通過返回值來通知作為調(diào)用者的接收函數(shù)對接收到的數(shù)據(jù)如何處理,但目前這種方法僅為需要處理復(fù)雜數(shù)據(jù)包格式時的一種可選方法,但不推薦。用戶如果想使用這種方法可以自己更改接收函數(shù)中相應(yīng)的
#ifdefSCOM_ComplexPackageFormat
#endif//SCOMM_ComplexPackageFormat
預(yù)編譯指令之間的內(nèi)容。
例如指定QueryPackageFormat的返回值的含義:
0:繼續(xù)找數(shù)據(jù)包頭或繼續(xù)找數(shù)據(jù)包尾。
1:找到數(shù)據(jù)包頭。
2:找到數(shù)據(jù)包尾。
3:數(shù)據(jù)包出錯,需要拋棄。
然后更改源代碼來實(shí)現(xiàn)上面的協(xié)議。

注意:當(dāng)用戶需要使用字符串的時候,可以利用簡單的包裝函數(shù)將字符串轉(zhuǎn)換為字節(jié)數(shù)組。所以沒有必要提供專用的字符串處理函數(shù)。

鍵盤掃描模塊
鍵盤掃描模塊有兩種工作方式,一種為自動的由時鐘模塊調(diào)用,另一種是由程序員自行調(diào)用。
1)由時鐘模塊自動調(diào)用的方式
將時鐘模塊實(shí)現(xiàn)文件(Timer.h)及鍵盤掃描模塊的實(shí)現(xiàn)文件(KBScan。c)包含進(jìn)工程,在Config.h文件中添加TIMER_KBSCANDELAY宏。時鐘模塊自動對時鐘中斷進(jìn)行計(jì)數(shù),當(dāng)達(dá)到TIMER_KBSCANDELAY宏所定義的值后,自動調(diào)用鍵盤掃描模塊中的函數(shù)KBScanProcess()進(jìn)行鍵盤掃描,也就是說,這個宏的值可以決定按鍵消抖動的時間。
用戶應(yīng)該提供兩個回調(diào)函數(shù)OnKBScan()及onKeysPressed()。在函數(shù)OnKBScan中進(jìn)行鍵盤掃描,并返回掃描碼。掃描碼的類型缺省為BYTE,當(dāng)鍵盤規(guī)模較大時,BYTE不能夠完全包含鍵盤信息時,可在Config.h文件中重定義宏KBVALUE,如下:
#defineKBVALUEWORD
這樣,就可以使用16位的鍵盤掃描碼,如果此時還達(dá)不到要求,可以將鍵盤掃描碼定義成一個結(jié)構(gòu),但這樣做將會增加代碼量及消耗更多的RAM資源,故不推薦。
掃描模塊調(diào)用OnKBScan取得掃描碼,并調(diào)用用戶可以重定義的宏IsNoKeyPressed來判斷是否有鍵按下,缺省的IsNoKeyPressed實(shí)現(xiàn)如下:
#defineIsNoKeyPressed(x)((x)==0x00)
即認(rèn)為OnKBScan返回0掃描碼時為沒有鍵按下,如果掃描函數(shù)返回其它非零掃描碼做為無鍵按下的掃描碼時,可以在Config.h文件中重定義IsNoKeyPressed宏的實(shí)現(xiàn)。
8位鍵盤掃描碼(缺省值)時,相應(yīng)的掃描函數(shù)為:
BYTEOnKBScan()
當(dāng)掃描模塊經(jīng)過軟件消抖動之后,發(fā)現(xiàn)有鍵按下,就會調(diào)用另一個回調(diào)函數(shù)onKeysPressed。函數(shù)的聲明應(yīng)該如下:
voidonKeyPressed(BYTEbyKBValue,BYTEbyState)
其中中的參數(shù)byKBValue的類型為BYTE,此為缺省值,如果使用其它類型的掃描碼,就將此參數(shù)變?yōu)橄鄳?yīng)類型。這個值由OnKBScan返回。另一個參數(shù)byState在通常情況下為零。但當(dāng)用戶在Config.h中定義宏KBSCAN_BRUSTCOUNT,同時鍵盤上的某鍵被按住不放時,掃描模塊對它自己的調(diào)用(注意這里和TIMER_KBSCANDELAY宏不同,TIMER_KBSCANDELAY是時鐘中斷足夠的次數(shù)后調(diào)用掃描模塊,而KBSCAN_BRUSHCOUNT為掃描模塊自身的被調(diào)用次數(shù))進(jìn)行計(jì)數(shù),當(dāng)達(dá)到KBSCAN_BRUSTCOUNT時,掃描模塊調(diào)用onKeysPressed,此時第一個參數(shù)的含義不變,而byState變成1,同時計(jì)數(shù)器復(fù)位,又經(jīng)過一段時間后,用值為3的byState調(diào)用onKeysPressed。這樣就可以很方便的實(shí)現(xiàn)多功能鍵或者檢測某鍵的長時間被按下。
2)由用戶自行調(diào)用
由用戶自行在程序中調(diào)用掃描模塊,而不是由時鐘中斷自行調(diào)用。其它與方式1相同。

注意:
1)函數(shù)KBScanProcess為非阻塞函數(shù),它將在很快的時間內(nèi)返回,等待再次分配給它執(zhí)行的機(jī)會。
2)函數(shù)KBScanProcess是在時鐘中斷外部運(yùn)行的,它的過程可以被任何中斷打斷,但不影響系統(tǒng)運(yùn)行。
3)byState的最大值為250,之后被復(fù)位為零。

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

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉