My friend and I are working on a project which involves programming an attiny48. We're coding in Atmel Studio 6.2.
Just to get our feet wet in C and embedded programming we're trying to make an LED flash. Here is the code we have so far:
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!
}
}
So what's happening is: The main() calls the function Init(), where we have copied the while loop that is supposed to flash the LED. Here, it does NOT work. If we comment out the while(1) loop in the Init() function, the while(1) loop that is in the main() runs and the LED flashes.
We've played with the code and established that the Delay_Ms(ms) works when called from the main(), but not when called from the Init(). We suspect that this has something to do with the order of definition, defs, the includes or the header files, but as inexperienced C programmers we are a little lost.
We could just use the built in delay function but then this problem may come up elsewhere, in the future!
Any tips appreciated!
Your Delay_Ms()
function will not work the way you expect it to. If optimizations are not enabled, the inner loop compiles to about 20 instructions, so it will run considerably slower than expected. If optimizations are enabled, though, the entire loop is optimized away, causing the delay to disappear entirely. (The whole function literally just ends up compiling to a single ret
instruction!)
Use the builtin _delay_ms()
; it's calibrated correctly, and will not disappear under optimization.