<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 牛人業(yè)話(huà) > 嵌入式里的“延遲”

嵌入式里的“延遲”

作者:jobs 時(shí)間:2015-05-27 來(lái)源:電子產(chǎn)品世界 收藏

  前些天在版主群里有人問(wèn)“有沒(méi)有好用的延遲函數啊?”我的第一反應就是“延遲函數要視自己的應用而編寫(xiě),不可能千篇一律的應用。”可是回首一看,單片機的發(fā)展歷程,在不同時(shí)期里有著(zhù)不一樣的延遲函數。

本文引用地址:http://dyxdggzs.com/article/274824.htm

  在版主上學(xué)的年代里,單片機課程老師對匯編語(yǔ)言有著(zhù)非常深入的了解,如XX指令是單指令周期,XX指令是雙指令周期。如果使用了編程,也要仔細看生成的匯編代碼然后再調節。例如下面的代碼示例:

  功能 延時(shí)(12M 24M)

  誤差 Ms S 5% 10Us 8%-80%

  //24M晶振 延時(shí) n毫秒

  void DelayMs_24M(unsigned int n)

  {

  unsigned int i=0,j=0;

  for(i=0;i

  for(j=0;j<357;j++);

  }

  延遲函數是通過(guò)的兩個(gè)循環(huán)計算而形成的停機等待而達到延遲的目的。代碼是通過(guò)查看由生成的匯編代碼指令——那個(gè)357便是由此計算出來(lái)的。當然,延遲函數是否精準也完全取決于那個(gè)357數字的選擇了。

  單周期指令,雙周期指令,數一數便可以了?其實(shí)查看匯編代碼沒(méi)有這么簡(jiǎn)單的,畢竟For循環(huán)也需要系統開(kāi)銷(xiāo)的,還有其它比較,判斷指令什么的。但這一切在IAR for AVR編譯環(huán)境里似乎就簡(jiǎn)單多了。

  在IAR for AVR編譯環(huán)境里,用戶(hù)只需要 #include "intrinsics.h"便可以調用void __delay_cycles(unsigned long);函數,這個(gè)函數是系統函數,其代表著(zhù)一個(gè)機器周期。用戶(hù)不再需要計算匯編語(yǔ)言的指令周期,不必再細讀單片機的操作手冊,強大的IAR編譯環(huán)境自己就算好了——單片機發(fā)展到IAR for AVR時(shí)代,也基本代表著(zhù)匯編退居二線(xiàn)。由于篇幅的原因,版主就不再這里為大家帖出代碼示例了。

  在A(yíng)tmel的8位單片機AVR系列一統天下的時(shí)候,ARM內核為代表的單片機在悄然崛起。不知不覺(jué),以ST公司stm32f103為代表的32位Cortex-M3內核的單片機占據了市場(chǎng)大部分分額,各大論壇爭先推出STM32版塊。

  其中,某位牛人推出的使用systick函數來(lái)完成延遲函數頗具人氣。我們來(lái)看一下源代碼:

  //初始化延遲函數

  void delay_init(u8 SYSCLK)

  {

  SysTick->CTRL&=0xfffffffb;//選擇內部時(shí)鐘 HCLK/8

  fac_us=SYSCLK/8;

  fac_ms=(u16)fac_us*1000;

  }

  void delay_ms(u16 nms)

  {

  SysTick->LOAD=(u32)nms*fac_ms; //時(shí)間加載

  SysTick->CTRL|=0x01; //開(kāi)始倒數

  while(!(SysTick->CTRL&(1<<16))); //等待時(shí)間到達

  SysTick->CTRL&=0XFFFFFFFE; //關(guān)閉計數器

  SysTick->VAL=0X00000000; //清空計數器

  }

  牛人的代碼還是非常簡(jiǎn)潔的,使用起來(lái)也方便,首先調用delay_init函數,然后,再調用delay_ms()函數。這個(gè)延遲函數也是非常準確的,因為其使用了單片機的硬件定時(shí)器模塊。在STM32F103高達72MHz的主頻,優(yōu)化的指令集系統下,系統的開(kāi)銷(xiāo)完成可以忽略。筆者也將其成功應用于單總線(xiàn)通訊方式的數字溫度采集傳感器18B20芯片上,測試良好。

  寫(xiě)到這里,筆者已經(jīng)介紹了三種延遲函數,它們三個(gè)都有一個(gè)共同的特點(diǎn):阻塞延遲函數——在“等待”延遲函數到來(lái)的時(shí)候里,單片機并沒(méi)有處理其它有用,有意義的事情,而是停機在等待著(zhù)時(shí)間的到來(lái)。對于我們要處理大量數據的單片機系統來(lái)說(shuō),這個(gè)劣勢有時(shí)就很難接受的。那么我們要怎么解決呢?

  我們仍然以STM32F103為例,仍然要使用強大的定時(shí)器,這里我們再次選用systick定時(shí)器。我們首先要初始化ST單片機systick,其每1ms進(jìn)入中斷一次,代碼如下:

  if (SysTick_Config(72000)) //參數為系統時(shí)鐘的向上溢出值,此配置為72000,即1ms中斷一次

  {

  /* Capture error */

  while (1);

  }

  之后,我們在systick的中斷函數里計數,示例代碼如下:

  void SysTick_Handler(void)

  {

  if(gCntLed[0] > 0)

  {

  gCntLed[0]--;

  }

  else

  {

  gCntLed[0] = 0;

  }

  }

  從上面代碼可以清楚看到,每1ms,gCntLed[0]將計數值減1,直到為0時(shí)止。而main函數里,就要不斷的查詢(xún)這個(gè)gCntLed[0]的值,當未達到0值時(shí),就去做別的事情,而查詢(xún)到0值時(shí),再去處理自己的事情,示例代碼如下:

  while(1)

  {

  if(gCntLed[0] == 0)

  {

  LedToggle(0);

  gCntLed[0] = 200;

  }

  KeyScan();

  }

  通過(guò)未阻塞的延遲函數,我們實(shí)現了LED燈每隔200ms閃爍一次的效果,與其同時(shí),我們也沒(méi)有停止不斷掃描按鍵。——這就是非阻塞延遲函數的強大優(yōu)勢。非阻塞式延遲函數還主要應用于操作系統函數里,喜歡的網(wǎng)友可以自己查看相關(guān)函數。

  隨著(zhù)時(shí)代的進(jìn)步,能源的問(wèn)題逐漸突出出來(lái)。剛剛筆者介紹的幾種函數都是在不停的“運行”,看似什么事情也沒(méi)有做,但是單片機確實(shí)在全力的“奔跑”,這與當前節碳減排,低功耗格格不入。MSP430算得上是低功耗的代表了,其延遲函數可以拿來(lái)借鑒一下。

  在MSP430的低功耗設計中,阻塞式延遲函數是基本不用的——因為功耗太大,未阻塞式延遲函數是必備條件。設計主要思想是,定時(shí)讓MSP430從睡眠模式里“醒”過(guò)來(lái),查看一下當前的時(shí)間與狀態(tài),然后再做決定如何處理。換句話(huà)說(shuō),上面的示例就變成了,MSP430每1ms準時(shí)醒來(lái)一次,處理了一下gCntLed[0]的值,然后又查看了一下,如果非0值,則繼續“睡”去了;如果恰好是0值,則再干一會(huì )兒事情……這里,MSP430大部分時(shí)間里就處于了低功耗的睡眠模式,自然也就節能了。

  又到總結的時(shí)候了,幾種延遲函數各有特點(diǎn)與應用場(chǎng)景,各位親愛(ài)的網(wǎng)友們根據自己的需求來(lái)自行選擇吧!當然,也可以來(lái)論壇的ARM版塊發(fā)帖求助,版主也會(huì )傾力奉獻的。

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
塵埃粒子計數器相關(guān)文章:塵埃粒子計數器原理
晶振相關(guān)文章:晶振原理


關(guān)鍵詞: 嵌入式 C語(yǔ)言

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>