2015-10-04 84 views
0

我和我的朋友正在開發一個涉及編程attiny48的項目。 我們正在編碼Atmel Studio 6.2。AVR C函數從Main函數工作,但不從其他函數

爲了讓我們在C語言和嵌入式編程方面有所收穫,我們試圖製作一個LED閃光燈。下面是代碼,我們到目前爲止有:

User.h

ifndef USER_H_ 
#define USER_H_ 

#include <avr/io.h> 

// # Defines 

#define F_CPU 1000000UL 

// Function Prototypes 
extern void Delay_Ms(uint16_t ms); 
extern void Init(void); 

extern uint8_t Check_Infrared(void); 
extern void Toggle_PC0 (void); 
#endif /* USER_H_ */ 

user.c的

#include <avr/io.h> 
#include <delay.h> 
#include "User.h" 

void Delay_Ms(uint16_t ms) 
{ 
    uint32_t Delay_Cycles; 


    for (Delay_Cycles = (ms * (F_CPU/10000)) ; Delay_Cycles > 0 ; Delay_Cycles--); 
} 

void Init(void) 
{ 
    // Define Output Pins 
    DDRC = DDRC |(1<<DDC0); // PC0 is digital output 

    while(1) 
    { 
     PINC = (1<<PINC0); // Toggle PC0, This is the LED we have connected 
     //_delay_ms(1000); This is the builtin Delay which works here 
     Delay_Ms(1000); //we have established that this fails 
    } 
} 

MAIN.C

#include <avr/io.h> 
#include "User.h" 

int main(void) 
{ 
    Init(); 
    while(1) 
    { 
     PINC = (1<<PINC0); // Toggle PC0 
     Delay_Ms(1000); //if we let it get here, it works! 
    } 
} 

小號o發生了什麼事情是:main()調用函數Init(),在那裏我們複製了應該使LED閃爍的while循環。在這裏,它不起作用。 如果我們註釋掉Init()函數中的while(1)循環,則main()中的while(1)循環會運行並且LED會閃爍。

我們玩過代碼,並確定Delay_Ms(ms)在從main()調用時起作用,但在從Init()調用時不起作用。我們懷疑這與定義,defs,include或頭文件的順序有關,但作爲缺乏經驗的C程序員,我們有點失落。

我們可以使用內置的延遲功能,但這個問題可能會在其他地方出現,在未來!

任何提示讚賞!

+0

當控制傳遞給init()時,它會運行自己的while循環,因爲它將它放入一個無止境的循環中。嘗試從那裏刪除。把它的內容放在外面。 – SanVed

回答

1

您的Delay_Ms()函數無法按照您期望的方式工作。如果優化未啓用,則內部循環會編譯爲大約20條指令,因此它的運行速度會比預期慢很多。但是,如果啓用優化,整個循環都會被優化,導致延遲完全消失。 (整個函數實際上只是最終編譯成單一的ret指令!)

使用內建的_delay_ms();它的校準正確,並且在優化下不會消失。

+0

+1。我正要發佈這個,你可以從生成的程序集中看到它完全消失。在for循環中簡單地使用__asm __(「nop」);'''可以停止優化,但是時序仍然不夠精確。雖然我不確定它是如何從'''main()'''工作的。 –

+0

困擾我的問題是爲什麼它在main中工作,但不是在重構到另一個文件時。我的教育猜測是,也許編譯器能夠在Delay_Ms()從相同的文件(在User.c中)調用時優化它,但是當它跨文件調用時(來自main.c),編譯器不知道優化它。 (它需要生成鏈接器鏈接到一起的引用)。 –

+0

插入'nop'最終解決了問題。 無論如何,我們打算使用內置延遲,我們現在只是想知道發生了什麼問題比晚些時候將我們的頭撞到牆上更好!非常感謝 – flyingsilverfin

0

我可以建議這種方法嗎?

void Delay_Ms(uint16_t ms) 
{ 
    while(ms--){ 
     _delay_ms(1);//built in util/delay.h 
    } 
} 

它會失去對時間精度的一些(也許爲1us每毫秒),但這樣一來,你可以使用帶有更大值的延遲(我懷疑你意識到你不能直接_delay_ms)

如果你想要準確的延遲,你需要使用定時器來實現它們...