在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<abbr id="27omo"></abbr>

<menu id="27omo"><dl id="27omo"></dl></menu>
    • <label id="27omo"><tt id="27omo"></tt></label>

      新聞中心

      EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > avr-gcc中關(guān)于delay延時函數(shù)的應(yīng)用修改版

      avr-gcc中關(guān)于delay延時函數(shù)的應(yīng)用修改版

      作者: 時間:2016-11-23 來源:網(wǎng)絡(luò) 收藏
      在51中我們的延時函數(shù)都是自己編寫的,無論是在匯編中還是在C言語中。雖然有模板,有時還是有點煩。呵呵。不過在應(yīng)用avr 單片機(jī)的時候我們就有福了。因為avr-gcc 提供給我們很方便的delay 延時函數(shù), 只有在源文件包含:

      #i nclude
      就可以使用了。這個頭文件定義了兩個級別的延時函數(shù)分別是:
      void_delay_us (double __us) ;//微秒級
      void_delay_ms (double __ms);//毫秒級

      不過不可以高興的太早,因為要在你的avr-gcc中正確使用它們是有條件的,下面我將慢慢道來。

      這個參數(shù)和 Makefile 中的 F_CPU 值有關(guān),Makefile 所定義的的F_CPU 變量的值會傳遞給編譯器。你如果用AVR_studio 4.1X來編輯和調(diào)試,用內(nèi)嵌AVR-GCC的進(jìn)行編譯,并且讓AVR_studio 幫你自動生成Makefile 的話,那你可以在:
      Project -> Configuration Options -> Gerneral -> Frequency 如下圖:

      本文引用地址:http://www.biyoush.com/article/201611/320151.htm

      寫下你的F_CPU的值,F(xiàn)_CPU這個值表示你的AVR單片機(jī)的工作頻率。單位是 Hz ,不是 MHZ,不要寫錯。如 7.3728M 則 F_CPU = 7372800
      你會發(fā)現(xiàn)在"delay.h" 頭文件中有這個樣的一個定義如下:
      #ifndef F_CPU
      # warning "F_CPU not defined for "
      # define F_CPU 1000000UL// 1MHz
      #endif

      這是為了在你沒有定義F_CPU這個變量(包括空),或是AVR_studio Frequency沒有給值的時候,提供一個默認(rèn)的 1MHz頻率值。讓編譯器編譯時不至于出錯。

      下面是這兩個函數(shù)的實體:
      void _delay_us(double __us)//微秒
      {
      uint8_t __ticks;
      double __tmp = ((F_CPU) / 3e6) * __us; // 3e6 是因為調(diào)用的_delay_loop_1()是三條指令的
      if (__tmp < 1.0)
      __ticks = 1;
      else if (__tmp > 255)
      __ticks = 0;
      else
      __ticks = (uint8_t)__tmp;
      _delay_loop_1(__ticks);
      }

      void _delay_ms(double __ms) // 毫秒
      {
      uint16_t __ticks;
      double __tmp = ((F_CPU) / 4e3) * __ms;// 4e3 是因為調(diào)用的_delay_loop_2()是四條指令的

      if (__tmp < 1.0)
      __ticks = 1;
      else if (__tmp > 65535)
      __ticks = 0;
      else
      __ticks = (uint16_t)__tmp;
      _delay_loop_2(__ticks);
      }

      你會發(fā)現(xiàn)他們都分別調(diào)用了_delay_loop_1(); 和_delay_loop_2(); 這兩個函數(shù)
      而這兩個函數(shù)又如下所示:
      void_delay_loop_1(uint8_t __count)
      {
      __asm__ volatile (
      "1: dec %0" ""
      "brne 1b"
      : "=r" (__count)
      : "0" (__count)
      );
      }
      從其函數(shù)注釋里面可以了解到,該函數(shù)用來延遲3個晶振時鐘周期,不包括程序調(diào)用和退出該函數(shù)所花費(fèi)的時間。該函數(shù)的形參__count是一個8位的變量,由此,我們就可以根據(jù)系統(tǒng)采用的晶振頻率算出該函數(shù)最大的延遲時間了:
      1MHz時:MAX_DELAY_TIME=(1/1000000)*3*256=0.000768S=768uS
      8MHz時:MAX_DELAY_TIME=(1/8000000)*3*256=0.000096S=96uS
      ............
      F_CPUMAX_DELAY_TIME=(1/F_CPU)*3*256
      依此類推。
      void_delay_loop_2(uint16_t __count)
      {
      __asm__ volatile (
      "1: sbiw %0,1" ""
      "brne 1b"
      : "=w" (__count)
      : "0" (__count)
      );
      }
      該函數(shù)延時4個晶振周期,形參是一個16位的變量,同樣我們也可以算出該函數(shù)最大的延遲時間:
      1MHz時:MAX_DELAY_TIME=(1/1000000)*4*65535=0.26214S=262.1mS
      8MHz時:MAX_DELAY_TIME=(1/8000000)*4*65535=0.03277S=32.8mS
      ............
      F_CPUMAX_DELAY_TIME=(1/F_CPU)*4*65535
      依此類推。
      重要提示:_delay_loop_1(0)、_delay_loop_1(256)延時是一樣的??!
      同理,_delay_loop_2(0)、_delay_loop_2(65536)延時也是一樣的?。∵@些函數(shù)的延時都是最長的延時。



      這兩個函數(shù)都是avr-gcc 的 inline匯編格式寫的,具體的語法規(guī)則我就不多說了??梢詤⒖糰vr-libc。不過這兩個函數(shù)很簡單,很容易明白。一個是字節(jié)遞減,一個是字遞減。如果你認(rèn)真看上面幾個函數(shù),你就會發(fā)現(xiàn)要正確使用它們是有如下條件的:
      1. 首先,你要正確定義你的 F_CPU 的值,也就是你的AVR單片機(jī)實際的頻率。否則延時不準(zhǔn)。(延時只在數(shù)字上不準(zhǔn)確,具體可以計算)
      2. 你在編譯時一定要打開優(yōu)化,Makefile中OPT 不要選 0 ,如果AVR_studio 不要選O0 。
      3. 你在使用這兩個delay()時,傳遞給兩個函數(shù)的實參要使用常量,不要使用變量。
      4. 設(shè)置的時間參數(shù)__ms , __us 是有范圍的,不要超過范圍。__ms:1 - [262.14 ms / (F_CPU/1e6) ],__us:1- [768 us / (F_CPU/1e6)] 。 [...]表取整數(shù)部分.(此處結(jié)論錯誤?)。
      __us的最大值應(yīng)該是768us(1M頻率下)MAX_VALUE=256*3/F_CPU s,最小值3個時鐘周期MIN_VALUE=1*3/F_CPU s;
      ,__ms最大值MAX_VALUE=65536*4/F_CPU s,MIN_VALUE=1*4/F_CPU s;


      只有具備了上面的條件你才可以正確使用延時函數(shù) _delay_us () 和 _delay_ms () 。對于第三個條件,為什么要選用常量,還有第二個條件為什么要打開優(yōu)化選項。這是為了讓編譯器在編譯的時候就把延時的值計算好,而不是把它編譯到程序中,在運(yùn)行時才進(jìn)行計算,那樣的話,一是會增加代碼的長度,還會使你的延時程序的延時時間加長,或是變得不可預(yù)料。產(chǎn)生時序的錯誤。
      在08版本中已經(jīng)修改,具體函數(shù)如下:
      void
      _delay_us(double __us)
      {
      uint8_t __ticks;
      double __tmp = ((F_CPU) / 3e6) * __us;
      if (__tmp < 1.0)
      __ticks = 1;
      else if (__tmp > 255)
      {
      _delay_ms(__us / 1000.0);
      return;
      }
      else
      __ticks = (uint8_t)__tmp;
      _delay_loop_1(__ticks);
      }
      當(dāng)__us過大的時候,就會調(diào)用_delay_ms();由上面可以知道8M時候_delay_ms最小可以延時4/8000000=0.5us 1M時,最小延時4/1000000=4us,可以連接上。
      void
      _delay_ms(double __ms)
      {
      uint16_t __ticks;
      double __tmp = ((F_CPU) / 4e3) * __ms;
      if (__tmp < 1.0)
      __ticks = 1;
      else if (__tmp > 65535)
      {
      //__ticks = requested delay in 1/10 ms
      __ticks = (uint16_t) (__ms * 10.0);
      while(__ticks)
      {
      // wait 1/10 ms
      _delay_loop_2(((F_CPU) / 4e3) / 10);
      __ticks --;
      }
      return;
      }
      else
      __ticks = (uint16_t)__tmp;
      _delay_loop_2(__ticks);
      }
      當(dāng)__ms過大時,只采用__ticks --的方式延時。先延時一個262ms(1M,32ms 8M),然后用遞減方式。


      關(guān)鍵詞: avr-gccdelay延時函

      評論


      相關(guān)推薦

      技術(shù)專區(qū)

      關(guān)閉