AVR340: Direct Driving of LCD Using General

AVR340: Direct Driving of LCD Using General
Purpose IO
Features
8-bit
Microcontrollers
•
•
•
•
•
•
•
Application Note
4K byte self-programming Flash Program Memory.
512 byte SRAM, 256 Byte EEPROM.
8 Channel 10-bit A/D-converter (TQFP/MLF).
debugWIRE On-chip Debug System.
Up to 20 MIPS throughput at 20 MHz.
23 to 28 I/O lines, depending on package.
PDIP (shown), TQFP and QFN/MLF packages available.
1 Introduction
Many products require a Liquid Crystal Display (LCD) Interfaced to a
microcontroller (MCU). This application note describes the operation of a
Multiplexed LCD. Also discussed are electrical waveforms and connections
needed by a LCD, as well as a C-program to operate the LCD. The result is an
excellent low cost combination and a starting point for many products.
Although multiplexed LCDs are initially more complex to get operational, they are
the lowest cost displays and require the lowest number of I/O pins of all glass
LCDs (glass refers to the lack of an additional on-board LCD driver chip).
Figure 1-1. ATmega48 PDIP package
Rev. 8103A-AVR-09/07
2 Details on the LCD
The LCD described within is Glass-only device (no interface IC on the LCD). The LCD
has 4 COM inputs and 8 segment inputs, requiring 12 I/Os on the ATmega48. There
are 11 to 16 additional I/Os still available on the ATmega48, depending on the
package chosen.
The LCD must be supplied with AC signals, typically square waves. LCDs will be
damaged if supplied with static DC signals, and irreversible plating of the segments
will occur. Figure 2-1 shows an example LCD footprint.
Figure 2-1. LCD footprint
The LCD segments will become visible if the voltage difference between a COM input
and a segment input is typically 3.5 VAC.
COM Inputs: In this example, the 4 COM inputs are each biased at ½ VCC. This is
done to allow selected segments to be visible. Figure 2-2 shows 3 of the 4 COM
waveforms. All 4 COMs are sequentially enabled to produce one AC cycle each. The
total time for all 4 COMs to cycle is approximately 16 msec, which refreshes the LCD
at about a 60 Hz rate. This is fast enough so no flicker will be noticed, and still slow
enough to prevent ghosting of the ‘off’segments.
The scope image shows that each COM signal goes from ½ VCC to VCC for 2 msec,
then to GND for 2 msec, then back to ½ VCC. This is referrd to as “half VCC
excitation”. More complex LCDs often use “one third excitation”, but this is beyond the
scope of this ap note.
For additional information on LCD excitation, see the STK502 User’s Guide, available
at www.avr.atmel.com .
Each COM cycle is active for 4 msec, then returning to ½ VCC, the inactive state.
This adds up to a total time for all 4 COMs to be 16 msec.
2
AVR340
8103A-AVR-09/07
AVR340
Figure 2-2. Scope screen dump
To energize a segment, the waveform to that segment must be 180 degrees out of
phase with its COM waveform. The voltage difference between the segment and
COM signals will therefore be typically 5 Volts AC, which causes the segment to
become visible after 300-400 msec of refresh cycles.
To de-energize (turn off) a segment, the COM and segment waveforms should be in
phase with each other while that segment’s COM is active, that is, not at 2.5 volts.
So, a LCD with all segments OFF will have the segment inputs IN PHASE with each
COM input. (COM3 was omitted from Figure 2-2, since only 4 channels were
available.)
3 Schematic Descritpion
The schematic in Figure 3-1 shows the simple interface between the ATmega48 and
PD-383 LCD. Notice the pull up resistors on the COM signals: These resistors
supply the ½ VCC voltage, which is necessary when a COM signal goes to the
Inactive state. The ATmega48 simply sets the respective output pin to an input, and
the resistors pull the signal to ½ VCC.
On the LCD, the 8 Segment connections have been re-labeled in this ap note as 1A,
1B, 2A, 2B, and so forth, to match the data within the C program’s segment table.
3
8103A-AVR-09/07
Figure 3-1. Connections overview
4
AVR340
8103A-AVR-09/07
AVR340
Figure 3-2. Program flowchart.
5
8103A-AVR-09/07
4 Look Up Table Operation
The Look Up Table (LUT), see Table 4-1 for an example, is a 10-byte long list of
bytes that describe which segment to activate for characters 0-9. More characters
could be defined requiring one byte per new character.
The basic operation is this:
• In the main program, 4 RAM locations contain the 4 characters to be displayed.
These RAM locations contain a binary number from 0-9, and could be later
modified to contain ASCII characters.
• For each character position, there are COMA and COMB inputs. When each of
the 4 COM inputs are active, the COMA and COMB inputs are the result of a C
language instruction where each character’s LUT values are OR’d together.
• As an example, to display a “5” in the right-most character position, examine the
last row entry of the LUT.
1. An interrupt occurs each 2 msec, which causes the Switch statement to be
accessed.
2. When COM1 is active (case 0), the program accesses the LUT at row “5” and the
masks off all but the 2 right-most bits. These are added to the “segs_out” variable,
an AVR® RAM location.
3. Similarly, while COM1 is active, the program accesses the LUT three more times
to OR the first 2 bits of the remaining three display characters into the segs_out
variable.
4. A total of 2*4 = 8 bits are OR’d together into the segs_out variable, and then they
are written to the PORTC output port.
5. Two msec later the Switch statement case 1 will be accessed. This time the
segs_out data is XOR’d with 0xFF to reverse the polarities of all bits, which is
required as AC waveforms are required by the LCD.
These XOR’d
(complimented) results are sent to PORTC.
• After another 2 msec has elapsed, the above sequence occurs again, this time
while COM2 is active. Switch statement case 2 is executed. This time, data for
each displayed character is accessed from the LUT and assembled in segs_out,
then sent to PORTC in time with the COM2 active signal on PORTD.
• The sequence is duplicated for COM3 and COM4 signals. The entire 4 COM
sequence takes 16 msec, that is, 2 msec for each of the 8 cases in the Switch
statement.
Consult Figure 3-2 for further details on program flow.
6
AVR340
8103A-AVR-09/07
AVR340
Table 4-1. Look up table (LUT).
Segment activated
Character
DP
D
C
E
G
F
B
A
COM4 B
COM4 A
COM3 B
COM3 A
COM2 B
COM2 A
COM1 B
COM1 A
HEX
0
0
1
1
1
0
1
1
1
77
1
0
0
1
0
0
0
1
1
22
2
1
1
0
1
1
0
1
1
DB
3
1
0
0
1
0
1
1
1
97
4
0
0
1
0
1
1
1
0
2E
5
0
1
1
0
1
1
0
1
6D
6
0
1
1
1
1
1
0
0
7C
7
0
0
1
0
0
0
1
1
23
8
1
1
1
1
1
1
1
1
FF
9
0
0
1
0
1
1
1
1
2F
5 Diagram of COM1-COM4 Signals
Figure 5-1 shows how the AC waveform is generated for two LCD segments. The
COM signals are generated by the C program shown section 6. To activate an LCD
segment, the opposite polarity waveform must be applied to the desired A or B input
pins of the LCD. There are A and B inputs for each of the 4 character positions.
7
8103A-AVR-09/07
Figure 5-1. Phase details and AC wave form
VCC
½
VCC
COM1
GND
COM2
COM3
COM4
16 msec
VCC
A
PIN 12
B
F
GND
PIN 12 out of phase with
COM1 Turns on Segment 1B
G
VCC
E
C
PIN 11
D
GND
PIN 11 out of phase with
COM1 Turns on Segment 1C
6 Application code
// File name: LCX_App_Note_5_3_05.c
Displays' PPD-332 3 1/2 digit LCD
Demo C code to run Pacific
// Compiled with CodeVision AVR, version 1.24.4a Evaluation
version, available from http://www.hpinfotech.ro
// This program displays 4 incrementing decimal digits on the LCD.
LCD has 4 COMs and 8 segment connections (12 total)
// COM1-COM4 outputs on PORTD
//Segment Outputs on PORTC, called 1A, 1B, 2A, 2B, 3A, 3B to match
A&B values in segment_table array
8
AVR340
8103A-AVR-09/07
AVR340
// The PD-332 has identical LCD wiring for each of 3 digits; 2
segment pins per digit, labeled A and B
#include <mega48.h>
unsigned char segs_out = 0;
unsigned char state_counter = 8;
unsigned char output_change = 0;
unsigned char LCD_d_1
=0;
// counter starts at "000"
unsigned char LCD_d_2
=0;
unsigned char LCD_d_3
=0;
unsigned char LCD_d_4
=0;
unsigned char Pt_1_sec
=0; // 0.1 second counter
// Prototypes defined below
void initialization(void);
#define debug 0
#define LCD_Driver 1
// Look Up Table (LUT) for 3 1/2 digit/4 COM LCD by Pacific
Displays, #PD-332
// The following table has 10 entries to display chars 0-9. Hex
values are COM1-COM4 for LCD inputs A & B.
const unsigned char segment_table[] =
{0x77,0x22,0xDB,0x97,0x2E,0x6D,0x7C,0x23,0xFF,0x2F}; //display
numbers 0-9
//************************Timer 0 overflow interrupt service
routine***********************
//
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Re-load Timer 0 value
TCNT0=5; //Timer0 period = 0.125 usec = 8MHZ/64.
usec*250 5 = 255-250 5/4/05
2msec = 8
state_counter++;
output_change = 1;
// This is a flag for main loop
if (state_counter > 7) state_counter = 0;
}
//*********************End of Interrupt Service
Routine*************************************
//**********************Main Begins
here****************************************************
void main(void) {
//* * * * * Call Initialization function * * * * * *see function
defined below* * * * * * *
initialization();
9
8103A-AVR-09/07
//* * * * * * * Eanble Global enable interrupts* * * * * * * * ** *
#asm("sei")
//**********The following infinate While Loop contains the Switch
statement for LCD refresh******
#if LCD_Driver
while (1)
{
if(output_change){
output_change = 0;
// The following state_counter generates the 4 COM output
waveforms via PORTD, each with HI and LOW outputs
switch (state_counter) {
case 0:
{
segs_out = (segment_table[LCD_d_1]& 0x03);
digit_1's A & B bits
0x03)*4);
//get
segs_out = segs_out | ((segment_table[LCD_d_2]&
//get digit_10's A & B bits
segs_out = segs_out | ((segment_table[LCD_d_3]&
0x03)*16); //get digit_100's A & B bits
segs_out = segs_out | ((segment_table[LCD_d_4]&
0x03)*64); //get digit_1000's A & B bits
DDRD = 0;
PORTD = 0x00;
PORTC = segs_out;
DDRC
= 0xFF; // always on
DDRD
= 0x01; //COM1 asserted LOW
}
break;
case 1:
{
PORTD = 0x01;
PORTC = segs_out ^ 0xFF; // Compliment segment
outputs
DDRC
= 0xFF; // always on
DDRD
= 0x01;
//COM1 asserted High
}
break;
case 2:
{
segs_out = (segment_table[LCD_d_1]& 0x0C)/4;
digit_1's A & B bits
//get
segs_out = segs_out | (segment_table[LCD_d_2]&
0x0C);//get digit_10's A & B bits
segs_out = segs_out | ((segment_table[LCD_d_3]&
0x0C)*4); //get digit_100's A & B bits
10
AVR340
8103A-AVR-09/07
AVR340
segs_out = segs_out | ((segment_table[LCD_d_4]&
0x0C)*16); //get digit_1000's A & B bits
DDRD
= 0;
PORTD = 0x00;
PORTC = segs_out;
DDRC
= 0xFF; // always on
DDRD
= 0x02;
//COM2 asserted LOW
}
break;
case 3:
{
PORTD = 0x02;
PORTC = segs_out ^ 0xFF; // Compliment segment
outputs
DDRC
=0xFF;
DDRD
= 0x02;
//COM2 asserted High
}
break;
case 4:
{
segs_out = (segment_table[LCD_d_1]& 0x30)/16;
//get digit_1's A & B bits
segs_out = segs_out | ((segment_table[LCD_d_2]&
0x30)/4);//get digit_10's A & B bits
segs_out = segs_out | (segment_table[LCD_d_3]&
0x30);//get digit_100's A & B bits
segs_out = segs_out | ((segment_table[LCD_d_4]&
0x30)*4);//get digit_1000's A & B bits
DDRD = 0;
PORTD = 0x00;
PORTC = segs_out;
DDRC
= 0xFF;
DDRD
= 0x04;
//COM3 asserted LOW
}
break;
case 5:
{
PORTD = 0x04;
PORTC = segs_out ^ 0xFF; // Compliment segment
outputs
DDRC
= 0xFF;
DDRD
= 0x04;
//COM3 asserted High
}
break;
case 6:
{
segs_out = (segment_table[LCD_d_1]& 0xC0)/64;
//get digit_1's A & B bits
segs_out = segs_out | ((segment_table[LCD_d_2]&
0xC0)/16); //get digit_10's A & B bits
11
8103A-AVR-09/07
segs_out = segs_out | ((segment_table[LCD_d_3]&
0xC0)/4); //get digit_100's A & B bits
segs_out = segs_out | (segment_table[LCD_d_4]&
0xC0); //get digit_1000's A & B bits
DDRD = 0;
PORTD = 0x00;
//
segment outputs
PORTC = 0x00;//LCD_d_3 ^ 0xFF; // Compliment
PORTC = segs_out;
DDRC
= 0xFF;
DDRD
= 0x08;
//COM4 asserted LOW
}
break;
case 7:
{
PORTD = 0x08;
PORTC = 0x55;
//
PORTC = 0xFF; //LCD_d_3;
PORTC = segs_out ^ 0xFF; // Compliment segment
outputs
DDRC
= 0xFF;
DDRD
= 0x08;
//COM4 asserted High
}
break;
default:
DDRC = 0;
DDRD = 0;
// COM1-COM4 float
}
// Increment a counter to measure out 0.1 sec
Pt_1_sec++;
if (Pt_1_sec >=50){//.1 sec
Pt_1_sec = 0;
LCD_d_1++;
// 3 1/2 digit ripple BCD counter
for LCD digits
if (LCD_d_1 >=10){
LCD_d_1 = 0;
LCD_d_2++;}
if (LCD_d_2 >=10){
LCD_d_2 = 0;
LCD_d_3++;}
if (LCD_d_3 >=10){
LCD_d_3 = 0;
LCD_d_4++;}
}// end .1 sec
} // ****************End of Switch
Statement************************
12
AVR340
8103A-AVR-09/07
AVR340
}
#endif
//***********************End of infinite While
loop**********************************
}
//***********************End of
Main*************************************************
//************************Initialization function defined
here***********************
void initialization(void) {
// Declare your local variables here
// Crystal Oscillator division factor: 1
CLKPR=0x80;
CLKPR=0x00;
//DDRC=0x7F;
//7 Segment outputs
// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x03;
// = 8MHz/64
3/22/05
TCNT0=0xC1;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture Dy Timer/Counter 1: Off
//************************End of Initialization function
***************************
}
13
8103A-AVR-09/07
7 References
Data sheet and more detail at http://www.atmel.com/products/AVR/
14
AVR340
8103A-AVR-09/07
Disclaimer
Headquarters
International
Atmel Corporation
2325 Orchard Parkway
San Jose, CA 95131
USA
Tel: 1(408) 441-0311
Fax: 1(408) 487-2600
Atmel Asia
Room 1219
Chinachem Golden Plaza
77 Mody Road Tsimshatsui
East Kowloon
Hong Kong
Tel: (852) 2721-9778
Fax: (852) 2722-1369
Atmel Europe
Le Krebs
8, Rue Jean-Pierre Timbaud
BP 309
78054 Saint-Quentin-enYvelines Cedex
France
Tel: (33) 1-30-60-70-00
Fax: (33) 1-30-60-71-11
Atmel Japan
9F, Tonetsu Shinkawa Bldg.
1-24-8 Shinkawa
Chuo-ku, Tokyo 104-0033
Japan
Tel: (81) 3-3523-3551
Fax: (81) 3-3523-7581
Technical Support
[email protected]
Sales Contact
www.atmel.com/contacts
Product Contact
Web Site
www.atmel.com
Literature Request
www.atmel.com/literature
Disclaimer: The information in this document is provided in connection with Atmel products. No license, express or implied, by estoppel or otherwise, to any
intellectual property right is granted by this document or in connection with the sale of Atmel products. EXCEPT AS SET FORTH IN ATMEL’S TERMS AND
CONDITIONS OF SALE LOCATED ON ATMEL’S WEB SITE, ATMEL ASSUMES NO LIABILITY WHATSOEVER AND DISCLAIMS ANY EXPRESS, IMPLIED
OR STATUTORY WARRANTY RELATING TO ITS PRODUCTS INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTY OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
CONSEQUENTIAL, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THIS DOCUMENT, EVEN IF ATMEL HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Atmel makes no representations or warranties with respect to the accuracy or completeness of the
contents of this document and reserves the right to make changes to specifications and product descriptions at any time without notice. Atmel does not make any
commitment to update the information contained herein. Unless specifically provided otherwise, Atmel products are not suitable for, and shall not be used in,
automotive applications. Atmel’s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.
© 2007 Atmel Corporation. All rights reserved. Atmel®, logo and combinations thereof, and others, are the registered trademarks or
trademarks of Atmel Corporation or its subsidiaries. Other terms and product names may be trademarks of others.
8103A-AVR-09/07