Flashing an LED at a Specific Frequency

Last modified by Microchip on 2023/11/10 11:09

AVR®: Flashing an LED at a Specific Frequency

Objectives

  • Introduce XCA8 Library functions to set a precise delay based on the AVR CPU frequency.
  • Find the clock source of the ATmega328P on the Xplained Mini.
  • Writing to the PIN register to efficiently toggle a GPIO pin.

Procedure

Library Function

Find the library function we need to set a delay in our code.

With the project from the previous lesson, open in MPLAB® X IDE, select Help, and then the Help Contents button in the top menu.

Help Contents

When the Help Contents opens, select the Search tab and type "avr user guide" in the Find field as shown. Then hit Enter and select About MPLAB XC8 C Compiler User's Guide for AVR MCU. Click the top link to the document on the right side of the panel.

Help Search

This will open the XC8 user's guide for AVR MCUs where we will search for "delay" in the document.  This will bring us to section 7.6 of the guide which describes the use of the delay function

Delay Search


Delay Function

Add the Delay function.

The user guide tells us that in order to use this function, we'll need to include the header avr/delay.h file.  Place the following line of code towards the top of our Getting_Started_with_AVR project like this:

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

int main(void) {
    DDRB |= (1 << PB5); // set PB5 as output pin
   
   while (1) {
       
       PORTB |= (1 << PB5); // set PB5 high
   
    }
}

The user guide also tells us that in order for this function to work properly, we will need to define the clock speed of the CPU.  This value will be assigned to the constant F_CPU.  The clock speed of the ATmega328PB can be found in the "ATmega328PB Xplained Mini User Guide".  By searching for "clock" in the document, you'll find this page where it indicates that while configured to run at 5 volts, the clock speed is 16000000 Mhz.

Clock Speed Table

Now we need to add this defined value to our code as an Unsigned Long constant as shown below on the first line.  The delay function has also been added to the main loop of the code as shown. It will cause a delay of 500ms. 

If you compile and run this code, it will not toggle the LED.  It will turn on the LED and leave it on.

#define F_CPU 16000000UL
#include
<avr/io.h>
#include
<avr/delay.h>


int main(void) {
    DDRB |= (1 << PB5); // set PB5 as output pin
   
   while (1) {
       
       PORTB |= (1 << PB5); // set PB5 high
      
       _delay_ms(500);

    }
}

Refer to Datasheet

One more modification is needed.

Another look at the datasheet for the ATmega328PB shows in the I/O-Ports section, that the PORTB statement in the above code is not going to toggle our pin.  Our code will set the pin as HIGH and each time the code loops, it will keep bringing the pin HIGH so that it never goes LOW.

To toggle the pin, we need to review this information from the datasheet and write our code accordingly...

Toggling the Pin section from the datasheet


Put the Code Together

Putting it together in MPLAB X IDE.

Let's put these lines of code together in MPLAB X IDE. We'll comment out the PORTB line so that it doesn't affect our code. Note the addition of a PINB statement that does the toggling. Here's the final code version:

#define F_CPU 16000000UL
#include
<avr/io.h>
#include
<avr/delay.h>


int main(void) {
    DDRB |= (1 << PB5); // set PB5 as output pin
   
   while (1) {
       
       //PORTB |= (1<< PORTB5);
       PINB |= (1 << PINB5);
      
       _delay_ms(500);
    }
}

Program the Device

Place this code into the main file of MPLAB X IDE and select the button indicated in the accompanying image to make and program the target device.

Program the Target

If everything was done as indicated, the LED on the board should blink.

Learn More