Application Note AN8000.13 Driving LCD Displays with I/Os AN8000.13 Application Note Driving LCD Displays using XE8000 standard I/O ports Rev 1 February 2006 www.semtech.com 1 Application Note AN8000.13 Driving LCD Displays with I/Os Table of Contents 1 1.1 2 2.1 2.2 2.3 3 3.1 4 4.1 4.2 4.3 4.4 4.5 5 5.1 5.2 5.3 Introduction................................................................................................................................................. 3 Document structure .................................................................................................................................. 3 LCD Basics.................................................................................................................................................. 4 LCD direct drive........................................................................................................................................ 5 LCD multiplex drive .................................................................................................................................. 6 Mixing multiplex and direct drive .............................................................................................................. 7 Standard implementations ........................................................................................................................ 9 Driving a 4x8 segments LCD using standard microcontroller I/O ports................................................... 9 Application example................................................................................................................................. 10 Introduction............................................................................................................................................. 10 Hardware................................................................................................................................................ 10 Defining the LCD pins ............................................................................................................................ 10 Software – Constant & Variables ........................................................................................................... 11 Software - Functions .............................................................................................................................. 13 Annex A – Application source code ....................................................................................................... 16 Main file .................................................................................................................................................. 16 LCD Driver C file .................................................................................................................................... 17 LCD Driver Header file ........................................................................................................................... 22 © Semtech 2006 www.semtech.com 2 Application Note AN8000.13 Driving LCD Displays with I/Os 1 INTRODUCTION This application note intends to explain how to realize a simple LCD driver using the microcontrollers I/O ports. The main goal of this document is to understand how to build a cheap LCD interface for small LCD displays for example a STD 4.5 digit TN display. 1.1 DOCUMENT STRUCTURE This document is separated in 5 sections • Introduction: This section. • LCD Basics: This section explains what is a LCD and different method to drive them. • Standard implementations: This section explains how to implement the different driving methods described in the chapter “LCD basics”. • Application example: This section shows how to realize a LCD driver using an existing display. • Application source code: Contains the source code of the application. © Semtech 2006 www.semtech.com 3 Application Note AN8000.13 Driving LCD Displays with I/Os 2 LCD BASICS The Liquid Crystal Display (LCD) is a passive display technology. This means that this type of display does not emit light; instead, it uses the ambient light from the environment. By manipulating this light, it displays images using very little power. In addition LCDs can operate with relatively low voltage (2V and up). This has made LCDs the preferred technology whenever low power consumption and compact size are critical. LCDs are composed of two electrodes with liquid crystals placed between them. By applying a voltage to the electrodes, the crystals change their orientation and modify the light polarization, which is revealed by a polarized filter placed on the surface of the display. electrode electrode liquid crystal liquid crystal electrode (backplane) electrode (backplane) AC voltage not applied, LC remains in its default orientation, light goes through the filter. AC voltage applied, LC changes its orientation, light is blocked by the filter. Liquid crystals are very sensitive to constant electric fields and DC voltages can cause an electrochemical reaction which destroys the liquid crystals irreversibly, therefore only DC-free AC-voltages should be applied. As soon as the amplitude of the applied AC field is superior to a given threshold (dependant upon the LCD geometry and technology), the segment turns dark. If this amplitude is smaller than the same threshold, the segment remains transparent. If the amplitude is very near to the threshold voltage, the segment remains gray or glitches. Due to the specific characteristic described above, the way to drive a liquid crystal segment is as follows: AC rms voltage Crystal voltage VDD 0V VDD VDD or Electrode 2 0V VDD VDD 0V 0V VDD crystal threshold -VDD 0V 0V Electrode 1 A) both signals in phase, the resulting voltage on the crystal is 0V VDD Crystal voltage Electrode 2 0V AC rms voltage VDD VDD 0V 0V VDD -VDD 0V crystal threshold Electrode 1 B) both signals in counter-phase, the resulting voltage on the crystal is +/- VDD © Semtech 2006 www.semtech.com 4 Application Note AN8000.13 Driving LCD Displays with I/Os 2.1 LCD DIRECT DRIVE In multiple segments driving, one of the electrodes is common to all the segments, this electrode is called the backplane (see drawing below). The backplane sends a square signal and the other electrodes send the same signal with no phase shift for transparent segments or with a phase shift of 180° for dark segments. VDD Electrode 2 (segment 2) Electrode 2 0V VDD Electrode 1 Electrode 1 (segment 1) 0V VDD Backplane (common) 0V s1 s2 Backplane Here segment 1 is “off” and segment 2 is “on” s1 voltage AC VDD VDD 0V 0V crystal threshold -VDD s2 voltage AC rms voltage VDD VDD 0V 0V -VDD rms voltage crystal threshold The signal is in phase on segment s1 and in counter-phase on segment s2, therefore the resulting voltage is 0 on segment s1 and +/- VDD on segment s2 This way of driving LCD’s segments is the simplest one and the one that offers the best contrast, since the resulting voltage on electrodes is VDD or 0V. The drawback is that one needs one pin to drive each segment (plus one for the backplane), this may quickly lead to huge numbers of connections to drive simple LCD displays. © Semtech 2006 www.semtech.com 5 Application Note AN8000.13 Driving LCD Displays with I/Os 2.2 LCD MULTIPLEX DRIVE In order to increase the number of segments one can increase the number of backplanes, this method enables one electrode to drive more than one segment. In the example below each electrode drives two segments (Multiplex by 2). Segments must also have an “inactive” phase when their electrode carries the signal for the segments on the other backplanes. This is done by adding intermediate signals onto each backplane. The AC voltage on one segment is then integrated over a complete cycle through all the backplanes. Electrode 2 (segment 3, 4) VDD Electrode 2 0V Electrode 1 (segment 1, 2) Electrode 1 VDD 0V VDD Backplane 1 s1 0V VDD s3 s4 Backplane 1 inactive inactive Backplane 2 s2 inactive inactive Backplane 2 0V signal cycle This way of driving introduces another parameter, now the resulting voltages between Electrodes and backplanes are not 0V or VDD but values in between and the time to change all the segments is multiplied by the number of backplanes. If we do some calculations we can have the resulting voltage for each segment. See figure below. Electrode 2 (segment 3, 4) Electrode 1 (segment 1, 2) VDD Electrode 2 0V VDD Electrode 1 0V VDD s1 s2 s3 s4 Backplane 1 Backplane 2 Backplane 1 0V VDD Backplane 2 0V s1: Electrode1 - Backplane1 -1 s2: Electrode1 - Backplane2 -0.5 0.5 1 0.5 -0.5 V11rms = − 12 + 12 + 0.52 + −0.52 ⋅ VDD = 0.791⋅ VDD 4 V12 rms = − 0.52 + 0.52 + 02 + 02 ⋅ VDD = 0.354 ⋅ VDD 4 V21rms = 0 2 + 0 2 + − 0 .5 2 + 0 .5 2 ⋅ VDD = 0.354 ⋅ VDD 4 V22 rms = 0.52 + −0.52 + −12 + 12 ⋅ VDD = 0.791⋅ VDD 4 s3: Electrode2 - Backplane1 -0.5 0.5 s4: Electrode2 - Backplane2 0.5 -0.5 Electrode Backplane -1 1 Resulting signal Mathematically we can see that Von (segment visible) is situated at 0.791 x VDD and Voff (segment invisible) is situated at 0.354 x VDD Multiplying the backplanes allows one to address more segments, the drawback of this technique is that the delta between Von and Voff is reduced; this implies that the contrast is also reduced. LCD technology has fixed thresholds for Von and Voff, developers must take into account these thresholds and ensure that generated Voff and Von must respect these thresholds. The standard manner to increase contrast when using multiple backplanes is to generate 3 levels of voltage instead of 2, but this technique is too complex to be implemented when using standard microcontroller I/O ports. © Semtech 2006 www.semtech.com 6 Application Note AN8000.13 Driving LCD Displays with I/Os 2.3 MIXING MULTIPLEX AND DIRECT DRIVE The main problem encountered using multiplex drive is that both “on” and “off” generated voltages may be above or below the LCD thresholds. This is even more of an issue with bias ½ and high multiplexing ratios where “on” and “off” generated voltages are not far from each other. VDD VDD VDD Ideal Both under LCD “on” threshold Both above LCD “off” threshold Generated “on” rms voltage Generated “off” rms voltage LCD “on” threshold LCD “off” threshold As the direct drive does not have this limitation (full signal is applied to the segment or no signal is applied), a simple way to shift the applied voltage is to mix multiplex and direct drive (see diagrams below). When using direct drive for a short period of time, all backplanes are connected together to form a single backplane and a uniform signal is applied to all electrodes, increasing or decreasing the mean RMS voltage applied to the whole LCD. By changing the ratio between the uniform direct drive signal and the addressed multiplexed signal, one moves the mean applied “on” and “off” levels. Shifting Down Generated Thresholds Electrode 2 (segment 3, 4) Electrode 1 (segment 1, 2) Backplane 1 Backplane 2 VDD Electrode 2 0V VDD Electrode 1 0V VDD 0V VDD s1 s2 s3 s4 Backplane 1 Backplane 2 0V 0.8 0.8 Segment1 vs Backplane1 Segment2 vs Backplane2 0.4 0.4 Two signals superposition Resulting signal 0.4 Von = 0.82 + 0.82 + 0.4 2 + 0.4 2 ⋅ VDD = 0.633 ⋅ VDD 4 0 Voff = 0 2 + 0 2 + 0.4 2 + 0.4 2 ⋅ VDD = 0.283 ⋅ VDD 4 0.4 0 Mathematically we can see that Von (segment visible) is situated at 0.633 x VDD and Voff (segment invisible) is situated at 0.283 x VDD As shown in figures above, direct drive waveforms are forced during a short period of time at the beginning of each pulse forcing them to 0V will shift down the average resulting values of generated thresholds and vice-versa. © Semtech 2006 www.semtech.com 7 Application Note AN8000.13 Driving LCD Displays with I/Os Shifting Up Generated Thresholds Electrode 2 (segment 3, 4) Electrode 1 (segment 1, 2) Backplane 1 Electrode 2 VDD 0V VDD Electrode 1 0V VDD 0V VDD Backplane 2 s1 s2 s3 s4 Backplane 1 Backplane 2 0V 1 Segment1 vs Backplane1 1 0.6 Segment2 vs Backplane2 0.6 Two signals superposition Resulting signal © Semtech 2006 0.6 0.6 Von = 0.2 0.2 Voff = 12 + 12 + 0.6 2 + 0.6 2 ⋅ VDD = 0.825 ⋅ VDD 4 0.2 2 + 0.2 2 + 0.6 2 + 0.6 2 ⋅ VDD = 0.447 ⋅ VDD 4 Mathematically we can see that Von (segment visible) is situated at 0.825 x VDD and Voff (segment invisible) is situated at 0.447 x VDD www.semtech.com 8 Application Note AN8000.13 Driving LCD Displays with I/Os 3 STANDARD IMPLEMENTATIONS When using multiple backplanes, the signal on the backplanes becomes analog; this means when using microcontroller’s standard I/O ports that external circuitry must be added in order to produce this analog waveform. Following are examples on how to set up the circuitry in order to obtain multiplex by two waveforms. Microcontroller t0 t1 t2 t3 States to generate waveforms a µC a a 1 0 HiZ HiZ b b b HiZ HiZ 1 0 a 1 0 0.5 0.5 b 0.5 0.5 1 0 a1 a0 b1 b0 The figure above shows the most common way to create the analog waveforms playing with the High impedance capability of the I/O ports Microcontroller t0 t1 t2 t3 ab1 ab ab0 a µC b BCD codes to generate waveforms a 1 0 0 1 bc1 bc bc0 c b 1 0 1 0 c 0 1 1 0 ab 1 0 0.5 0.5 bc 0.5 0.5 1 0 ab1 ab0 bc1 bc0 The figure above shows an alternative for I/O ports that do not have the High impedance capability. Note that putting the I/O port as an input cannot be considered as a true HiZ, and in this case can lead to uncertain behavior since value of the input voltage is VDD/2. 3.1 DRIVING A 4X8 SEGMENTS LCD USING STANDARD MICROCONTROLLER I/O PORTS Application schematic Microcontroller t0 a ab b bc c µC d L7 L6 L5 L4 L3 L1 L0 e t2 t3 t4 t5 t6 t7 LCD 4x8 ab0 bc1 bc0 cd L2 t1 ab1 de cd1 cd0 de1 de0 L0 L1 L2 L3 L4 L5 L6 L7 © Semtech 2006 www.semtech.com 9 Application Note AN8000.13 Driving LCD Displays with I/Os 4 APPLICATION EXAMPLE 4.1 INTRODUCTION In this chapter we will setup an example application using an LCD, based on the theory of the previous chapters. The goal is to be able to develop an LCD driver with any simple LCD display. Knowing the pin assignment of the LCD will allow you to develop the corresponding driver. 4.2 HARDWARE 1 XE8000MP 1 XE8000EV101 1 Display LCD DISPLAYTECH 066-P2 MUX3 36 seg 4.2.1 LCD Hardware The LCD hardware is described below: Pin mapping: 1 1F 2 1A 3 1B 4 2F 5 2A 6 2B 3F 7 8 3A 3B 9 10 4F 11 4A 12 4B 1E 1G 1C 2E 2G 2C 3E 3G 3C 4E 4G 4C DP1 1D K DP2 2D - DP3 3D LOBAT DP4 4D CONT 13 COM1 14 15 16-30 NC COM2 COM3 4.3 DEFINING THE LCD PINS If we want to drive all the segments we have to use PC0 to PC7 and PB0 to PB3 for the signal driving and PB5 to PB7 to generate the common waveforms. In this case, pins have been assigned as follows: ports LCD pins com1 PC 0 PC 1 1 2 PC 2 3 PC 3 PC 4 PC 5 PC 6 PC 7 PB 0 PB 1 PB 2 4 5 6 7 8 9 10 11 PB 3 12 1F 1A 1B 2F 2A 2B 3F 3A 3B 4F 4A 4B 1E 1G 1C 2E 2G 2C 3E 3G 3C LO BAT 4E 4G 4C com2 com3 DP1 1D K DP2 2D - DP3 3D © Semtech 2006 DP4 4D CONT PB 6-7 13 COM 1 PB 6-5 14 PB 5-7 15 COM 2 1630 NC COM 3 www.semtech.com 10 Application Note AN8000.13 Driving LCD Displays with I/Os 4.3.1 Choosing The Common Waveform Generation Schematic Since the XE8801A can only use analog mode (equivalent to Hi-Z) when using pairs of pins, the alternative chained resistor schematic as shown in standard implementations, has to be used. The chained resistor schematic is more complex to implement but allows the use of single pins rather than pairs, without using the analog mode 4.3.2 Application Schematic Microcontroller R = 6 x 330K t0 ca ab PB5 a PB6 b XE8801A t1 t2 t3 t4 t5 COM1 ca1 ca0 ab1 COM2 bc ab0 PB7 c bc1 PC0 - PB3 L0 – L11 COM3 bc0 12 Lx 12 4.4 SOFTWARE – CONSTANT & VARIABLES Definitions of constants and variables 4.4.1 LCD Com Constant Table In order to generate the common wave forms we have to define an array containing six constants corresponding to the six possible states on the common lines: AB1, AB0, BC1, BC0, CA1 and CA0. a 1 0 1 0 0 b 0 1 1 0 1 c 1 0 0 1 1 ab 0.5 0.5 1 0 0.5 bc 0.5 0.5 0.5 0.5 1 ca 1 0 0.5 0.5 0.5 ca1 ca0 ab1 ab0 bc1 PB7 1 0 0 1 1 PB6 0 1 1 0 1 PB5 1 0 1 0 0 PB4 0 0 0 0 0 PB3 0 0 0 0 0 PB2 0 0 0 0 0 PB1 0 0 0 0 0 PB0 0 0 0 0 0 hex 0xA0 0x40 0x60 0x80 0xC0 1 0 0 0.5 0 0.5 bc0 0 0 1 0 0 0 0 0 0x20 4.4.2 LCD Data Constant Table To display numbers we need to have another constant table that contains the seven segments states for each number. a 0 1 2 3 4 5 6 7 8 9 1 0 1 1 0 1 1 1 1 1 b 1 1 1 1 1 0 0 1 1 1 c 1 1 0 1 1 1 1 1 1 1 d 1 0 1 1 0 1 1 0 1 0 e f 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 1 0 1 1 g 0 0 1 1 1 1 1 0 1 1 hex 0x7E 0x30 0x6D 0x79 0x33 0x5B 0x5F 0x70 0x7F 0x73 F B E B C C D A F A A A G C C D D © Semtech 2006 E B G C C D A B G E F B G D A A F B G C F G E A B F G C C D B D www.semtech.com 11 Application Note AN8000.13 Driving LCD Displays with I/Os 4.4.3 LCD Lines Variable Table This variable is a picture of the display and is used to refresh the LCD; one must modify this table in order to see the display changing at the next refresh. This variable is the most important. It represents the actual LCD display state. The table below represents the variable organization; we can see that every segment is represented for each phase of the LCD frame. (Note that “!” represent the Boolean operation NOT) 13 14 15 1 2 3 4 5 6 7 8 9 10 11 12 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PB0 PB1 PB2 PB3 c1+ c1c2+ c2c3+ !1f 1f !1e 1e !DP1 !1a 1a !1g 1g !1d !1b 1b !1c 1c !K !2f 2f !2e 2e !DP2 !2a 2a !2g 2g !2d !2b 2b !2c 2c !- !3f 3f !3e 3e !DP3 !3a 3a !3g 3g !3d !3b 3b !3c 3c !LOBAT !4f 4f !4e 4e !DP4 !4a 4a !4g 4g !4d !4b 4b !4c 4c !CONT c3- DP1 1d K DP2 2d - DP3 3d LOBAT DP4 4d CONT Note: This table is initialized with all segments “off”. © Semtech 2006 www.semtech.com 12 Application Note AN8000.13 Driving LCD Displays with I/Os 4.5 SOFTWARE - FUNCTIONS 4.5.1 Refresh Line In order to display a value on the LCD we must implement a function that will modify the LCD_Lines[ ] variable. This function will use LCD_Data[ ] constants as a template to set the wanted segments of the wanted digit. The special symbols such as DPx, LOBAT or CONT will be managed through another function described later in this document. We will call this function Refresh_Line. This function will have 2 arguments. The first argument will be used as an index to the LCD_Data[ ] constant table (Digits template). The second argument corresponds to the digit to be displayed. In order to simplify the code, the LCD_Data[ ] table has been rearranged in order to fit the LCD display physical layout. The two tables below gives a representation of the Refresh_Line function behavior. LCD_Data[ ] c b d g a e f hex function call : Refresh_Line ( 9, 4 ) 0 1 1 1 0 1 1 1 0x77 1 1 1 0 0 0 0 0 0x03 2 0 1 1 1 1 1 0 0x5D 3 1 1 1 1 1 0 0 0x1F 4 1 1 0 1 0 0 1 0x2B 5 1 0 1 1 1 0 1 0x3E 6 1 0 1 1 1 1 1 0x7E 7 1 1 0 0 1 0 0 0x07 8 1 1 1 1 1 1 1 0x7F 9 1 1 0 1 1 0 1 0x2F 7 6 5 4 3 2 1 1. The function takes the number 9, segment f value in the table LCD _Data [ ] 2. This value is inverted and placed at the fourth digit to enable the f segment (c1+ !4F) 3. Then the non inverted value is placed at the fourth digit to enable the f segment (c1- 4F) 4. Points 1 to 3 are repeated for all the segments of the fourth digit 1 LCD_Lines[ ] 12 11 10 9 8 7 6 5 4 3 2 1 PB2 0 !4a PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0 !3b !3a !3f !2b !2a !2f !1b !1a !1f 1 4a PB1 0 !4f 2 1 1 4f 3 PB0 c1- PB3 0 !4b 1 4b 3b 3a 3f 2b 2a 2f 1b 1a 1f c2+ 1 !4c 0 !4g 0 !4e !3c !3g !3e !2c !2g !2e !1c !1g !1e c2- 0 4c c3+ !CONT 1 4g 1 !4d c3- CONT 0 4d c1+ 6 7 3 4 1 4e 5 2 3c 3g 3e 2c 2g 2e 1c 1g 1e !DP4 !LOBAT !3d !DP3 !- !2d !DP2 !K !1d !DP1 DP4 LOBAT 3d DP3 - 2d DP2 K 1d DP1 © Semtech 2006 www.semtech.com 13 Application Note AN8000.13 Driving LCD Displays with I/Os 4.5.2 Set Special As special symbols can be considered as flags on the LCD display, this function allows all of them to be set individually. We will call this function SetSpecial. This function will have 2 arguments. The first argument will be a predefined value corresponding to the symbol to be displayed (DPx, LOBAT…) . The second argument corresponds to the state of the symbol (0 = OFF, 1 = ON) The table below gives a representation of the SetSpecial function behavior. Function call: SetSpecial( DP1, 1 ) 1 Place a 0 at the symbol DP1 (c3+ !DP) 2 Place a 1 at the symbol DP1 (c3- DP) LCD_Lines[ ] c1+ 12 11 10 9 8 7 6 5 4 3 2 1 PB3 PB2 PB1 PB0 PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0 !4b !4a !4f !3b !3a !3f !2b !2a !2f !1b !1a !1f c1- 4b 4a 4f 3b 3a 3f 2b 2a 2f 1b 1a 1f c2+ !4c !4g !4e !3c !3g !3e !2c !2g !2e !1c !1g !1e c2- 4c 4g 4e 3c 3g 3e 2c 2g 2e 1c 1g c3+ !CONT !4d !DP4 !LOBAT !3d !DP3 !- !2d !DP2 !K !1d 0 !DP1 1d 1 DP1 2 c3- 4.5.3 CONT 4d DP4 LOBAT 3d DP3 - 2d DP2 K 1e 1 LCD Refresh In order to avoid the LCD display blinking the index of the LCD_Lines[x] array must be changed at least 150 times per second. This means a complete display refresh every 25 times per second (25Hz) which is the physical limit for the eye to not see the refresh. Moreover, to implement the contrast correction as described in the chapter “Mixing multiplex and direct drive” we need to have a faster refresh rate, see the timing diagrams below. Contrast correction scheme Std Multiplex scheme 40 ms max (25Hz) 40 ms max (25Hz) t0 t5 t10 t15 t20 t25 t30 t0 t1 t2 t3 t4 t5 c1+ c1+ COM1 c1- COM1 c1- c2+ c2+ COM2 c2c3+ COM2 c2c3+ COM3 c3- Lx LCD Lines COM3 c3- Lx LCD Lines t0 = 6.7ms t0 = 1.3ms In this example we choose to have 6 steps to correct the contrasts, this implies a higher refresh frequency. © Semtech 2006 www.semtech.com 14 Application Note AN8000.13 Driving LCD Displays with I/Os The function will be called LCDRefresh and will have to be called at least every 1.3 ms. This function does not need any arguments. This function uses a variable that contains a set of flags, these flags will be used to generate the correct pulse widths for the contrast correction and the data display. The diagram below shows the timings generated through these flags. LCDFlags ratio AB = 0 1 pulse AB = 0.5 1 polarity AB = 1 1 correction 9 1 Not used 10 5 x Not used 6 1 x ratio: Triggers the writing of the contrast correction pulse pulse: Triggers the writing of the standard multiplex pulse polarity: Determines the current polarity of the common. Correction: Inverts the correction shift if at 1. ratio 2 x Not used pulse x Not used polarity AB = 0.5 AB = 0.5 3 7 11 4 8 12 AB = 0.5 Contrast correction pulse, depends on polarity, ratio & correction flags Standard multiplex drive, depends on pulse flags The table below shows the different states of the flags state 0 1 2 3 4 5 6 7 8 9 10 11 12 rat 0 0 1 0 1 0 1 0 1 0 1 0 1 pul 0 0 0 1/0 0 1/0 0 1/0 0 1/0 0 1/0 0 pol 1 1 1 0 0 1 1 0 0 1 1 0 0 cor 0 0 0 0 0 0 0 0 0 0 0 0 0 AB = 1 LCD_COM[0] 0 LCD_COM[1] 1 LCD_COM[2] 0 LCD_COM[3] 1 LCD_COM[4] 0 LCD_COM[5] © Semtech 2006 www.semtech.com 15 Application Note AN8000.13 Driving LCD Displays with I/Os 5 ANNEX A – APPLICATION SOURCE CODE This LCD driver can be found annexed in a zip file, some other functions have been added in order to simplify the use of the LCD display. Functions added: void Number2LCD (_U16 Value); void InitLCD(void); void AllChar(_U8 State); void LCDOff(void); This function takes a number from 0 to 9999 and displays it on the LCD This function inits the hardware (counters ports etc..) This function clears/displays all the segments of the LCD This function clears the LCD and disables all the peripherals In the zip file you will find two projects, one is the standard template including the LCD driver below; the other is a basic clock application. Below is the main file of the standard template showing the minimum code to write to see something on the LCD. 5.1 MAIN FILE /******************************************************************* ** File : main.c ** ******************************************************************** ** ** ** Version : ** ** ** ** Writen by : ** ** ** ** Date : XX-XX-XXXX ** ** ** ** Project : ** ** ** ******************************************************************** ** Changes : ** ******************************************************************** ** Description : Main program ** *******************************************************************/ #include "Globals.h" /******************************************************************* ** Global variables declaration ** *******************************************************************/ _U8 Toggle = TRUE; // Global variable changed in irq 128Hz /******************************************************************* ** main : Main program function ** ******************************************************************** ** In : ** ** Out : ** *******************************************************************/ int main (void){ _U16 i; InitMicro(); _Monitor_Init(); _Monitor_SoftBreak; InitLCD(); // Initializes the microcontroller (RC @ 1MHz) // Initializes LCD RegIrqEnHig |= 0x40; // Enables the 128Hz interrupt while(1){ //displays numbers from 0 to 9999 for (i = 0 ; 9999 > i; i++){ Number2LCD (i); // display the current loop value do{ asm("halt");// waits for the 1Hz interrupt }while(!Toggle); Toggle = FALSE; } } return 0; } void Handle_Irq_128Hz (void){ Toggle = TRUE; } © Semtech 2006 www.semtech.com 16 Application Note AN8000.13 Driving LCD Displays with I/Os 5.2 LCD DRIVER C FILE /******************************************************************* ** File : 0x_LcdDriver.c ** ******************************************************************** ** ** ** Version : V 1.0 ** ** ** ** Writen by : Gregoire Guye ** ** ** ** Date : 21-02-2005 ** ** ** ** Project : ** ** ** ******************************************************************** ** Changes : ** ******************************************************************** ** Description : 0x LCD driver ** *******************************************************************/ #include "0x_LcdDriver.h" /******************************************************************* ** Global variables declaration ** *******************************************************************/ // Common Scheme _U8 LCD_Com[] = {CA1, CA0, AB1, AB0, BC1, BC0}; // Display Scheme initialized at LCD off (all 0) _U16 LCD_Lines[] = {0xFFFF, 0x0000, 0xFFFF, 0x0000, 0xFFFF, 0x0000 }; // Ports image // Numbers from 0 to null predefined // 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 // data (0,1,2,3,4,5,6,7,8,9,- , ,c ,l ,e ,t ,b ,n) _U8 LCD_Data[] = {0x77,0x60,0x3E,0x7C,0x69,0x5D,0x5F,0x64,0x7F,0x6D,0x08,0x00,0x17, 0x13,0x1F,0x1B,0x5B,0x4A}; volatile _U8 CountInt,CountIntStep = 1; _U8 LCDFlags = 0x08; _U8 CountIntTick; _U8 CurrentLine = 0x00; © Semtech 2006 www.semtech.com 17 Application Note AN8000.13 Driving LCD Displays with I/Os /*************************************************************************** ** Refresh_Line : Transposes a number in a digit ** **************************************************************************** ** This routines transposes the values stored in the LCD_Datatable to the ** ** table used to display values on LCD , in this case a 6 rows x 12 col ** ** disposed as follow : ** ** ** ** LCD_Lines[] ** ** /-------------------------------------------------------------\ ** ** |PB3 .PB2|PB1 . PB0 |PC7 . PC6|PC5 . PC4|PC3 . PC2|PC1 . PC0| ** ** c1+|!4B .!4A|!4F .!3B |!3A .!3F |!2B .!2A |!2F .!1B|!1A .!1F | ** ** c1-| 4B . 4A| 4F . 3B | 3A . 3F | 2B . 2A | 2F . 1B| 1A . 1F | ** ** c2+|!4C .!4G|!4E .!3C |!3G .!3E |!2C .!2G |!2E .!1C|!1G .!1E | ** ** c2-| 4C . 4G| 4E . 3C | 3G . 3E | 2C . 2G | 2E . 1C| 1G . 1E | ** ** c3+|!CONT.!4D|!DP4.!LOBAT|!3D .!DP3|!- .!2D |!DP2 .!K |!1D .!DP1| ** ** c3-| CONT. 4D| DP4. LOBAT| 3D . DP3| - . 2D | DP2 . K | 1D . DP1| ** ** +-----+---+----+------+----+----+----+----+-----+---+----+----+ ** ** ** **************************************************************************** ** In : number (0-null), digit_no (0-3) ** ** Out : - (LCD_lines modified) ** ***************************************************************************/ void Refresh_Line (_U8 number, _U8 digit_no ){ _U8 i, Lines_index, phase; _U16 mask, temp ,curr_num; Lines_index = 0; // initializes the line index phase = 0; // with phase = 0 first "1" on commons digit_no = (3 - digit_no); digit_no *= 3; // Transforms digit_no to column index (3 multiple) mask = 0x01; // Initialises the mask mask <<= digit_no; // Place it to the right column curr_num = LCD_Data[number]; // Copy the Sline corresponding number for (i = 0; i < 14; i++){ phase ^= 0x01; // Toggles the phase if(phase){ // Write the current val & its inverse successively temp = (~curr_num & 0x01); // Mask the current val (inverse) and save it in temp }else{ temp = (curr_num & 0x01); // Mask the current val and save it in temp curr_num >>= 1; // Seek the next current val to write } temp <<= digit_no; // Places the value to its correct digit place LCD_Lines[Lines_index] &= ~mask; // Clears the previous value then write the new value LCD_Lines[Lines_index] |= (temp & mask); Lines_index++; // Writes next line if (i == 3){ // If the number of lines max -1 is reached mask <<= 1; // Moves the mask by 1 digit_no++; // Changes the line to write Lines_index = 0; // Re-initializes the line index }else if (i == 9){ mask <<= 1; // Moves the mask by 1 digit_no++; // Changes the line to write Lines_index = 0; // Re-initializes the line index } } } © Semtech 2006 www.semtech.com 18 Application Note AN8000.13 Driving LCD Displays with I/Os /******************************************************************* ** Display_LCD : Displays the current value of LCD_line table ** ******************************************************************** ** In : ** ** Out : ** *******************************************************************/ void Display_LCD (void){ _U8 IntPBVal, IntPCVal; if (CountIntTick == CountIntStep){ LCDFlags |= 0x01; // Sets Ratio Flag to 1 } else if (CountIntTick == 6){ LCDFlags |= 0x03; // Sets Pulse &Ratio flags to 1 CountIntTick = 0; } if(CountIntTick == 0 && ((LCDFlags & 0x03) == 0x03)){ }else{ CountIntTick++; } // Standard MUX3 drive section if((LCDFlags & 0x01) == 0x01){ if((LCDFlags & 0x02) == 0x02){ LCDFlags ^= 0x04; // toggles the polarity flag LCDFlags &= ~0x03; // Clears the Ratio & Pulses flags CurrentLine++; }else{ // Save the current ports values IntPBVal = RegPBOut; IntPCVal = RegPCOut; // Clears the correct pins according to predefined masks IntPBVal &= ~(COMMON_MASK3 | LINE_MASK2); IntPCVal &= ~LINE_MASK1; // Applies the common pattern IntPBVal |= (LCD_Com[CurrentLine]& COMMON_MASK3); // Applies the data patterns IntPCVal |= (LCD_Lines[CurrentLine] & LINE_MASK1); IntPBVal |= ((LCD_Lines[CurrentLine] >> 8) & LINE_MASK2); // Update the display RegPBOut = IntPBVal; RegPCOut = IntPCVal; } } // End of Standard MUX3 drive section // Contrast adjustment section else{ // Force the Commons to 0 or 1 during the period defined by the ratio if((LCDFlags & 0x04) == 0x04){ RegPBOut |= COMMON_MASK3; // Forces Commons to 1 }else{ RegPBOut &= ~COMMON_MASK3; // Forces Commons to 0 } // Force the Data to 0 or 1 during if((LCDFlags & 0x04) == ((LCDFlags RegPCOut |= LINE_MASK1; RegPBOut |= LINE_MASK2; }else{ RegPCOut &= ~LINE_MASK1; RegPBOut &= ~LINE_MASK2; } } // End of Contrast adjustment section if(CurrentLine == 6){ CurrentLine = 0; } the period defined by the ratio & 0x08)>> 1)){ // Forces Datas to 1 (PC0 - PC7) // Forces Data to 1 (PB0 - PB3) // Forces Datas to 0 (PC0 - PC7) // Forces Data to 0 (PB0 - PB3) // End of the table = 6 } © Semtech 2006 www.semtech.com 19 Application Note AN8000.13 Driving LCD Displays with I/Os /******************************************************************* ** SetSpecial : Sets the Special characters on LCD_Lines ** ******************************************************************** ** In : Special char to modify DP1, K, DP2, MINUS, ** ** DP3, LOBAT, DP4, CONT ** ** State 0 / 1 ** ** Out : ** *******************************************************************/ void SetSpecial(_U8 Schar, _U8 State){ _U16 mask = 0x01; mask <<= (Schar); // Shift the mask at the correct column if (State){ LCD_Lines[4]&= ~mask; // Unsets the corresponding bit LCD_Lines[5]|= mask; // Set the corresponding bit (inverse) }else{ LCD_Lines[4]|= mask; // Sets the corresponding bit LCD_Lines[5]&= ~mask; // Unsets the corresponding bit (inverse) } } /******************************************************************* ** AllChar : Sets all the Characters on LCD_Lines ** ******************************************************************** ** In : State 0 / 1 ** ** Out : ** *******************************************************************/ void AllChar(_U8 State){ if (State){ LCD_Lines[0] &= ~0x7FFF; LCD_Lines[1] |= 0x7FFF; LCD_Lines[2] &= ~0x7FFF; LCD_Lines[3] |= 0x7FFF; LCD_Lines[4] &= ~0x7FFF; LCD_Lines[5] |= 0x7FFF; } else{ LCD_Lines[0] |= 0x7FFF; LCD_Lines[1] &= ~0x7FFF; LCD_Lines[2] |= 0x7FFF; LCD_Lines[3] &= ~0x7FFF; LCD_Lines[4] |= 0x7FFF; LCD_Lines[5] &= ~0x7FFF; } } /******************************************************************* ** Number2LCD : Transposes a 3 digits number on the LCD display ** ******************************************************************** ** In : Value (0-9999) ** ** Out : ** *******************************************************************/ void Number2LCD (_U16 Value){ Refresh_SLine Refresh_SLine Refresh_SLine Refresh_SLine ((Value % 10), 0); (((Value / 10) % 10), 1); (((Value / 100) % 10), 2); (((Value / 1000) % 10), 3); } /******************************************************************* ** InitLCD : Initialises the counters for the LCD ** ******************************************************************** ** In : ** ** Out : ** *******************************************************************/ void InitLCD(void){ RegPCOut RegPCDir RegPBDir RegPBOpen RegPBPullup RegCntCtrlCk RegCntConfig1 RegCntC RegIrqEnHig RegCntOn = 0x00; = 0xFF; = 0xFF; = 0x00; = 0xFF; |= 0x10; &= ~0x40; = 0x18; |= 0x08; |= 0x04; // // // // // // // // // // Set PC out at 0 Sets PortC pins as outputs Sets PortB pins as outputs Port B hasn't open drain outputs No Pullups ck for counter C = 32KHz Counter C down counting 1.3kHz Authorize interrupt Counter C (240Hz) Starts the counter C } © Semtech 2006 www.semtech.com 20 Application Note AN8000.13 Driving LCD Displays with I/Os /******************************************************************* ** LCDOff : Switches off the LCD Display ** ******************************************************************** ** In : ** ** Out : ** *******************************************************************/ void LCDOff(void){ AllChar(0); // Clears the LCD display RegPCOut = 0x00; // Clears PortC RegPBOut &= ~0xEF; // Clears PortB RegIrqEnHig &= ~0x08; // Disable interrupt Counter C (240Hz) RegCntOn &= ~0x04; // Stops the counter C } /******************************************************************* ** Interrupts Handling ** *******************************************************************/ /******************************************************************* ** Handle_Irq_CntC : Handles the interruption Counter C that ** ** clocks the LCD display in order to have a ** ** total frame of 32Hz ** ******************************************************************** ** In : ** ** Out : ** *******************************************************************/ void Handle_Irq_CntC (void){ Display_LCD (); } //End Handle_Irq_CntC © Semtech 2006 www.semtech.com 21 Application Note AN8000.13 Driving LCD Displays with I/Os 5.3 LCD DRIVER HEADER FILE /******************************************************************* ** File : 0x_LcdDriver.h ** ******************************************************************** ** ** ** Version : V 1.0 ** ** ** ** Writen by : Gregoire Guye ** ** ** ** Date : 21-02-2005 ** ** ** ** Project : ** ** ** ******************************************************************** ** Changes : ** ******************************************************************** ** Description : 0x LCD driver ** *******************************************************************/ #ifndef __0X_LCDDRIVER__ #define __0X_LCDDRIVER__ /******************************************************************* ** Include files ** *******************************************************************/ #include "Globals.h" /******************************************************************* ** Global definitions ** *******************************************************************/ // Commons waveforms // +_---- F ---+_ #define AB1 0x60 // | | _______| | ____________ #define AB0 0x80 // |_|_ ¦ |_|_ #define BC1 0xC0 // ____| | ___¦____| | ________ #define BC0 0x20 // |_|_ ¦ |_|_ #define CA1 0xA0 // ________| | ¦________| | ____ #define CA0 0x40 // |_|_ |_| // Digits #define #define #define #define D1 D2 D3 D4 3 2 1 0 // // // // Digit1 Digit2 Digit3 Digit4 Xxxx xXxx xxXx xxxX // Special Chars #define #define #define #define #define #define #define #define DP1 K DP2 MINUS DP3 LOBAT DP4 CONT 0 2 3 5 6 8 9 11 // // // // // // // // Decimal point 1 "1" Icon Decimal point 2 "-" Icon Decimal point 3 low bat Icon Decimal point 4 Continuity Icon // Masks #define COMMON_MASK3 0xE0 #define LINE_MASK1 #define LINE_MASK2 0xFF 0x0F // (PB5 to PB7) Mux 3 // (PC0 to PC7) // (PB0 to PB3) // Special #define #define #define #define #define #define #define #define _MINUS 10 _NULL 11 _C 12 _L 13 _E 14 _T 15 _B 16 _N 17 © Semtech 2006 www.semtech.com 22 Application Note AN8000.13 Driving LCD Displays with I/Os © Semtech 2006 All rights reserved. Reproduction in whole or in part is prohibited without the prior written consent of the copyright owner. The information presented in this document does not form part of any quotation or contract, is believed to be accurate and reliable and may be changed without notice. No liability will be accepted by the publisher for any consequence of its use. Publication thereof does not convey nor imply any license under patent or other industrial or intellectual property rights. Semtech. assumes no responsibility or liability whatsoever for any failure or unexpected operation resulting from misuse, neglect improper installation, repair or improper handling or unusual physical or electrical stress including, but not limited to, exposure to parameters beyond the specified maximum ratings or operation outside the specified range. SEMTECH PRODUCTS ARE NOT DESIGNED, INTENDED, AUTHORIZED OR WARRANTED TO BE SUITABLE FOR USE IN LIFE-SUPPORT APPLICATIONS, DEVICES OR SYSTEMS OR OTHER CRITICAL APPLICATIONS. INCLUSION OF SEMTECH PRODUCTS IN SUCH APPLICATIONS IS UNDERSTOOD TO BE UNDERTAKEN SOLELY AT THE CUSTOMER’S OWN RISK. Should a customer purchase or use Semtech products for any such unauthorized application, the customer shall indemnify and hold Semtech and its officers, employees, subsidiaries, affiliates, and distributors harmless against all claims, costs damages and attorney fees which could arise. Contact Information Semtech Corporation Wireless and Sensing Products Division 200 Flynn Road, Camarillo, CA 93012 Phone (805) 498-2111 Fax : (805) 498-3804 © Semtech 2006 www.semtech.com 23