新聞中心

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

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

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

sp;
不過(guò)不可以高興的太早,因?yàn)橐谀愕腶vr-gcc中正確使用它們是有條件的,下面我將慢慢道來(lái)。

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

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

void _delay_ms(double __ms)// 毫秒板,有時(shí)還是有點(diǎn)煩。呵呵。不過(guò)在應(yīng)用av
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms; // 4e3 是因?yàn)檎{(diào)用的_delay_loop_2()是四條指令的&nb

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

板,有時(shí)還是有點(diǎn)煩。呵呵。不過(guò)在應(yīng)用av
這兩個(gè)函數(shù)都是avr-gcc 的 inline匯編格式寫的,具體的語(yǔ)法規(guī)則我就不多說(shuō)了??梢詤⒖糰vr-libc。不過(guò)這兩個(gè)函數(shù)很簡(jiǎn)單,很容易明白。一個(gè)是字節(jié)遞減,一個(gè)是字遞減。如果你認(rèn)真看上面幾個(gè)函數(shù),你就會(huì)發(fā)現(xiàn)要正確使用它們是有如下條件的:
1. 首先,你要正確定義你的 F_CPU 的值,也就是你的AVR單片機(jī)實(shí)際的頻率。否則延時(shí)不準(zhǔn)。
2. 你在編譯時(shí)一定要打開優(yōu)化,Makefile中OPT 不要選 0 ,如果AVR_studio 不要選O0 。
&nb
3. 你在使用這兩個(gè)delay()時(shí),傳遞給兩個(gè)函數(shù)的實(shí)參要使用常量,不要使用變量。
4. 設(shè)置的時(shí)間參數(shù)__ms , __us 是有范圍的,不要超過(guò)范圍。__ms:1 - [262.14 ms / (F_CPU/1e6) ], __us:1- [768 us / (F_CPU/1e6)] 。 [...] 表取整數(shù)部分.

sp;
對(duì)于第4條范圍,來(lái)個(gè)例子:
如果F_CPU = 7372800,則__ms范圍:1 - 35 ,而__us范圍:1 - 104 。

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

發(fā)現(xiàn)一寫就寫了兩個(gè)多小時(shí),看起來(lái)不長(zhǎng)??磥?lái)說(shuō)出來(lái)很容易,寫下來(lái)還是要費(fèi)點(diǎn)工夫的,希望對(duì)你的有所幫助。呵呵。分享快樂(lè),共同進(jìn)步。



關(guān)鍵詞: avrgccdelay延時(shí)函

評(píng)論


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

關(guān)閉