Flashing an LED at a Specific Frequency
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.
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.
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 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/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.
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.
#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...
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:
#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.
If everything was done as indicated, the LED on the board should blink.