新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > avr-gcc中關于delay延時函數的應用

        avr-gcc中關于delay延時函數的應用

        作者: 時間:2016-11-24 來源:網絡 收藏
        在51中我們的延時函數都是自己編寫的,無論是在匯編中還是在C言語中。雖然有模板,有時還是有點煩。呵呵。不過在應用avr單片機的時候我們就有福了。因為avr-gcc 提供給我們很方便的delay 延時函數, 只有在源文件包含:
        #i nclude
        就可以使用了。這個頭文件定義了兩個級別的延時函數分別是:
        ; 在51中我們的延時函數都是自己編寫的
        void _delay_us (double __us) ;//微秒級
        void _delay_ms (double __ms);//毫秒級

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

        這個參數和 Makefile 中的 F_CPU 值有關,Makefile 所定義的的F_CPU 變量的值會傳遞給編譯器。你如果用AVR_studio 4.1X來編輯和調試,用內嵌AVR-GCC的進行編譯,并且讓AVR_studio 幫你自動生成Makefile 的話,那你可以在:
        ,無論是在匯編中還是在C言語中。雖然有模
        Project -> Configuration Options -> Gerneral -> Frequency如下圖:
        ; 在51中我們的延時函數都是自己編寫的
        寫下你的F_CPU的值,F_CPU這個值表示你的AVR單片機的工作頻率。單位是 Hz ,不是 MHZ,不要寫錯。如 7.3728M則 F_CPU = 7372800 。
        你會發現在"delay.h" 頭文件中有這個樣的一個定義如下:
        #ifndef F_CPU; 在51中我們的延時函數都是自己編寫的
        # warning "F_CPU not defined for "
        # define F_CPU 1000000UL// 1MHz
        #endif
        板,有時還是有點煩。呵呵。不過在應用av
        這是為了在你沒有定義F_CPU這個變量(包括空),或是AVR_studio Frequency沒有給值的時候,提供一個默認的 1MHz頻率值。讓編譯器編譯時不至于出錯。

        sp;
        下面是這兩個函數的實體:
        void _delay_us(double __us)// 微秒
        {; 在51中我們的延時函數都是自己編寫的
        uint8_t __ticks;
        double __tmp = ((F_CPU) / 3e6) * __us;// 3e6 是因為調用的_delay_loop_1()是三條指令的
        if (__tmp < 1.0)&nb
        __ticks = 1;
        else if (__tmp > 255)
        __ticks = 0;; 在51中我們的延時函數都是自己編寫的
        else
        __ticks = (uint8_t)__tmp;
        _delay_loop_1(__ticks);,無論是在匯編中還是在C言語中。雖然有模
        }

        void _delay_ms(double __ms)// 毫秒板,有時還是有點煩。呵呵。不過在應用av
        {
        uint16_t __ticks;
        double __tmp = ((F_CPU) / 4e3) * __ms; // 4e3 是因為調用的_delay_loop_2()是四條指令的&nb

        if (__tmp < 1.0)
        __ticks = 1;,無論是在匯編中還是在C言語中。雖然有模
        else if (__tmp > 65535)
        __ticks = 0;
        else; 在51中我們的延時函數都是自己編寫的
        __ticks = (uint16_t)__tmp;
        _delay_loop_2(__ticks);
        }
        ,無論是在匯編中還是在C言語中。雖然有模
        你會發現他們都分別調用了_delay_loop_1(); 和_delay_loop_2(); 這兩個函數
        而這兩個函數又如下所示:
        void _delay_loop_1(uint8_t __count)板,有時還是有點煩。呵呵。不過在應用av
        {
        __asm__ volatile (
        "1: dec %0" "",無論是在匯編中還是在C言語中。雖然有模
        "brne 1b"
        : "=r" (__count)
        : "0" (__count)sp;
        );
        }
        void _delay_loop_2(uint16_t __count),無論是在匯編中還是在C言語中。雖然有模
        {
        __asm__ volatile (
        "1: sbiw %0,1" ""&nb
        "brne 1b"
        : "=w" (__count)
        : "0" (__count)sp;
        );
        }

        板,有時還是有點煩。呵呵。不過在應用av
        這兩個函數都是avr-gcc 的 inline匯編格式寫的,具體的語法規則我就不多說了。可以參考avr-libc。不過這兩個函數很簡單,很容易明白。一個是字節遞減,一個是字遞減。如果你認真看上面幾個函數,你就會發現要正確使用它們是有如下條件的:
        1. 首先,你要正確定義你的 F_CPU 的值,也就是你的AVR單片機實際的頻率。否則延時不準。
        2. 你在編譯時一定要打開優化,Makefile中OPT 不要選 0 ,如果AVR_studio 不要選O0 。
        &nb
        3. 你在使用這兩個delay()時,傳遞給兩個函數的實參要使用常量,不要使用變量。
        4. 設置的時間參數__ms , __us 是有范圍的,不要超過范圍。__ms:1 - [262.14 ms / (F_CPU/1e6) ], __us:1- [768 us / (F_CPU/1e6)] 。 [...] 表取整數部分.

        sp;
        對于第4條范圍,來個例子:
        如果F_CPU = 7372800,則__ms范圍:1 - 35 ,而__us范圍:1 - 104 。

        sp;
        只有具備了上面的條件你才可以正確使用延時函數 _delay_us () 和 _delay_ms () 。對于第三個條件,為什么要選用常量,還有第二個條件為什么要打開優化選項。這是為了讓編譯器在編譯的時候就把延時的值計算好,而不是把它編譯到程序中,在運行時才進行計算,那樣的話,一是會增加代碼的長度,還會使你的延時程序的延時時間加長,或是變得不可預料。產生時序的錯誤。

        發現一寫就寫了兩個多小時,看起來不長。看來說出來很容易,寫下來還是要費點工夫的,希望對你的有所幫助。呵呵。分享快樂,共同進步。



        關鍵詞: avrgccdelay延時函

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 佛学| 日喀则市| 水城县| 五寨县| 望都县| 重庆市| 新宁县| 东乡族自治县| 昔阳县| 明水县| 乌兰察布市| 西昌市| 阿勒泰市| 大田县| 永嘉县| 巴林右旗| 双城市| 阿城市| 平顺县| 赤水市| 徐闻县| 乐清市| 营口市| 南郑县| 西平县| 邹平县| 西青区| 东源县| 安国市| 宾阳县| 台湾省| 安福县| 洞口县| 二连浩特市| 筠连县| 桑日县| 美姑县| 柞水县| 哈巴河县| 台中县| 墨玉县|