/*----------------------------------------------------------------------------*/ /* LCD initialization and data transfer routines */ /* 4-bit bus version */ /* Filename: lcd_lib_4bit_rev3_brd.c */ /* Author: Larry Aamodt */ /* Version: 1/25/19 written */ /* 1/28/19 updated */ /* 1/29/20 updatedi */ /* 2/12/20 revised LCD control signal port & pins */ /* 2/21/20 added string display, hex, & decimal routines */ /* 4/04/22 minor source code format updates. No functional change */ /* 5/12/22 revised for rev 3 i/o board. contrl pins changed */ /* Compiler: Keil uVision5 */ /* Hardware: NXP Freedom board and a 8-column x 2-row LCD display */ /* PORT C bits 13,16,17 used for control */ /* PORT C bits 0,1,2,3 used for data */ /* Software note: A software loop is used for time delay generation */ /* Port C clocks are now turned on here during init */ /* function use: call LCD_command to move the cursor, clear screen, etc. */ /* call LCD_send_data to send one ASCII character code */ /* Includes functions to display the following: */ /* - a string of characters */ /* - display 4 hex digits from an unsigned 32 bit int */ /* - display 8 hex digits from an unsigned 32 bit int */ /* - display a decimal number in N digits from an */ /* unsigned 32 bit int (N= 1 to 7) */ /*----------------------------------------------------------------------------*/ #include #include #define LCD_EN 0x00002000 // PTC13 LCD enable #define LCD_RW 0x00010000 // PTC16 LCD read/write #define LCD_RS 0x00020000 // PTC17 LCD RS #define LCD_LOW4_MASK 0x0000000F // low 4 bits of a command #define LCD_UPPER4_MASK 0x000000F0 // upper 4 bits of a command #define LCD_MASK 0x0000000F // PortC bits 0-3 #define LCD_DATA_PINS 0x0000000F // PortC LCD data pins #define LCD_CNTRL_PINS 0x00032000 // PortC LCD control pins #define GPIO 1 #define clear_screen 0x01 #define cursor_left 0x10 #define cursor_right 0x14 #define cursor_line1 0x80 #define cursor_line2 0xC0 /*---------------------------------------------------------------------------- LCD function prototypes *----------------------------------------------------------------------------*/ void LCD_display_string(char dstr[]); // display a char string on LCD void LCD_display_hex16(uint32_t data); // display a 16-bit number in hex void LCD_display_hex32(uint32_t data); // display a 32-bit number in hex void LCD_display_decimal(uint32_t data, uint32_t numdig); // display decimal # void LCD_command(uint32_t command); // use to send LCD commands void LCD_send_data(uint32_t data); // use to send one char to screen void delayMs(uint32_t n); void pulse_the_LCD_enable(void); void LCD_init(void); /*---------------------------------------------------------------------------- * Display a string of characters on the LCD display L.Aamodt * *----------------------------------------------------------------------------*/ void LCD_display_string(char dstr[]) { uint32_t i; i=0; while (dstr[i] != 0){ LCD_send_data(dstr[i]); i++; } } /*---------------------------------------------------------------------------- * Display a 16 bit number in hexadecimal on the LCD display L.Aamodt **----------------------------------------------------------------------------*/ void LCD_display_hex16(uint32_t data) { uint32_t i, temp, mask; mask = 0x0f000; for (i=12; i>0; i=i-4) { temp = (data & mask); temp >>= i; temp = temp + 48; // 48 is ASCII 0 if (temp > 57) temp = temp + 7; // 65 is ASCII A LCD_send_data(temp); mask >>= 4; } temp = (data & mask); temp = temp + 48; if (temp > 57) temp = temp +7; LCD_send_data(temp); } /*---------------------------------------------------------------------------- * Display a 32 bit number in hexadecimal on the LCD display L.Aamodt **----------------------------------------------------------------------------*/ void LCD_display_hex32(uint32_t data) { uint32_t i, temp, mask; mask = 0x0f0000000; for (i=28; i>0; i=i-4) { temp = (data & mask); temp >>= i; temp = temp + 48; // 48 is ASCII 0 if (temp > 57) temp = temp + 7; // 65 is ASCII A LCD_send_data(temp); mask >>= 4; } temp = (data & mask); temp = temp + 48; if (temp > 57) temp = temp +7; LCD_send_data(temp); } /*---------------------------------------------------------------------------- * Display a positive number in decimal on the LCD display L.Aamodt * Two parameters: (number, number-of-digits-to-display) **----------------------------------------------------------------------------*/ void LCD_display_decimal(uint32_t data, uint32_t numdig) { int32_t i; uint32_t array[10]; for (i=numdig; i>0; i--) { array[i-1] = data%10; data = data/10; } for (i=0; iSCGC5 |= SIM_SCGC5_PORTC_MASK;; uint32_t k; // First set up bits in GPIO Port C used by the LCD for (k=0; k<4; k++) { // make ports GPIO PORTC->PCR[k] &= ~PORT_PCR_MUX_MASK; // 4 LCD data bits PORTC->PCR[k] |= PORT_PCR_MUX(GPIO); } for (k=16; k<18; k++) { // make ports GPIO PORTC->PCR[k] &= ~PORT_PCR_MUX_MASK; // LCD control (3-bits total) PORTC->PCR[k] |= PORT_PCR_MUX(GPIO); } PORTC->PCR[13] &= ~PORT_PCR_MUX_MASK; // more control pins PORTC->PCR[13] |= PORT_PCR_MUX(GPIO); PTC->PDDR |= LCD_DATA_PINS; // set ports to output PTC->PDDR |= LCD_CNTRL_PINS; PTC->PCOR = LCD_RW | LCD_RS | LCD_EN; // clear R/W, RS, and EN // Now initialize the LCD itself delayMs(00); PTC->PCOR = LCD_MASK; // clear output data bits to 0 PTC->PSOR = (0x3); // put a wake-up value on bus delayMs(10); pulse_the_LCD_enable(); delayMs(1); pulse_the_LCD_enable(); delayMs(1); pulse_the_LCD_enable(); delayMs(1); PTC->PCOR = LCD_MASK; // clear output data bits to 0 PTC->PSOR = (0x2); // initialize to 4-bit bus mode delayMs(10); pulse_the_LCD_enable(); LCD_command(0x28); // Set to 4-bit/2-line/5x7pixels LCD_command(0x10); // LCD_command(0x0F); // Display on, cursor on and blink LCD_command(0x06); // } /*---------------------------------------------------------------------------- Send a command to the LCD L.Aamodt *----------------------------------------------------------------------------*/ void LCD_command(uint32_t command) { PTC->PCOR = LCD_RW | LCD_RS | LCD_EN; // clear R/W, RS, and EN PTC->PCOR = LCD_MASK; // clear output data bits to 0 PTC->PSOR = (command & LCD_UPPER4_MASK)>>4; // output upper 4 bits of command pulse_the_LCD_enable(); PTC->PCOR = LCD_MASK; // clear output data bits PTC->PSOR = (command & LCD_LOW4_MASK); // output lower 4 bits pulse_the_LCD_enable(); if (command < 4) delayMs(3); // command 1 and 2 need 1.64ms else delayMs(1); // all others 40us } /*---------------------------------------------------------------------------- Pulse the LCD enable line L.Aamodt *----------------------------------------------------------------------------*/ void pulse_the_LCD_enable(void) { PTC->PSOR = LCD_EN; // assert enable delayMs(1); PTC->PCOR = LCD_EN; // de-assert enable } /*---------------------------------------------------------------------------- Send data (one character, using ASCII code) to the LCD L.Aamodt *----------------------------------------------------------------------------*/ void LCD_send_data(uint32_t data) { PTC->PCOR = LCD_RW | LCD_EN; // clear R/W, RS, and EN PTC->PSOR = LCD_RS; // set RS high PTC->PCOR = LCD_MASK; // clear output data bits to 0 PTC->PSOR = (data & LCD_UPPER4_MASK)>>4; // output upper 4 bits of command pulse_the_LCD_enable(); PTC->PCOR = LCD_MASK; // clear output data bits PTC->PSOR = (data & LCD_LOW4_MASK); // output lower 4 bits pulse_the_LCD_enable(); } /*---------------------------------------------------------------------------- Delay, used with the LCD routines. Delay specified in units of milliseconds The inner loop max count should be 3500 for 20.97 MHZ system clock rate or 8000 for 48 MHZ system clock rate L.Aamodt *----------------------------------------------------------------------------*/ void delayMs(uint32_t n) { uint32_t i; uint32_t j; for(i=0; i < n; i++) for(j=0; j < 8000; j++) {} }