Getting Started with AVR - Video Training Series

 Introduction and Key Training Application

In this series, we will be introducing a number of AVR® MCU peripherals, including GPIO, timer/counter, USART and ADC. In the process, we will work towards building an example application which samples an analog light sensor; then proportional to this ADC sensor reading, updates a PWM duty cycle. An averaged sensor value is then sent over the USART to a PC terminal.


Part 2 - Finding Documentation and Turning on an LED

 In this video:

  • Find the device datasheet, Xplained Mini User Guide and schematics.
  • Start a new GCC C Executable project in Atmel Studio 6.
  • Demonstrate how to efficiently use the datasheet to understand how to configure a pin and turn on an LED.
  • Set up and use the debugWIRE interface to program the ATmega328P.

Part 3 - Flashing an LED at a Specific Frequency

 In this video:

  • Introduce AVR® LibC functions to set a precise delay based upon 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.

Part 4 - Read an I/O as Input to Turn on LED

 In this video:

  • Set up macros to make code more readable.
  • Poll the status of the GPIO connected to the switch.
  • Debug in Atmel Studio using the I/O view, seeing bits in the PIN, DDRB and PORTB registers change as we single step through the code.

Part 5 - Using Pin Change Interrupts

 In this video:

  • Pin change IRQ's are used in low power board controllers.
  • Alternate functions of PORTB, including pin change IRQs.
  • Navigate the register map of the ATmega328P.
  • Enable an IRQ in the pin change Mask Register.
  • Enable the pin change IRQ in the pin change IRQ control register.
  • Determine the AVR® MCU status register enabling global IRQs.
  • Use AVR Libc support for IRQs (the required include, sei() and IRQ vector).
  • Testing by hitting a breakpoint in the ISR.

Part 6 - Making Our Simple App Low Power

 In this video:

  • Using sleep modes to reduce power consumption.
  • Active clock domains and wake-up sources in the different sleep modes.
  • Using the Power Reduction Register to turn of the clocks to unused peripherals.
  • AVR® Libc support for sleep modes.
  • Choosing and setting a sleep mode.
  • Enabling sleep, putting the CPU to sleep and disabling sleep on waking up.
  • A recommended application note, AVR4013: picoPower Basics.

Part 7 - Using Timer Overflow IRQs

 In this video:

  • Timer-Counter overview and block diagram.
  • Calculating the frequency of a timer-counter overflow.
  • The slowest an 8-bit timer can overflow, running the CPU at 16 MHz.
  • Register configuration to set up a 16-bit timer to overflow twice a second, including setting the timer prescalar and enabling the timer overflow IRQ.
  • Adding AVR Libc header file for interrupts.
  • Toggling the LED in the timer overflow Interrupt Service Routine.

Part 8 - Using Timer Compare Match IRQs

 In this video:

  • Change timer mode to Clear Timer on Compare Match (CTC) mode.
  • Enable Compare Match IRQ.
  • Update the interrupt vector efficiently (from timer overflow to CTC match on channel A).
  • Write a generic function to overflow the timer at a given frequency.

Part 9 - Using PWM to Dim an LED

 In this video:

  • Introduce Pulse Width Modulation (PWM) and the importance of high frequency and resolution.
  • Set a prescalar of 1 to get maximum PWM frequency.
  • Set up two output compare IRQ’s: one to control the period, the other to control the duty cycle.

Part 10 - Updating PWM Duty Cycle Using a Millisecond Timer

 In this video:

  • Setting up a millisecond timer to update the duty cycle
  • Using the 8-bit timer-counter 0 as a millisecond timer.
  • Incrementing the duty cycle every 2 ms, resetting the duty cycle to 0 when it equals the period.

Part 11 - A More Complete PWM Driver

 In this video:

  • Create functions: PWM_Increase_duty(), PWM_Decrease_duty(), PWM_BrightDim()
  • Use enumerators to keep track of the direction of PWM duty cycle change.
  • Declare our function prototypes.

Part 12 - Seeing Our PWM Waveforms on the Atmel Data Visualizer

 In this video:

  • Use the Data Visualizer graph function to look at GPIO in pin (as opposed to bus) mode.
  • Look at the PWM waveforms to see increasing duty cycles.
  • Understand what we changed in the code to give us more easily understandable waveforms.
  • Use cursors to measure the PWM frequency, showing that it is very close to the configured value of 10 kHz.

Part 13 - Using Hardware Fast PWM Mode and Testing with Data Visualizer

 In this video:

  • Understand the Fast PWM timing diagram.
  • Modify our PWM initialization function to configure 11-bit PWM and clear Output Compare 1B (OC1B) on compare match.
  • Find that OC1B is an alternate pin function of PB2 and setting this as an output.
  • Use the Data Visualizer's GPIO view in pin mode to analyze the output waveforms.
  • Utilize cursors to measure the frequency of the waveforms of both the LED pin (PB5) and OC1B (PB2).
  • Check the measured frequency (7813 Hz), against that from the formula in the datasheet (7812 Hz), showing the frequency is measured as expected.

Part 14 - Switching Between Programing and Power Options with Xplained Mini

 In this video:

  • Alternate between ISP and debugWIRE interface (toggling the power after using SPI to enable the Debug Wire Enable (DWEN) Fuse).
  • Switch to ISP from debugWIRE: While debugging, selecting "Disable debugWIRE and close", now able to select ISP.
  • Open the Programming dialog box in ISP mode to read the fuse settings.
  • Program the Clout Out (CKOUT) fuse to put the AVR® MCU clock out on the COUT pin.
  • Run the ATmega328P Xplained Mini at:
    • 5 V - reading a clock frequency of 16 MHz.
    • 3 V - reading a clock frequency of 8 MHz.
  • Understand speed vs. voltage of the AVR MCU from the datasheet.

Part 15 - Setting up the Data Visualizer

 In this video:

  • Explore the Atmel Data Visualizer, the Data Gateway Interface and where to find help when necessary.
  • Find two DGI_GPIO pins available to us on the Atmel | SMART SAM D21 Xplained Pro.
    • (DGI_GPIO0 is PA27, which is PIN9 on EXT3)
    • (DGI_GPIO1 is PA28, which is PIN10 on EXT3)
  • Connect these DGI pins to PB5 (LED) and PB2 (OC1B), which we would like to monitor.

Part 16 - Using the AVR USART to Loopback From a Serial Terminal

 In this video:

  • Block diagram overview of the AVR® USART (Universal Synchronous and Asynchronous serial Receiver and Transmitter).
  • USART initialization: 8 data bits, 1 stop bit, 9600 baud
  • USART receive function: Wait for data to be received, then store in data register.
  • USART transmit function: Wait for empty transmit buffer, then put data in the buffer.
  • Implement a simple loopback and test in Atmel Studio's terminal window.

Part 17 - Understanding the USART Baud Rate Macro

 In this video:

  • Baud rate equations to set the USART Baud Rate Register (UBRRn), based on a required baud rate and CPU frequency.
  • Tables of UBRRn settings for different CPU frequencies.
  • How to debug in order to check that the macro used to set UBRRn matches the recommendation in the tables.

Part 18 - Using an App Note to Implement IRQ-Based USART Communications

 In this video:

  • Find Atmel AVR® MCU application notes and source code.
  • Provide an overview of AVR306: Using the AVR USART in C.
  • Copy relevant code into the project.
  • Add the Libc header file for interrupts.
  • Modify the USART initialization function to auto calculate the baud rate register and to use one stop bit.
  • Adjust interrupt vectors written for IAR to AVR Libc.
  • Debug to understand what happens when we hit the data register empty interrupt.

Part 19 - Splitting Functions into USART.h and.c Files

 In this video:

  • Reference Tutorial on AVR® Freaks: Modularizing C Code: Managing Large Projects (by Dean Camera)
  • Grey out code that will not compile as part of your project (e.g. through #IFDEF), using Naggy (Available from the extension manager)
  • Move defines and function prototypes, used in relation to the USART, to a header file: USART_irq.h.
  • Move USART functions and variables to USART_irq.c.
  • Use of the Extern keyword is highlighted for global variables.
  • Add include files.
  • Add USART_irq.h to both main.c and USART_irq.h.

Part 20 - Sending "Hello World!" from the AVR USART

 In this video:

  • Provide relevant community developed training materials for a useful USART_putstring() function.
  • Modify this to call our USART_Transmit() function.
  • Use delays for testing purposes.
  • Put additional functionality into USART_irq.c and the function prototype to USART_irq.h, so main remains clean.

Part 21 - Using AVR LibC’s stdio to Send Formatted Strings

 In this video:

  • Provide good community tutorials to understand using printf( )
    1. Use Standard IO streams in AVR® GCC
    2. Use printf with an AVR® MCU
  • Set up a 'file' and a 'stream', using FDEV_SETUP_STREAM
  • Copy our existing IRQ based void USART0_Transmit( unsigned char data ) function, then modifying the parameter types to match what FDEV_SETUP_STREAM expects to create int USART0_Transmit_IO( char data, FILE *steam ), in the process extending the functionality of our USART_irq driver.
  • Test our formatted string.
  • Add a loop counter to our formatted string, using Stanford's AVR Programming Wiki to check syntax.

Part 22 - Using and Testing the AVR ADC

 In this video:

  • Provide a block diagram overview of the AVR® MCU's 10-bit Successive Approximation ADC.
  • Input voltage reference options and input channels.
  • Discuss prescale and conversion timing requirements, keeping the ADC clock between 50 & 200 kHz, setting a prescalar of 64, since we have a F_CPU = 8 MHz.
  • Set the range of the ADC by setting the voltage reference (to AVcc).
  • Open a new project and setting writing ADC_init ( ), using the datasheet as a coding reference.
  • Choose ADC1 as ADC input channel, connected to port C1 on the ATmega328P Xplained mini.
  • Configure the options in the ADC status and control register & ADC Auto Trigger Enable (ADATE).
  • Toggle an LED in the ADC ISR, so that we have a line of code to set a breakpoint on.
  • Connect a potentiometer to vary the voltage on the ADC pin.
  • Debug to verify the register configuration.
  • Example reading on the ADC result register: 0x156, or 342.
  • Vin = ADC * Vref / 1024 = 342 * 3.297 = 1.1011 measured by ADC, 1.104 measured by voltmeter, so 2.9 mV error or 1 LSB.
  • AVR120: Characterization and Calibration of the ADC on the AVR MCU.

Part 23- Updating PWM Duty Cycle Based on the ADC Sensor Reading

 In this video:

  • Update the PWM duty cycle based upon the ADC result register.
  • Open AVR_PWM.c, from a previous video.
  • Copy relevant PWM_init_LED() function, relevant defines, and interrupt service routines back into this project.
  • Verify that we can change the LED brightness by varying the POT connected to the ADC.
  • Find the user guide and schematics for the I/O1 Xplained Pro (ATIO1-XPRO), from The Atmel Store
  • Connecting the I/O1 Xplained pro to the ATmega328P Xplained mini.
  • Verifying that we are now able to change the LED brightness as the light sensor reading changes.

Part 24 - Averaging 10 mS ADC Samples Over a Second

 In this video:

  • Modify a millisecond timer function, from Updating PWM duty cycle using a millisecond timer, we create a 10 mS timer.
  • Test the frequency, using the Data Visualizer, by toggling a pin in the timer IRQ.
  • Change ADC auto trigger source to Timer Counter 0 Compare Match A.
  • Create volatile global variables 'accumulator', 'average' and 'samples', using these to calculate an average in the ADC IRQ.
  • Verify that we are now averaging ADC light sensor readings every second.

Part 25 - Sending Averaged ADC Sample Reading Over the USART

 In this video:

  • Complete the functionality initiated in the video Updating PWM Duty Cycle Based on the ADC Sensor Reading.
  • Average samples and send this over the USART to a terminal.
  • Add USART_irq.c and USART_irq.h files to our project (created in the earlier USART videos of this series).
  • Open the main file developed earlier (AVR_USART.c) as an example reference, to add the required variables and function calls to our project.
  • Test that USART stdio is working in this project by sending "Hello World!"
  • Send the average in a USART string from theADC interrupt service routine, completing the functionality that was introduced in the earlier videos.

Part 26 - Better Coding Practice for USART Send Using a Sendflag

 In this video:

  • Debug the IRQ driven USART communications to understand what happens when a string is sent.
  • Demonstrate that the USART Data Rate Empty IRQ has hit a number.
  • Create a global flag, which is checked in the while loop, to determine when the average should be sent over the USART, enabling us to move the USART send function out of the ADC ISR.
  • Reveal that we still have the same functionality, but having implemented better coding practice.

Part 27 - Understanding USART TX Pin Activity Using the Data Visualizer

 In this video:

  • The datasheet to find the TX pin on Port D1.
  • The Data Visualizer in pin mode to monitor the activity on this line in order to see the pulse bursts every second.
  • Cursors to demonstrate that each transmission takes roughly 37 mS (spanning more than three timer counter triggered ADC sample readings and ADC conversion complete IRQs).

Part 28 - picoPower and Putting an Application to Sleep

 In this video:

  • Revisit AVR® Libc support for sleep.
  • Disable the brownout detector when sleeping.
  • Provide an overview of the solution project to "AVR Hands-on megaAVR® picoPower®,” which uses a very similar application to the one we have developed.
  • Explore the techniques used to save power:
    1. GPIO set as inputs with pull-ups enabled.
    2. Use the Power Reduction Register to turn off the clocks to unused peripherals.
    3. Use the Asynchronous Timer-Counter 2, which can be clocked directly from an RTC.
  • Set the sleep mode to power-save mode.
  • In the while loop if the sendflag is set, after sending the USART string, putting the AVR MCU to sleep.
© 2017 Microchip Technology, Inc.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.