Basic LCD Example for Xmega-B1

Created by Scott Schmit, last modified on Dec 03, 2013



The purpose of this page is to present a basic application that describes how to operate the LCD c42048 that comes standard with the ATxmega128B1 Xplained Kit from Atmel. The project combines functions that are scattered throughout the Atmel Software Framework (ASF) into a single Atmel Studio 6 project made up of only a few files, while maintaining a standard project flow that has been implemented in ASF for Xmega devices. It is meant to provide an easy introduction to the integrated LCD controller that is included in the Xmega B-family of microcontrollers.

Project Requirements

  • Atmel Studio 6 - Free software development tool from Atmel for ARM and AVR devices.
  • XMEGA-B1 Xplained - Development board for the Xmega B-family of microcontrollers. It is loaded with the ATxmega128B1 device.
  • JTAGICE3 - Atmel Debugger/Programmer. JTAGICE3 was used for this project, but any Atmel programmer that supports PDI programming can be used.
  • USB Cable - The XMEGA-B1 Xplained board can be easily powered through its USB 2.0 mini B connector. Consult the XMEGA-B1 Xplained Hardware User Guide for additional power up options.

Xmega Family Overview

The ATxmega device family is the highest performance 8-bit AVR microcontroller family from Atmel. They deliver excellent power consumption characteristics for 8-bit microcontrollers while integrating features such as 12-bit ADC, USB device connectivity, AES and DES crypto modules, DMA controller and Event System, CRC generator, along with multiple serial communication ports. The family is made up of the A, B, C, and D Series. The D Series is the entry level Xmega series with no USB connectivity or integrated LCD controller. The C Series adds USB Full-speed Device connectivity on top of the D Series functionality. The B Series adds an integrated LCD controller, capable of up to 4x40 segments, on top of the C Series functionality. The A Series adds AES/DES crypto engine on top of C Series functionality but has no integrated LCD controller. The Xmega chip-set is available in multiple different package types such as QFN, QFP, and BGA with available program memory ranging from 16 to 384 KB. The reader is strongly advised to read the datasheets corresponding to the microcontroller being used to determine which specific features are available, along with electrical characteristics and pin assignments. The images on this page and most of the information was found in the documents isted below. This page focuses on the ATxmega128B1 microcontroller loaded on the Xmega128B1 Xplained kit.


C42048A LCD

The C42048A was designed specifically for the Atmel Xmega Xplained kit. It was designed to evaluate the full capability of the integrated LCD controller. It contains a group of seven 14-segment alphanumeric digits, a group of five 7-segment digits, a bar graph of 9 segments, along with 13 additional icons. The LCD pixels are mapped using 40 segments and 4 common terminals which can be accessed directly from the Display Memory registers.

Pixel Connections

Each pixel on the display has a unique connection between a Common line and a Segment line, much like a point has a unique coordinate on an x-y plane. Figure 1 illustrates the “grid” of connections between the Segment and Common lines.

Figure 2 illustrates which Common and Segment pins are mapped to each individual pixel on the C42048A LCD.

From this pixel map, the reader can see that pixel (0,0) corresponds with the Level Bar at the lower portion of the display.

LCD Timing

For a pixel to become visible, an absolute voltage above a certain threshold must be applied across the corresponding Segment and Common pins. However, this voltage cannot be held at a constant (DC) value to prevent degrading of the liquid crystal. Therefore the voltage is altered in a sequence that’s dependent on the number of Common lines used by the display. The frequency of the alternating signal determines the frame rate of the LCD. The integrated LCD controller takes care of the voltage level present on each Common and Segment line and the frame rate of the LCD. However, the user needs to specify the number of Common lines present and configure the LCD registers accordingly.

The LCD controller within the Xmega128B1 is capable of controlling LCDs using 1 to 4 common lines. The C42048 LCD uses 4 Common lines. For an LCD with 4 Common lines, the frame length must be divided into 4 individual periods. This is known as 1/4 Duty. Each Common line of the LCD is energized for 1/4 of the frame. The voltage level on the Segment line and Common line is divided into even thirds between Ground and V_lcd. This is known as 1/3 Bias. Figures 3 and 4 below illustrate the timing diagram for energizing a pixel connected to Common line 0 and Segment line 0 (0,0). To make pixel (0,0) visible, the voltage on the Segment line 0 is phase shifted so that | SEG0 - COM0 | > | V_threshold |.

Design Considerations

This section describes some typical considerations a designer must account for in every Xmega design, along with some considerations for LCD-specific Xmega applications. Each sub-section includes general considerations, along with some register configuration examples. The reader is encouraged to have the Xmega-B manual available for easy reference. All example code is written in C-Programming language. If global definitions are used in the examples, the 8-bit hex value is included in comments for easy reference.

System Clock and Frame Rate Options

The selected source for the 32kHz RTC is also used to source the system clock of the LCD. This can be sourced from an internal 32kHz oscillator within the Xmega, or an external 32kHz source such as a crystal. The LCD clock rate is then derived from a prescaler that divides the 32kHz source. The actual LCD frame rate is dependent on the number of Common lines used by the display, the RTC source frequency, and the LCD Prescaler configuration. The frame rate for a 1/4 Duty LCD can range from 31.25 Hz up to 512 Hz.

The designer must ensure the LCD peripheral is enabled by writing a ‘0’ to the LCD bit of the PRGEN register. An example of this is shown below. No LCD register configurations will take effect if the LCD peripheral is disabled. This seems like an obvious statement, but it is an easy thing to overlook if peripherals were disabled to save power.

PR.PRGEN &= ~PR_LCD_bm; // ~0x80

The Real Time Counter Control Register (CLK.RTCCTRL) is used to define the source for the RTC. For this example, the 32kHz internal ULP oscillator was used as the RTC source. The designer must ensure the RTC is enabled by setting the RTCEN bit in the CLK.RTCCTRL register. An example of loading these settings is shown below.


LCD Control Register B (LCD.CTRLB) is used to define the frame rate of the display. Consult the device datasheet for all available frame rate options. For this example, the LCD frame rate was set to 62.5 Hz with Low Power waveform enabled using 1/4 Duty and 1/3 Bias. An example of loading this frame rate based on the 32kHz source is shown below.


Note: For this example, the CPU clock and all of the system clock prescalers were set. However, all that is absolutely necessary to operate the LCD is that the RTC source is configured properly.

Interrupt Configuration

Xmega devices include a Programmable Multilevel Interrupt Controller which allows the designer to assign a priority level to individual interrupts. It also allows round-robin or vector address based interrupt execution. The designer should customize interrupt execution priority based on the needs of the specific application.

The LCD controller in Xmega B devices supports a user configurable interrupt. If enabled, the interrupt will execute every time a specified number of frame periods has passed. The period between interrupts can be in the range of 1 to 32 for default waveforms. If Low Power waveforms are enabled, the range is 2 to 64 frames. Since, the LCD clock operates off of the RTC source, the LCD interrupt is also derived from the RTC source. This allows a convenient means of performing scheduled updates of the LCD, such as scrolling text, incrementing a progress bar, blinking icons, or updating a digital clock.

The LCD Interrupt Control Register (LCD.INTCTRL) is used to specify the interrupt period and the priority level of the interrupt. For this example, the LCD interrupt was scheduled to execute every 16 frames and was given high level priority. An example of configuring this interrupt period is shown below.


At 62.5 Hz, a frame is being executed every 16 ms. With the current configuration, the time between interrupts will be 256 ms (about 4 interrupts per second). Exactly 4 interrupts per second would be achieved if a 32.768kHz source was used instead of a 32kHz source.

The LCD Controller also utilizes an Interrupt Flag Register (LCD.INTFLAGS). The FCIF bit is set whenever the specified number of frames has been reached, causing the interrupt. The bit is cleared automatically by hardware when the ISR is carried out in software. The designer could also use this register in a polling scheme to execute periodic updates, even with the interrupt disabled. Generally, it’s a good idea to explicitly clear this bit during configuration. This is demonstrated in the following bit of code.

LCD.INTFLAGS |= LCD_FCIF_bm; // 0x01

Port I/O Configuration

On the Xmega128B1 Xplained board, the backlight of the LCD is controlled using PORTE, PIN5. Therefore, the pin needs to be configured as an output using the PORTE Direction Register (PORTE.DIR). This pin controls the gate of a MOSFET which allows current through the LED backlight of the LCD. Pulse-width-modulation (PWM) can be used to finely control the intensity of the backlight. If fine control is not required, the user can turn the backlight fully-on by writing a ‘1’ to PE5, or turn the backlight completely off by writing a ‘0’ to PE5. The PORTE Out-set and Out-clear Registers (PORTE.OUTSET, PORTE.OUTCLR) can be used to turn individual bits ON or OFF. For this example, the backlight was turned on full-bright. An example of this is shown below.

PORTE.DIR = 0x20; // set PE5 to output
PORTE.OUTSET = 0x20; // turn backlight fully-on by setting bit 5

If using an LCD that doesn’t require all 40 segment pins of the Xmega, up to 16 segment pins (SEG39:24) can be converted to general purpose I/O pins. If configured as GPIO, the highest 8 segment pins (SEG39:32) become PORTG. If configured as GPIO, the next 8 segment pins 32:24 become PORTM. The lowest 24 segment pins (SEG23:0) cannot be converted to GPIO. If using an LCD with less than 20 segment pins, the remaining dedicated segment pins on the Xmega can be tied to ground. The 6 least significant bits of the LCD Control Register C (LCD.CTRLC) are used to define which pins are used as segment drivers. Below shows an example of using a 30 segment LCD and converting the highest 10 segment pins to GPIO.

LCD.CTRLC = 0x1E; // lowest 30 segment pins used to drive LCD
                  // segment pins 39 down to 32 become PORTG[7:0]
                  // segment pins 31 and 30 become PORTM[1:0]

For this example, all 40 segments were used, so CTRLC was loaded with 0x3F.

Additional LCD Register Configuration

The LCD Control Register A (LCD.CTRLA) controls many of the global functions of the LCD. Specifically, it is used to enable the LCD, specify an internal or external LCD voltage bias source, control Data Memory shadowing, swap Common/Segment pins, clear the Display Memory contents, enable/disable all segments at once, and blank the display. For this example, Control Register A was configured to simply enable the LCD peripheral and enable all segments. An example of this is demonstrated in the following code.


The LCD Control Register D (LCD.CTRLD) supports hardware blinking of pixels to reduce software complexity if desired. This register is used to enable hardware blinking and specify blink rates of 0.5, 1, 2, or 4 Hz. For this example, hardware blinking was not implemented, so Control Register D was left at it’s default value of 0x00. However, the following line of code demonstrates how a designer could implement a 2Hz hardware controlled blink rate.


Only pixels connected to Segment lines 0 and 1 support individual hardware blinking control. Control Register E (LCD.CTRLE) is used to specify which segments to enable blinking on. The 4 most significant bits specify which pixels on SIG1 have hardware blinking enabled. Likewise, the 4 least significant bits of Control Register E are used to specify which pixels connected to SEG0 have hardware blinking enabled. If Control Registers D and E are configured properly, the pixel will blink as soon as the segment is enabled in Display Memory. Refer to Fig. 2 above to determine which pixels are supported by hardware blinking (all those connected to SEG0 or SEG1). The selected pixels would blink at the rate specified in Control Register D. If no segments are specified in Control Register E, but the Blink Enable bit is set, blinking will commence on all segments set in Display Memory, regardless of whether or not they are connected to SEG0 or SEG1. For this example, hardware blinking was disabled. However, the following bit of code demonstrates how a user would enable hardware blinking on the “Warning” pixel (0,1).

LCD.CTRLE = LCD_BPS10_bm; // 0x10 - This enables blinking on the pixel connected to Seg1, Com0 (Warning) at the rate specified in LCD.CTRLD
LCD.DATA0 |= 0x02; // This sets the Warning pixel in Display Memory. Typically, a function call would be used to determine
                   // which register and bit to set for individual pixels instead of hard-coding values to Display Memory

LCD Control Register F is used to finely control the contrast of the display. The 6 least significant bits of the register are used to enter a signed 6-bit value to adjust the voltage across each pixel’s Segment and Common pins. Acceptable decimal values are in the range of -32 to 31. These values correspond to a voltage range of approximately 2.5 to 3.5V. Therefore, the default value of 0x00 will achieve a voltage of approximately 3.0V across all enabled pixels. The following code demonstrates how a user could set the LCD contrast 50% higher than default (approx. 3.25V across pixel terminals).

LCD.CTRLF = 15; // 0x0F - Halfway between 0(0x00) and 31(0x1F)

The Xmega LCD controller supports 7-segment digits with 3 or 4 Common pins, 14-segment digits with 4 Common pins, and 16-segment digits with 3 Common pins. Control Register G (LCD.CTRLG) is used to specify which type of digit is being used. This register is also used to specify which Segment terminal to start writing the decoded display to. Control Register H is used to enter the desired display data. The digit decoder then automatically converts the data to individual display codes which are written to Display Memory. For this example, 14-segment digits with 4 Common pins were used to display the alpha characters, while the 7-segment digits with 4 Common terminals were used to display numeric characters. Refer to the Example Project below for example usage of writing alpha/numeric characters to the LCD.

Note: Every time the digit decoder operates, all 4 pixels connected to Segment 11 get cleared by hardware. The 4 affected pixels are the Degree C, Degree F, Volt, and milliVolt Icons. If the application uses any of these 4 icons, the designer is responsible for re-displaying these icons after every decoder operation. For this example, definitions were set in a header file called “My_Board.h” to specify which icons were used for the application.

When referring to “Display Memory” we really mean the LCD Data Registers 0 through 19 (LCD.DATA19:0). The designer can manually set/clear pixels by directly writing to these registers, but a more convenient way to display data would be to use Control Registers G and H to automatically update Display Memory.

Reducing Power Consumption

Decreasing power consumption can be achieved in a variety of ways. The easiest and most obvious way would be to turn off the LED backlight (PE5 = ‘0’) or at least use a PWM with low duty cycle (10~25%) to reduce the current draw of the backlight. However, this may not be an option in outdoor applications with bright sunlight.

Reducing the frame rate will also minimize power consumption. This is accomplished using Control Register B.

The Low Power Waveform can be used to reduce power consumption by decreasing the number of oscillations on the Segment and Common lines. The Low Power Waveform is enabled in Control Register B. The tradeoff with enabling Low Power Waveform is that it increases the minimum LCD interrupt period.

Another way to reduce power consumption is to use the lowest possible contrast value. This is accomplished using Control Register F and will be specific to each individual application.

Downloadable Xmega LCD Example Project

Download the following zip file and open the Basic LCD Example Project for Xmega128B1 microcontroller. It provides an easy-to-read project with documentation that describes basic functionality of the integrated LCD controller found in Xmega B devices.

Comments from the Author

The reader is encouraged to read through all of the documentation that is referenced on this page. Was this page helpful? Is there anything you would like to see added to the EEWiki? I hope you enjoy experimenting with the integrated Xmega LCD controller!

  • Scott

For questions or feedback about information on this or any other page, please go to the TechForum: TechForum