Child pages
  • Using the Segment LCD Controller on the Kinetis KL46
Skip to end of metadata
Go to start of metadata

Table of Contents

Introduction

Multiplexed segment LCD operation isn't necessarily straightforward or easy, even with a peripheral to help with it.  The purpose of this page is to help guide you through the configuration of the Segment LCD controller on the Kinetis KL46.  While the example is done using the LCD on the FRDM-KL46z board, this setup can be used as a reference to help configure the controller for other LCDs as well. 

In the LCD controller each element consists of a front plane segment and a back plane phase.  These 8 phases are labeled A through H.  Each bit controls whether the pin is "active" on a particular phase.  Each LCD_Pn Signal can be connected to multiple segments (in front plane operation) or one or more phases (in back plane operation).  On the FRDM-KL46z, each front plane pin will be connected to 4 segments, while the back plane pin will be active during 2 of 8 phases.  An LCD element is turned on when the associated back plane phase is active along with the front plane segment.

For reference I will be using certain fonts or styles to denote specific things, shown in the following table

StyleMeaningExample
BoldExact wording or buttonClick on Next to continue
ItalicsFilename, Path, or Variable

Now open My_File.c

MonospaceRegister namesSet the 9th bit in SIM_SCGC5

Helpful Links

Reference Information

Kinetis KL46 Reference Manual The section for the SLCD begins on page 863.

Lumex S401M16KR Datasheet This is the display on the FRDM-KL46z.

Example Code

Seg_LCD.h This is the header file with function declarations and definitions

Seg_LCD.c This is the file containing functions and variables

Getting Started

For basic information on registry manipulation on the KL46, please see the eewiki article here.

For this example I will be creating a new project, though it can be entirely incorporated into an existing one.

As I prefer to keep my code as modular as possible, I will be creating a c file for functions and a header file to be included in the main c file.  These will be refered to as SegLCD.c and SegLCD.h for the rest of the page.

I will be using the System_MKL46Z4.c and MKL46Z4.h files included with KEIL uVision4.74.0.0.  These will need to be included for the code to function properly, and information on how to select these can be found in the eewiki article listed above.

Initializing the LCD

LCD Pins on the FRDM-KL46z connect to the LUMEX LCD-S401M16KR in the following manner (from FRDM-KL46Z User Guide)

s401 PinKL46 LCD PinPin Name
1LCD_P40 (COM 0)

PTD0

2LCD_P52 (COM 1)PTE4
3LCD_P19 (COM 2)PTB23
4LCD_P18 (COM 3)PTB22
5LCD_P37PTC17
6LCD_P17PTB21
7LCD_P7PTB7
8LCD_P8PTB8
9LCD_P53PTE5
10LCD_P38PTC18
11LCD_P10PTB10
12LCD_P11PTB11

As such, we don't need to enable PORTA, but all other ports are needed.

Below is my example code for initializing the LCD.  It is included in SegLCD.c, or can simply be copy pasted into your code.  I highly suggest reading it and at least getting a basic understanding of what the registers do so you know what options are available to you. More information on these registers can be found in the KL46 reference manual in the "helpful links" section.

SegLCD_Init
void SegLCD_Init(void){ //Initializes all components of SLCD on the FRDM-KL46Z
 
 SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK | SIM_SCGC5_SLCD_MASK; //Enable Clock to ports B, C, D and E, and SegLCD Peripheral
 LCD->GCR |= LCD_GCR_PADSAFE_MASK; //Set PADSAFE to disable LCD while configuring
 LCD->GCR &= ~LCD_GCR_LCDEN_MASK;  //Clear LCDEN (LCD Enable) while configuring
 
 //Configure pins *From Reference manual, set pins to MUX 0 for normal LCD display operation, only use MUX 7 if using LCD fault detection
 PORTB->PCR[7]  = PORT_PCR_MUX(0u);     //Set PTB7 to LCD_P7
 PORTB->PCR[8]  = PORT_PCR_MUX(0u);     //Set PTB8 to LCD_P8
 PORTB->PCR[10] = PORT_PCR_MUX(0u);     //Set PTB10 to LCD_P10
 PORTB->PCR[11] = PORT_PCR_MUX(0u);     //Set PTB11 to LCD_P11
 PORTB->PCR[21] = PORT_PCR_MUX(0u);     //Set PTB21 to LCD_P17
 PORTB->PCR[22] = PORT_PCR_MUX(0u);     //Set PTB22 to LCD_P18
 PORTB->PCR[23] = PORT_PCR_MUX(0u);     //Set PTB23 to LCD_P19
 PORTC->PCR[17] = PORT_PCR_MUX(0u);     //Set PTC17 to LCD_P37
 PORTC->PCR[18] = PORT_PCR_MUX(0u);     //Set PTC18 to LCD_P38
 PORTD->PCR[0]  = PORT_PCR_MUX(0u);     //Set PTD0 to LCD_P40
 PORTE->PCR[4]  = PORT_PCR_MUX(0u);     //Set PTE4 to LCD_P52
 PORTE->PCR[5]  = PORT_PCR_MUX(0u);     //Set PTE5 to LCD_P53
 
 //Configure LCD Registers
 //Configure LCD_GCR - General Control Register, controls most options in LCD Peripheral
 LCD->GCR =//LCD_GCR_RVEN_MASK |       //Clear LCD_GCR_RVEN, disable voltage regulator.
       LCD_GCR_RVTRIM(0x00) |      //Set RVTRIM to 0, irrelevant as voltage regulator is disabled, but setting it to a known state.
       LCD_GCR_CPSEL_MASK |      //Set LCD_GCR_CPSEL to use capacitor charge pump.
       LCD_GCR_LADJ(0x03) |      //Set LCD_GCR_LADJ to 11, slow clock rate = lower power, but higher load capacitance on the LCD requires higher clock speed.
      //LCD_GCR_VSUPPLY |        //Clear LCD_GCR_VSUPPLY, drive VLL3 externally.
       LCD_GCR_PADSAFE_MASK |     //Set LCD_GCR_PADSAFE, leave enabled during configuration process.
      //LCD_GCR_FDCIEN_MASK |      //Clear LCD_GCR_FDCIEN, No interrupt from fault dection.
       LCD_GCR_ALTDIV(0x00) |     //Set LCD_GCR_ALTDIV to 11, divide alternate clock by 512.  This is assuming an 8MHz External Crystal is used.
      //LCD_GCR_ALTSOURCE_MASK |    //Set LCD_GCR_ALTSOURCE, Part of setting clock source to OSCERCLK, or external oscillator.
       LCD_GCR_FFR_MASK |       //Set LCD_GCR_FFR, allow an LCD Frame Frequency of 46.6Hz to 146.2Hz.  Disable to change range to 23.3Hz to 73.1Hz.
      //LCD_GCR_LCDDOZE_MASK |     //Clear LCD_GCR_LCDDOZE, allows LCD peripheral to run even in doze mode.  Set to disable LCD in doze mode.
      //LCD_GCR_LCDSTP_MASK |      //Clear LCD_GCR_LCDSTP, allows LCD peripheral to run even in stop mode.  Set to disable LCD in stop mode.
      //LCD_GCR_LCDEN_MASK |      //Clear LCD_GCR_LCDEN, Disables all front and backplane pins.  Leave disabled during configuration process.
       LCD_GCR_SOURCE_MASK |      //Set LCD_GCR_SOURCE, Part of setting clock source to OSCERCLK, or external oscillator.
       LCD_GCR_LCLK(0x04) |       //Set LCD_GCR_LCLK to 111, LCD Clock prescaler where LCD controller frame frequency = LCD clock/((DUTY  |  1) x 8 x (4 | LCLK[2:0]) x Y), where Y = 2, 2, 3, 3, 4, 5, 8, 16 chosen by module duty cycle config
       LCD_GCR_DUTY(0x03);        //Set LCD_GCR_DUTY to 011, Have 4 backplane pins, so need a 1/4 duty cycle.
 
 //Configure LCD_SEG_AR  - Auxiliary Register, controls blinking of LCD
 LCD->AR = //LCD_AR_BLINK_MASK |       //Clear LCD_SEG_AR_BLINK, Disable SLCD blinking.  Enable to make LCD Blink.
      //LCD_AR_ALT_MASK |        //Clear LCD_SEG_AR_ALT, if enabled LCD back plane sequencer changes to an alternate display.  Only functional if DUTY[2:0] is less than 100(binary).  This allows a blink screen that is not blank.
      //LCD_AR_BLANK_MASK |       //Clear LCD_SEG_AR_BLANK, asserting bit clears all segments in LCD. 
      //LCD_AR_BMODE_MASK |       //Clear LCD_SEG_AR_BMODE, if enabled displays alternate display during blink period instead of blank.
      LCD_AR_BRATE(0x00);        //Set LCD_SEG_AR_BRATE to 000.  Frequency of blink is determined by LCD clock/(2^(12 + BRATE))
      
 //Configure LCD_SEG_FDCR - Fault Detect Control Register, controls use of Fault Detect features of SLCD.
 LCD->FDCR = 0x00000000;           //Clear all bits in FDCR.  As this will not be covering use of fault detect, this register is cleared.
 
 //Configure LCD_PENn - Pin Enable Register, controls which of the possible LCD pins are used
 //LCD->PEN[0] contains bits 0-31, while LCD->PEN[1] contains bits 32-63.  For pins >= 32, set in LCD->PEN[1] as LCD_PEN_PEN(Pin#-32)
 LCD->PEN[0] =  LCD_PEN_PEN(1u<<7u) |    //LCD_P7
         LCD_PEN_PEN(1u<<8u) |    //LCD_P8
         LCD_PEN_PEN(1u<<10u)|    //LCD_P10
         LCD_PEN_PEN(1u<<11u)|    //LCD_P11
         LCD_PEN_PEN(1u<<17u)|    //LCD_P17
         LCD_PEN_PEN(1u<<18u)|    //LCD_P18
         LCD_PEN_PEN(1u<<19u);    //LCD_P19
 LCD->PEN[1] =  LCD_PEN_PEN(1u<<5u) |    //LCD_P37
         LCD_PEN_PEN(1u<<6u) |    //LCD_P38
         LCD_PEN_PEN(1u<<8u) |    //LCD_P40
         LCD_PEN_PEN(1u<<20u)|    //LCD_P52
         LCD_PEN_PEN(1u<<21u);    //LCD_P53
 
 //Configure LCD_SEG_BPENn - Back Plane Enable Register, controls which pins in LCD->PEN are Back Plane (commons)
 //LCD->BPEN[0] contains bits 0-31, while LCD->BPEN[1] contains bits 32-63.  For pins >= 32, set in LCD->BPEN[1] as LCD_BPEN_BPEN(Pin#-32)
 LCD->BPEN[0] = LCD_BPEN_BPEN(1u<<18u)|   //LCD_P18  COM3
         LCD_BPEN_BPEN(1u<<19u);   //LCD_P19, COM2
 LCD->BPEN[1] = LCD_BPEN_BPEN(1u<<8u) |   //LCD_P40, COM0
         LCD_BPEN_BPEN(1u<<20u);   //LCD_P52, COM1
 
 //Configure LCD_WFyTOx - Configures 4 Waveform signals, LCD_WF[z] is defined such that x = (z*4) and y = 3 | (z*4)
 //Where x is the n index value of WFn on the least significant byte (bits 7-0) and y is the n index value of WFn on the most significant byte (bits 31-24)
 //Note that "Disabled" is used for pins that are not set as LCD pins, where "Off" is used for pins that are set as LCD, but are just inactive.
 LCD->WF[0]  = LCD_WF_WF0(0x00) |      //WF Pin 0 Disabled
         LCD_WF_WF1(0x00) |      //WF Pin 1 Disabled
         LCD_WF_WF2(0x00) |      //WF Pin 2 Disabled
         LCD_WF_WF3(0x00) ;      //WF Pin 3 Disabled
 LCD->WF[1]  = LCD_WF_WF4(0x00) |      //WF Pin 4 Disabled
         LCD_WF_WF5(0x00) |      //WF Pin 5 Disabled
         LCD_WF_WF6(0x00) |      //WF Pin 6 Disabled
         LCD_WF_WF7(0x00) ;      //WF Pin 7 Off
 LCD->WF[2]  = LCD_WF_WF8(0x00) |      //WF Pin 8 Off
         LCD_WF_WF9(0x00) |      //WF Pin 9 Disabled
         LCD_WF_WF10(0x00)|      //WF Pin 10 Off
         LCD_WF_WF11(0x00);      //WF Pin 11 Off
 LCD->WF[3]  = LCD_WF_WF12(0x00)|      //WF Pin 12 Disabled
         LCD_WF_WF13(0x00)|      //WF Pin 13 Disabled
         LCD_WF_WF14(0x00)|      //WF Pin 14 Disabled
         LCD_WF_WF15(0x00);      //WF Pin 15 Disabled
 LCD->WF[4]  = LCD_WF_WF16(0x00)|      //WF Pin 16 Disabled
         LCD_WF_WF17(0x00)|      //WF Pin 17 Off
         LCD_WF_WF18(0x88)|      //WF Pin 18 (COM3) is enabled on Phases D and H
         LCD_WF_WF19(0x44);      //WF Pin 19 (COM2) is enabled on Phases C and G
 LCD->WF[5]  = LCD_WF_WF20(0x00)|      //WF Pin 20 Disabled
         LCD_WF_WF21(0x00)|      //WF Pin 21 Disabled
         LCD_WF_WF22(0x00)|      //WF Pin 22 Disabled
         LCD_WF_WF23(0x00);      //WF Pin 23 Disabled
 LCD->WF[6]  = LCD_WF_WF24(0x00)|      //WF Pin 24 Disabled
         LCD_WF_WF25(0x00)|      //WF Pin 25 Disabled
         LCD_WF_WF26(0x00)|      //WF Pin 26 Disabled
         LCD_WF_WF27(0x00);      //WF Pin 27 Disabled
 LCD->WF[7]  = LCD_WF_WF28(0x00)|      //WF Pin 28 Disabled
         LCD_WF_WF29(0x00)|      //WF Pin 29 Disabled
         LCD_WF_WF30(0x00)|      //WF Pin 30 Disabled
         LCD_WF_WF31(0x00);      //WF Pin 31 Disabled
 LCD->WF[8]  = LCD_WF_WF32(0x00)|      //WF Pin 32 Disabled
         LCD_WF_WF33(0x00)|      //WF Pin 33 Disabled
         LCD_WF_WF34(0x00)|      //WF Pin 34 Disabled
         LCD_WF_WF35(0x00);      //WF Pin 35 Disabled
 LCD->WF[9]  = LCD_WF_WF36(0x00)|      //WF Pin 36 Disabled
         LCD_WF_WF37(0x00)|      //WF Pin 37 Off
         LCD_WF_WF38(0x00)|      //WF Pin 38 Off
         LCD_WF_WF39(0x00);      //WF Pin 39 Disabled
 LCD->WF[10] = LCD_WF_WF40(0x11)|      //WF Pin 40 (COM0) is enabled on Phases A and E
         LCD_WF_WF41(0x00)|      //WF Pin 41 Disabled
         LCD_WF_WF42(0x00)|      //WF Pin 42 Disabled
         LCD_WF_WF43(0x00);      //WF Pin 43 Disabled
 LCD->WF[11] = LCD_WF_WF44(0x00)|      //WF Pin 44 Disabled
         LCD_WF_WF45(0x00)|      //WF Pin 45 Disabled
         LCD_WF_WF46(0x00)|      //WF Pin 46 Disabled
         LCD_WF_WF47(0x00);      //WF Pin 47 Disabled 
 LCD->WF[12] = LCD_WF_WF48(0x00)|      //WF Pin 48 Disabled
         LCD_WF_WF49(0x00)|      //WF Pin 49 Disabled
         LCD_WF_WF50(0x00)|      //WF Pin 50 Disabled
         LCD_WF_WF51(0x00);      //WF Pin 51 Disabled
 LCD->WF[13] = LCD_WF_WF52(0x22)|      //WF Pin 52 (COM1) is enabled on Phases B and F
         LCD_WF_WF53(0x00)|      //WF Pin 53 Off
         LCD_WF_WF54(0x00)|      //WF Pin 54 Disabled
         LCD_WF_WF55(0x00);      //WF Pin 55 Disabled
 LCD->WF[14] = LCD_WF_WF56(0x00)|      //WF Pin 56 Disabled
         LCD_WF_WF57(0x00)|      //WF Pin 57 Disabled
         LCD_WF_WF58(0x00)|      //WF Pin 58 Disabled
         LCD_WF_WF59(0x00);      //WF Pin 59 Disabled
 LCD->WF[15] = LCD_WF_WF60(0x00)|      //WF Pin 60 Disabled
         LCD_WF_WF61(0x00)|      //WF Pin 61 Disabled
         LCD_WF_WF62(0x00)|      //WF Pin 62 Disabled
         LCD_WF_WF63(0x00);      //WF Pin 63 Disabled
        
 //Disable GCR_PADSAFE and Enable GCR_LCDEN
 LCD->GCR &= ~LCD_GCR_PADSAFE_MASK;      //Clear PADSAFE to unlock LCD pins
 LCD->GCR |= LCD_GCR_LCDEN_MASK;       //Set LCDEN to enable operation of LCD
}//End SegLCD_Init 

 

Writing the Control Library

Now that we have an initialization function, we still need functions to use the LCD.  A bit of the operation was discussed in the introduction, and more information can be found in the reference manual pages 918-919.

 As our backplanes are already set from the initialization function, we know that COM0 is on phase A, COM1 on phase B, COM2 on phase C, and COM3 on phase D. On the FRDM-KL46z, each character is controlled by two pins, so we can determine what segments will be on from the following table.  For each character, Pin 1 is (Digit*2 - 1) and Pin 2 is Digit*2.

 Pin 1Pin 2
A (COM0)DDecimal/Colon
B (COM1)EC
C (COM2)GB
D (COM3)FA

So if we wanted segments A, B, D, E and G (the number 2) lit on the third digit, we would have to set WF8B[53] and WF8B[37], the 5th and 6th frontplane pins, to 0x77 and 0xCC respectively.  This will make pin 5 active on phases A, B and C (segments D E and G) and pin 6 on phases C and D (segments A and B).

 In the helpful links and downloads section I have included a SegLCD.c and SegLCD.h, which have some basic functions included.  I have them listed below and will briefly describe the functionality and dependencies of each.

 Variable Definitions and Macros

These macros define how many pins are on the LCD, how each segment needs to be manipulated, a mapping from LCD pins to Microcontroller pins and inline functions for turning decimals and the colon on and off. These should be placed in the header file for the LCD functions.

Macros
//Define Number of Front and Back plane pins
#define LCD_NUM_FRONTPLANE_PINS 8
#define LCD_NUM_BACKPLANE_PINS 4
//Create macros for segments
#define LCD_SEG_D 0x11
#define LCD_SEG_E 0x22
#define LCD_SEG_G 0x44
#define LCD_SEG_F 0x88
#define LCD_SEG_DECIMAL 0x11
#define LCD_SEG_C 0x22
#define LCD_SEG_B 0x44
#define LCD_SEG_A 0x88
#define LCD_CLEAR 0x00
//Create Macros for each pin
#define LCD_FRONTPLANE0 37u
#define LCD_FRONTPLANE1 17u
#define LCD_FRONTPLANE2 7u
#define LCD_FRONTPLANE3 8u
#define LCD_FRONTPLANE4 53u
#define LCD_FRONTPLANE5 38u
#define LCD_FRONTPLANE6 10u
#define LCD_FRONTPLANE7 11u
#define LCD_BACKPLANE0 40u
#define LCD_BACKPLANE1 52u
#define LCD_BACKPLANE2 19u
#define LCD_BACKPLANE3 18u
//Macros for turning decimal points and colon on and off
#define SegLCD_DP1_On() LCD->WF8B[LCD_FRONTPLANE1]  |= LCD_SEG_DECIMAL;
#define SegLCD_DP1_Off() LCD->WF8B[LCD_FRONTPLANE1] &= ~LCD_SEG_DECIMAL;
#define SegLCD_DP2_On() LCD->WF8B[LCD_FRONTPLANE3]  |= LCD_SEG_DECIMAL;
#define SegLCD_DP2_Off() LCD->WF8B[LCD_FRONTPLANE3] &= ~LCD_SEG_DECIMAL;
#define SegLCD_DP3_On() LCD->WF8B[LCD_FRONTPLANE5]  |= LCD_SEG_DECIMAL;
#define SegLCD_DP3_Off() LCD->WF8B[LCD_FRONTPLANE5] &= ~LCD_SEG_DECIMAL;
#define SegLCD_Col_On() LCD->WF8B[LCD_FRONTPLANE7]  |= LCD_SEG_DECIMAL;
#define SegLCD_Col_Off() LCD->WF8B[LCD_FRONTPLANE7] &= ~LCD_SEG_DECIMAL;

 

These variables take information from the header file and make two arrays indexing pin number on the LCD to pin number on the microcontroller.  These should be place at the top of your C file containing the functions. 

Variable Definitions
const static uint8_t LCD_Frontplane_Pin[LCD_NUM_FRONTPLANE_PINS] = {LCD_FRONTPLANE0, LCD_FRONTPLANE1, LCD_FRONTPLANE2, LCD_FRONTPLANE3, LCD_FRONTPLANE4, LCD_FRONTPLANE5, LCD_FRONTPLANE6, LCD_FRONTPLANE7};
const static uint8_t LCD_Backplane_Pin[LCD_NUM_BACKPLANE_PINS] = {LCD_BACKPLANE0, LCD_BACKPLANE1, LCD_BACKPLANE2, LCD_BACKPLANE3};
 SegLCD_Set

Dependencies

This function is dependent on the variable "LCD_Frontplane_Pin" which is defined in SegLCD.c.  This variable holds which LCD pins map to which Microcontroller pins.  This is not removable without a serious rework.

Dependency

This function is dependent on the SegLCD_DisplayError function!  This is removable by removing or commenting out the "If(Digit > 4)" if statement, but will cause an input of Digit > 4 to create undefined behavior.

 

SegLCD_Set takes Value and places it in the Digit slot of the LCD, with 1 being the leftmost, 4 being the rightmost.  This does not alter any of the other digits, though it will clear decimals and colons on that digit.

 It will display "Err" if Digit is greater than 4.  If Value is greater than 15 it will NOT display an error and will not change the display. 

SegLCD_Set
void SegLCD_Set(uint8_t Value,uint8_t Digit){//Sets a value from 0-F to a specified Digit, with 1 being the leftmost, 4 being the rightmost. Will not display error is Value is outside of 0-F, but display will not update
 if(Digit > 4){
 SegLCD_DisplayError(0x01);
 } //Display "Err" if trying to access a digit that does not exist
 else{
 if(Value==0x00) {LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E |LCD_SEG_F); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x01){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_CLEAR); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x02){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B);}
 else if(Value==0x03){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x04){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x05){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_C);}
 else if(Value==0x06){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_C);}
 else if(Value==0x07){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_CLEAR); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x08){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x09){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x0A){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_E | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = (LCD_SEG_A | LCD_SEG_B | LCD_SEG_C);}
 else if(Value==0x0B){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = LCD_SEG_C;}
 else if(Value==0x0C){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_F); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = LCD_SEG_A;}
 else if(Value==0x0D){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = LCD_SEG_B | LCD_SEG_C;}
 else if(Value==0x0E){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = LCD_SEG_A;}
 else if(Value==0x0F){LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-2)]] = (LCD_SEG_E | LCD_SEG_F | LCD_SEG_G); LCD->WF8B[LCD_Frontplane_Pin[((2*Digit)-1)]] = LCD_SEG_A;}
 }
}//End SegLCD_Set

 

 

 SegLCD_DisplayDecimal

Dependency

This function is dependent on the SegLCD_Set function!  This is not removable without a serious rework.

Dependency

This function is dependent on the SegLCD_DisplayError function!  This is removable by removing or commenting out the "If(Value > 9999)" if statement and making the else statement the main block of code, but will cause inputs greater than 4 digits to display undefined behavior.

SegLCD_DisplayDecimal takes Value and displays it to the screen in decimal. If the number is greater than 4 digits it will display "Err". If Value is less than 4 digits there will be leading zeros.

SegLCD_DisplayDecimal
void SegLCD_DisplayDecimal(uint16_t Value){//Displays a 4 Digit number in decimal
 if(Value > 9999){
  SegLCD_DisplayError(0x10); //Display "Err" if value is greater than 4 digits
 }
 else{
  SegLCD_Set(Value/1000,1);
  SegLCD_Set((Value - (Value/1000)*1000)/100,2);
  SegLCD_Set((Value - (Value/100)*100)/10,3);
  SegLCD_Set(Value - (Value/10)*10,4);
 }
}//End SegLCD_Display4Digit

 

 

 

 SegLCD_DisplayHex

SegLCD_DisplayHex takes Value and displays it in hexadecimal on the LCD.  If Value is less than 0x1000 it will display leading zeros.

SegLCD_DisplayHex
void SegLCD_DisplayHex(uint16_t Value){ //Displays a 16 bit number in Hex Format
 SegLCD_Set((Value & 0xF000)>>12, 1);
 SegLCD_Set((Value & 0x0F00)>>8 , 2);
 SegLCD_Set((Value & 0x00F0)>>4 , 3);
 SegLCD_Set((Value & 0x000F)>>0 , 4);
}//End SegLCD_DisplayHex
 SegLCD_DisplayTime

Dependency

This function is dependent on the SegLCD_Set function!  This is not removable without a serious rework.

Dependency

This function is dependent on the SegLCD_DisplayError function!  This is removable by removing or commenting out the "If((Value1 > 99) | (Value2 > 99))" if statement and making the else statement the main block of code, but will cause inputs greater than 2 digits to display undefined behavior.

Dependency

This function is dependent on the SegLCD_Col_On() macro!  This is removable by removing or commenting out the line "SegLCD_Col_On();" and replacing it with an equivalent way of turning the colon on.

SegLCD_DisplayTime displays Value1, then Value2 to the screen separated by a colon.  This was originally intended to display time (as seen by the name) but can be used for other purposes. If Value1 or Value2 are greater than 2 digits it will display "Err".

SegLCD_DisplayTime
void SegLCD_DisplayTime(uint8_t Value1, uint8_t Value2){//Displays 2 values separated by a colon
 if((Value1 > 99) | (Value2 > 99)){
  SegLCD_DisplayError(0x10); //Display "Err" if either value is greater than 2 digits
 }
 else{
  SegLCD_Set(Value1/10, 1);
  SegLCD_Set(Value1 % 10, 2);
  SegLCD_Set(Value2/10, 3);
  SegLCD_Set(Value2 % 10, 4);
  SegLCD_Col_On();
 }
}//End SegLCD_DisplayTime
 SegLCD_DisplayError

Dependency

This function is dependent on the SegLCD_Set function!  This is  removable by removing or commenting out the "If(ErrorNum < 0x10)" if statement, moving the else statement to the main code, and changing the input from "uint8_t ErrorNum" to "void".  This will cause the function to only display "Err" without a number.

The SegLCD_DisplayError function displays "Err#" to the LCD, where # is ErrorNum. If ErrorNum is greater than 0x0F, it will simply display Err.

SegLCD_DisplayError
void SegLCD_DisplayError(uint8_t ErrorNum){//Displays Err# on screen, where # is a value 0-F.  If ErrorNum is outside of that range, just displays Err
 LCD->WF8B[LCD_FRONTPLANE0] = (LCD_SEG_D | LCD_SEG_E | LCD_SEG_F | LCD_SEG_G);
 LCD->WF8B[LCD_FRONTPLANE1] = (LCD_SEG_A);
 LCD->WF8B[LCD_FRONTPLANE2] = (LCD_SEG_E | LCD_SEG_G);
 LCD->WF8B[LCD_FRONTPLANE3] = (LCD_CLEAR);
 LCD->WF8B[LCD_FRONTPLANE4] = (LCD_SEG_E | LCD_SEG_G);
 LCD->WF8B[LCD_FRONTPLANE5] = (LCD_CLEAR);
 if(ErrorNum < 0x10){
  SegLCD_Set(ErrorNum,4); //Display ErrorNum in digit 4 if within valid range.  If not, leave blank.
 }
 else{
  LCD->WF8B[LCD_FRONTPLANE6] = (LCD_CLEAR);
  LCD->WF8B[LCD_FRONTPLANE7] = (LCD_CLEAR);
 }
}//End SegLCD_DisplayError

 

Contact and Other Info

I hope you found this article helpful and insightful.  If you have any issues or think something should be added to this article please contact me at eewiki@digikey.com.

A thank you to our sponsor at digikey.com.  If you want to help out the EE wiki, click a link or two to the digikey website or just browse around other EEwiki articles.  Continued interest helps show that the EEwiki is a valuable tool and worth supporting.

-Ethan

 

  • No labels