2015-10-04 35 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)

如果你想要准确的延迟,你需要使用定时器来实现它们...