PIC18F14K50: Pantalla LCD 16x2 (HD44780)

Page 1

Por: Omar Gurrola

2/26/13

http://www.proprojects.wordpress.com

PIC18F14K50: Pantalla LCD 16x2 (HD44780) Existen muchos tipos de pantallas con diferentes características, pero en esta ocasión trabajaremos con una pantalla LCD de 16x2 (16 caracteres por 2 líneas) con luz trasera.

Este tipo de LCDs permiten trabajar en modo de 8 bits (D0-D7) y 4 bits (D4-D7), comúnmente se trabaja con cuatro para reducir la cantidad de pines requeridos por el uC. También permite escribir y leer con el pin R/W pero será mandado a tierra para escribir en el únicamente. Para trabajar con este LCD disponemos de varias librerías que se pueden utilizar: 1. Microchip C18 <xlcd.h>: Intente utilizar esta librería y al parecer tiene el problema de que siempre utiliza el PORB para los datos a pesar de cambiarlos en la cabecera, por lo que no pude utilizarla. 2. Microchip Application Maestro <xlcd.h>: Esta aplicación nos permite crear librerías personalizadas para varios dispositivos, entre ellos el LCD. La librería está bien optimizada pero es muy básica, tú debes crear tus funciones adicionales como la de gotoxy, etc. Y también debes conocer los comandos que le puedes mandar. 3. Armandas <HD44780.h>: Librería diseñada por Armandas Jarusauskas. Tiene todas las funciones básicas implementadas como: lcd_command, lcd_write, lcd_write_pgm, lcd_goto, lcd_add_character, lcd_clear, lcd_return_home, lcd_display_on/off, lcd_cursor_on/off, lcd_blinking_on/off, lcd_backlight_on, etc. Esta libreria pesa alrededor de 275 Bytes más que la de Microchip Aplication Maestro. Para facilitarnos el trabajo utilizaremos la librería número 3 de armandas con unas modificaciones que realice. Para configurar la librería realizar los siguientes cambios en la cabecera < HD44780.h>. 1. 2. 3. 4. 5. 6. 7. 8.

Lo primero es ajustar el número de líneas y caracteres del LCD, en este caso 2 y 16. Si no se piensa leer del LCD comentar //#define LCD_RW_MODE para no utilizar el pin R/W. Si no se piensa controlar la luz de iluminación con el uC comentar //#define LCD_HAS_BACKLIGHT. Si los pines que utilizaremos del puerto no son la parte baja debemos realizar un corrimiento, definirlo en DATA_SHIFT con la cantidad de corrimientos necesarios. Si se necesita, cambiar las direcciones de cada inicio de línea para el gotoxy. Definir el StartUpCode. Esta línea sirve para realizar ajustes previos a cualquier puerto que necesitemos, por ejemplo desactivar los análogos del puerto que se utilizara con el LCD. Realizar los cambios de puertos y pines para D4-D7, S y E. Luego tenemos que ajustar los tiempos de retardos requeridos utilizando la librería <delay.h> o cualquier otro método de retardo: a. > 40 ns b. > 50 us


Por: Omar Gurrola 2/26/13 c. > 250 us d. > 1.6 ms e. ~ 10 ms 9. Con eso está configurada la librería y lista para ser usada en main.c.

http://www.proprojects.wordpress.com

HD44780.h /** * Driver library for HD44780-compatible LCD displays. * https://github.com/armandas/Yet-Another-LCD-Library * * Author: Armandas Jarusauskas (http://projects.armandas.lt) * * Contributors: * Sylvain Prat (https://github.com/sprat) * * This work is licensed under a * Creative Commons Attribution 3.0 Unported License. * http://creativecommons.org/licenses/by/3.0/ * */ /** Mod. By: Omar Gurrola www.proprojects.wordpress.com 2/26/13 - Added #if DATA_SHIFT > 0 to shift (To remove warning) - Added LCD_RW_MODE if you use RW pin otherwise connecto to 0 (GND) - Added StartUpCode in lcd_init() - Added LCD_START_DELAY() to stablize when power on. - Changed algorith for lcd_gotoxy(), because don't work right for 20x4 LCD **/ /******************************* CONFIG ***************************************/ #include "wait.h" #include "pic18f14k50_io.h" // number of lines on the LCD #define LCD_LINES 2 #define LCD_CHARACTERS 16 // If you will use RW pin otherwise comment it //#define LCD_RW_MODE // If you will control backlight with a pin //#define LCD_HAS_BACKLIGHT // data mask // this must match the data pins on the port // this program uses 4 lower bits of PORT #define DATA_MASK 0b00001111 // if you don't use the lower four pins // for your data port, your data will have // to be shifted. // number of left shifts to do: #define DATA_SHIFT 0 // Lines directions for gotoxy function #define LCD_LINEDEF_DIR 0x00 // If other than 1-4 is selected #define LCD_LINE1_DIR 0x00 #define LCD_LINE2_DIR 0x40 #define LCD_LINE3_DIR 0x14 #define LCD_LINE4_DIR 0x54 // Define StartUp Code Code if you need // Like AD disable, etc. #define StartUpCode() OpenOutPC() // pins #define LCD_DATA #define LCD_DATA_DDR

LATC TRISC

#define LCD_EN #define LCD_EN_DDR

LATCbits.LATC4 TRISCbits.TRISC4

#define LCD_RS #define LCD_RS_DDR

LATCbits.LATC5 TRISCbits.TRISC5

#ifdef LCD_RW_MODE #define LCD_RW #define LCD_RW_DDR #endif

TRISGbits.TRISG3 LATGbits.LATG3

#ifdef LCD_HAS_BACKLIGHT


Por: Omar Gurrola

2/26/13

#define LCD_BL_DDR #define LCD_BL #endif

TRISGbits.TRISG4 LATGbits.LATG4

// timings: depend on the instruction clock speed #define LCD_ADDRESS_SETUP_DELAY() Nop() // > 40 ns #define LCD_EXECUTION_DELAY() Wait50us() // > 50 us #define LCD_ENABLE_PULSE_DELAY() Wait250us() // > 250 ns #define LCD_HOME_CLEAR_DELAY() Waitmsx(2) // > 1.6 ms #define LCD_START_DELAY() Waitmsx(10) // ~ 10 ms /******************************* END OF CONFIG ********************************/ // commands #define CLEAR_DISPLAY #define RETURN_HOME #define ENTRY_MODE #define DISPLAY_CONTROL #define CURSOR_DISPLAY_SHIFT #define FUNCTION_SET #define SET_CGRAM_ADDR #define SET_DDRAM_ADDR

0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80

// ENTRY_MODE flags #define CURSOR_INCREMENT #define ENABLE_SHIFTING

0x02 0x01

// DISPLAY_CONTROL flags #define DISPLAY_ON #define CURSOR_ON #define BLINKING_ON

0x04 0x02 0x01

// CURSOR_DISPLAY_SHIFT flags #define DISPLAY_SHIFT #define SHIFT_RIGHT

0x08 0x04

// FUNCTION_SET flags #define DATA_LENGTH #define DISPLAY_LINES #define CHAR_FONT

0x10 0x08 0x04

// function prototypes void lcd_flags_set(unsigned char, unsigned char, unsigned char); void lcd_initialize(void); void lcd_command(unsigned char); void lcd_data(unsigned char); void lcd_write(char *); void lcd_write_pgm(const rom char *); void lcd_goto(unsigned char, unsigned char); void lcd_add_character(unsigned char, unsigned char *); // inline functions #define lcd_clear() #define lcd_return_home()

lcd_command(CLEAR_DISPLAY); LCD_HOME_CLEAR_DELAY() lcd_command(RETURN_HOME); LCD_HOME_CLEAR_DELAY()

#define #define #define #define #define #define

lcd_flags_set(DISPLAY_CONTROL, lcd_flags_set(DISPLAY_CONTROL, lcd_flags_set(DISPLAY_CONTROL, lcd_flags_set(DISPLAY_CONTROL, lcd_flags_set(DISPLAY_CONTROL, lcd_flags_set(DISPLAY_CONTROL,

lcd_display_on() lcd_display_off() lcd_cursor_on() lcd_cursor_off() lcd_blinking_on() lcd_blinking_off()

#ifdef LCD_HAS_BACKLIGHT #define lcd_backlight_on() LCD_BL = 1 #define lcd_backlight_off() LCD_BL = 0 #endif

DISPLAY_ON, 1) DISPLAY_ON, 0) CURSOR_ON, 1) CURSOR_ON, 0) BLINKING_ON, 1) BLINKING_ON, 0)

http://www.proprojects.wordpress.com


Por: Omar Gurrola

2/26/13

http://www.proprojects.wordpress.com

HD44780.c /** * Driver library for HD44780-compatible LCD displays. * https://github.com/armandas/Yet-Another-LCD-Library * * Author: Armandas Jarusauskas (http://projects.armandas.lt) * * Contributors: * Sylvain Prat (https://github.com/sprat) * * This work is licensed under a * Creative Commons Attribution 3.0 Unported License. * http://creativecommons.org/licenses/by/3.0/ * */ /** Mod. By: Omar Gurrola www.proprojects.wordpress.com 2/26/13 - Added #if DATA_SHIFT > 0 to shift - Added LCD_RW_MODE if you use RW pin otherwise connecto to 0 (GND) - Added StartUpCode in lcd_init() - Added LCD_START_DELAY() to stablize when power on. - Changed algorith for lcd_gotoxy(), because don't work right for 20x4 LCD **/ #include "HD44780.h" // private function prototypes static void _send_nibble(unsigned char); static void _send_byte(unsigned char); static void _set_4bit_interface(); // global variables unsigned char display_config[6]; // private utility functions static void _send_nibble(unsigned #if DATA_SHIFT > 0 data <<= DATA_SHIFT; #endif LCD_DATA &= ~DATA_MASK; LCD_DATA |= DATA_MASK & data;

char data) { // shift the data as required // clear old data bits // put in new data bits

LCD_EN = 1; LCD_ENABLE_PULSE_DELAY(); LCD_EN = 0; LCD_ENABLE_PULSE_DELAY(); } static void _send_byte(unsigned char data) { _send_nibble(data >> 4); _send_nibble(data & 0x0F); } static void _set_4bit_interface() { LCD_RS = 0; #ifdef LCD_RW_MODE LCD_RW = 0; #endif LCD_ADDRESS_SETUP_DELAY(); _send_nibble(0b0010); LCD_EXECUTION_DELAY(); } /** * Display string stored in RAM * * Usage: * char message[10] = "Hello"; * lcd_write(message); */ void lcd_write(char * str) { unsigned char i = 0; while (str[i] != '\0') lcd_data(str[i++]); } /** * Display string stored in program memory * * Usage: * lcd_write_pgm("Hello"); */


Por: Omar Gurrola

2/26/13

void lcd_write_pgm(const rom char * str) { unsigned char i = 0; while (str[i] != '\0') lcd_data(str[i++]); } /** * Move cursor to a given location */ void lcd_goto(unsigned char row, unsigned char col) { unsigned char addr; switch(row){ case 1: addr = LCD_LINE1_DIR; break; case 2: addr = LCD_LINE2_DIR; break; case 3: addr = LCD_LINE3_DIR; break; case 4: addr = LCD_LINE4_DIR; break; default:addr = LCD_LINEDEF_DIR; break; } addr += col - 1; lcd_command(SET_DDRAM_ADDR | addr); } /** * Add a custom character */ void lcd_add_character(unsigned char addr, unsigned char * pattern) { unsigned char i; lcd_command(SET_CGRAM_ADDR | addr << 3); for (i = 0; i < 8; i++) lcd_data(pattern[i]); } /** * Lousy function for automatic LCD initialization */ void lcd_initialize(void) { unsigned char i; // Run StartUp Code first StartUpCode(); // Wait some time LCD_START_DELAY(); // set relevant pins as outputs LCD_DATA_DDR = ~DATA_MASK; LCD_RS_DDR = 0; #ifdef LCD_RW_MODE LCD_RW_DDR = 0; #endif LCD_EN_DDR = 0; #ifdef LCD_HAS_BACKLIGHT LCD_BL_DDR = 0; #endif // initialize the display_config for (i = 0; i < 6; i++) { display_config[i] = 0x00; } _set_4bit_interface(); // function set lcd_flags_set(FUNCTION_SET, DATA_LENGTH | CHAR_FONT, 0); lcd_flags_set(FUNCTION_SET, DISPLAY_LINES, 1); #ifdef LCD_HAS_BACKLIGHT lcd_backlight_on(); #endif lcd_display_on(); lcd_cursor_off(); lcd_blinking_off(); lcd_flags_set(ENTRY_MODE, CURSOR_INCREMENT, 1); lcd_flags_set(ENTRY_MODE, ENABLE_SHIFTING, 0); lcd_clear(); lcd_return_home(); }

http://www.proprojects.wordpress.com


Por: Omar Gurrola void lcd_command(unsigned char command) { LCD_RS = 0; #ifdef LCD_RW_MODE LCD_RW = 0; #endif LCD_ADDRESS_SETUP_DELAY(); _send_byte(command); LCD_EXECUTION_DELAY(); } void lcd_data(unsigned char data) { LCD_RS = 1; #ifdef LCD_RW_MODE LCD_RW = 0; #endif LCD_ADDRESS_SETUP_DELAY(); _send_byte(data); LCD_EXECUTION_DELAY(); } void lcd_flags_set(unsigned char instruction, unsigned char flags, unsigned char value) { unsigned char index; switch (instruction) { case ENTRY_MODE: index = 0; break; case DISPLAY_CONTROL: index = 1; break; case CURSOR_DISPLAY_SHIFT: index = 2; break; case FUNCTION_SET: index = 3; break; case SET_CGRAM_ADDR: index = 4; break; case SET_DDRAM_ADDR: index = 5; break; } if (value == 0) display_config[index] &= ~flags; // reset flags else display_config[index] |= flags; // set flags lcd_command(instruction | display_config[index]); }

2/26/13

http://www.proprojects.wordpress.com


Por: Omar Gurrola main.c /* * * * * * * * * * * * * * * * * * * * * * */

2/26/13

http://www.proprojects.wordpress.com

Copyright (c) 2011-2013, http://www.proprojects.wordpress.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1.- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2.- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/********************************************************************************** * Author: Omar Gurrola * Site: http://www.proprojects.wordpress.com * Processor: PIC18 * Compiler: C18 v3.45 * File Name: main.c * Description: Main program * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Rev. Date Comment * 1.0 04/01/12 Initial version * 1.1 01/29/13 Remove ISR prototipes, they are declared in hid_bl.h *********************************************************************************/ /** INCLUDES *******************************************************/ #include <p18f14k50.h> #include "pic18f14k50_cbits.h" #include "pic18f14k50_io.h" #include "stdvars.h" #include "wait.h" #include "HD44780.h" /** DECLARATIONS ***************************************************/ #pragma code // Forces the code below this line to be put into the code section (Memory Adress >= 0x'REMDIR'02A) /** Interrupt Service Routines (ISR)********************************/ #pragma interrupt HighPriorityISR void HighPriorityISR (void){ //Check which interrupt flag caused the interrupt. //Service the interrupt //Clear the interrupt flag //Etc. } //This return will be a "retfie fast", since this is in a #pragma interrupt section #pragma interruptlow LowPriorityISR void LowPriorityISR (void){ //Check which interrupt flag caused the interrupt. //Service the interrupt //Clear the interrupt flag //Etc. }

//This return will be a "retfie", since this is in a #pragma interruptlow section

void main(void){ char data[]="Omar Gurrola"; OSCCONbits.IRCF = 0b110; OSCTUNEbits.SPLLEN = 1;

// Poscaler selected to 8 MHz // PLLx4 Enable System FQ = 32 MHz

lcd_initialize(); lcd_goto(1,3); lcd_write(data); lcd_goto(2,3); lcd_write_pgm("Pro Projects"); while(true){ ; } // end while } // end main()

// String in RAM // String in ROM


Por: Omar Gurrola Diagrama esquemรกtico:

Circuito armado:

2/26/13

http://www.proprojects.wordpress.com


Por: Omar Gurrola

2/26/13

Referencias 

Microchip, “PIC18F/LF1XK50 Data Sheet”, 2010, http://ww1.microchip.com/downloads/en/DeviceDoc/41350E.pdf

Hitachi, “HD44780U (LCD-II) Data Sheet” http://www.sparkfun.com/datasheets/LCD/HD44780.pdf

Armandas, “HD44780 LCD driver library for PIC18 microcontrollers” http://projects.armandas.lt/lcd-library.html

ENMCU, “2x16 Character LCD with C18” http://www.enmcu.com/guides/2x16characterlcdwithc18

http://www.proprojects.wordpress.com


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.