2
\$\begingroup\$

I'm following a basic tutorial for AVR.

All seems fine but the speed? The problem is that if I leave the speed of the xtal commented the code works, but if I place it in 8 MHz or 16 MHhz [I'm using an Arduino board with a 328p], the led stays on a long time and unresponsive, so why if I leave the speed commented it works?

I checked the speed in the fuses and change it to 8 internal, 16 MHz external and same problem, what is this noob trap?

Here the code from link:

//#define F_CPU 16000000UL         /* 8MHz crystal oscillator */

    #define BUTTON_PORT PORTB       /* PORTx - register for button output?? PULL UP? */
    #define BUTTON_PIN PINB         /* PINx - register for button input */
    #define BUTTON_BIT PB3          /* bit for button input/output */

    #define LED_PORT PORTD          /* PORTx - register for LED output */
    #define LED_BIT PD4             /* bit for button input/output */
    #define LED_DDR DDRD            /* LED data direction register */

    #define DEBOUNCE_TIME 25        /* time to wait while "de-bouncing" button */
    #define LOCK_INPUT_TIME 250     /* time to wait after a button press */



#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>

/* function prototypes */

void delay_ms(uint16_t ms);
void init_io();
int button_is_pressed();
void toggle_led();

int main(void)
{

    init_io();

    while(1)
    {
        if (button_is_pressed())
        {
            toggle_led();
            _delay_ms(LOCK_INPUT_TIME);
        }
    }
}

void init_io()
{
    /* set LED pin as digital output */
    LED_DDR = _BV (LED_BIT);

    /* led is OFF initially (set pin high) */
    LED_PORT |= _BV(LED_BIT);

    /* turn on internal pull-up resistor for the switch */
    BUTTON_PORT |= _BV(BUTTON_BIT);
}

int button_is_pressed()
{
    /* the button is pressed when BUTTON_BIT is clear */
    if (bit_is_clear(BUTTON_PIN, BUTTON_BIT))
    {
        _delay_ms(DEBOUNCE_TIME);
        if (bit_is_clear(BUTTON_PIN, BUTTON_BIT)) return 1;
    }

    return 0;
}

void toggle_led()
{
    LED_PORT ^= _BV(LED_BIT);
}
\$\endgroup\$
1
\$\begingroup\$

Could you please state what type of AVR you have?

I would think that as long as you do not define the F_CPU, the delay routine will take the default value to calculate the delay. Now if you just tell the CPU to assume a faster clock (this is what you do with redefining F_CPU) it has to count much higher to reach the same delay. Since the physical clock is still slow, the delay will be off by some very nasty factor.

If you're using Atmel Studio 6(+) take a look at the ASF wizard which has a specific template for the sysclock. Then it's just a matter of correctly defining the board_sysclk.h (which gets generated automatically) and a call to sysclk_init();

What did you really connect to the external pin?

Also, care must be taken when exceeding a specific value (this differs for various parts). In case of a high clock frequency, you will need to adjust the flash waitstates before switching the clock source.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.