#include <Arduino.h>
/*
*****************************************
********** LCD 2x16 (4 bit) **********
*****************************************
- MODO 4 BIT -
Cuando se aplica tensión al LCD, el controlador aparece siempre en el modo de interfaz de 8 bits.
Esto significa que el controlador LCD lee los ocho pines de datos cada vez que llega un impulso al pin PE.
¿Qué pasa entonces cuando se conecta una interfaz de datos de 4 bits?
En este caso, puede haber datos indeterminados en los cuatro bits inferiores, especialmente si esos pines
no se han conectado a tierra como se recomienda.
El controlador ha sido configurado para ignorar esos cuatro bits inferiores durante
la primera parte del proceso de inicialización, hasta que la interfaz real haya sido establecida.
líneas LCD:
- VSS GND
- VCC +5V
- Vo Ajuste del contraste Nota(2)
- RS Selección de registo
- R/W Lectura /Escritura
- EN Habilitación
- D0 A D3 GND
- D4 a D7 Datos 4 bit
- A Ánodo Led retroiluminación
- K Cátodo
VRG (15/05/2022)
*/
// Declaración de variables y ctes
const uint8_t lcd_Linea_Uno = 0x00; // Direcciones DDRAM comienzo de la línea 1
const uint8_t lcd_Linea_Dos = 0x40; // y de la línea 2
// Interface paralelo 4 bit del LCD
const uint8_t DB[4] = {2, 3, 4, 5}; // Bus datos DB[3...0]
const uint8_t PE = 10; // Enable
const uint8_t RS = 11; // Registro de Datos/Instrucciones
// Instrucciones del LCD
const uint8_t lcd_Clear = 0b00000001; // pone en todos los caracteres el ASCII 'espacio'
const uint8_t lcd_Home = 0b00000010; // regresa el cursor a la primera posición de la primera línea
const uint8_t lcd_EntryMode = 0b00000110; // desplaza el cursor de izquierda a derecha en lectura/escritura
const uint8_t lcd_DisplayOff = 0b00001000; // apaga la pantalla
const uint8_t lcd_DisplayOn = 0b00001100; // pantalla activada, cursor desactivado, carácter sin parpadeo
const uint8_t lcd_FunctionReset = 0b00110000; // reinicia la pantalla
const uint8_t lcd_FunctionSet4bit = 0b00101000; // interface de 4 bits, pantalla de 2 líneas, fuente de 5x7 (5x8)
const uint8_t lcd_SetCursor = 0b10000000; // establecer la posición del cursor
char mensaje_1[] = "VICENTE"; // Mensaje inicial para depuración
char mensaje_2[] = "Rey Garcia";
// Prototipo de Funciones
void lcd_escribir_texto(char[]); // mostrar una cadena
void lcd_escribir_caracter_4b(uint8_t); // escribir un carácter
void lcd_escribir(uint8_t); // escribir LCD
void lcd_instruccion_4b(uint8_t); // escribir instrucciones 4 bits
void lcd_init_4b(); // inicializar interface en 4 bits
// Inicialización
void setup() {
for (int i = 0; i <= 3; i++) // Interface Bus de Datos 4 bits
pinMode(DB[i], OUTPUT);
pinMode(PE, OUTPUT); // Interface Bus de Control
pinMode(RS, OUTPUT); // PE enable, RS
lcd_init_4b(); // inicializar el LCD en modo 4
lcd_escribir_texto(mensaje_1);
lcd_instruccion_4b(lcd_SetCursor | lcd_Linea_Dos); // saltar a la segunda línea
delayMicroseconds(80); // minimo 40 uS retardo
lcd_escribir_texto(mensaje_2);
}
// ------------ Programa Principal ----------
void loop() {
}
// ------------ FIN --------------
// F U N C I O N E S
void lcd_init_4b(){
// comienza con direccionamiento en 8 bit
// los cuatro bits inferiores son irrelevantes
delay(100); // retardo initial (mayor de 40 ms)
digitalWrite(RS, LOW); // seleccionar registro de instrucción
digitalWrite(PE, LOW); // PE a nivel bajo inicialmente
lcd_escribir(lcd_FunctionReset); // Primera parte de la secuencia de inicialización
delay(10); // 4,1ms min.
lcd_escribir(lcd_FunctionReset);
delayMicroseconds(200); // 100µS min.
lcd_escribir(lcd_FunctionReset);
delayMicroseconds(200); // 100µS min.
lcd_escribir(lcd_FunctionSet4bit); // establercer modo, líneas y fuente
delayMicroseconds(80); // 40uS min
// Aquí empieza el direccionamiento en 4 bits
lcd_instruccion_4b(lcd_FunctionSet4bit); // establercer modo, líneas y fuente
delayMicroseconds(80); // 40uS min
lcd_instruccion_4b(lcd_DisplayOff); // poner display OFF
delayMicroseconds(80); // 40µs min
lcd_instruccion_4b(lcd_Clear); // Borrar RAM de pantalla
delay(4); // 1,64ms min
lcd_instruccion_4b(lcd_EntryMode); // set desired shift characteristics
delayMicroseconds(80); // 40µS min
lcd_instruccion_4b(lcd_DisplayOn); // Enciende la pantalla
delayMicroseconds(80); // 40µs min
}
//-------------------------------------------------------------------------------------------
void lcd_escribir_texto(char texto[]) {
int i = 0;
while (texto[i] != '\0') { // leer caracteres hasta la marca final '\0'
lcd_escribir_caracter_4b(texto[i]);
i++;
delayMicroseconds(80);
}
}
//-------------------------------------------------------------------------------------------
void lcd_escribir_caracter_4b(uint8_t lcd_dato) {
digitalWrite(RS, HIGH); // seleccionar Registro de Datos (RS = 1)
digitalWrite(PE, LOW); // inicialmente Enable = 0
lcd_escribir(lcd_dato); // escribir datos parte alta
lcd_escribir(lcd_dato << 4); // escribir datos parte baja
}
//-------------------------------------------------------------------------------------------
void lcd_instruccion_4b(uint8_t lcd_instruccion) {
digitalWrite(RS, LOW); // seleccionar Registro de Instrucción (RS = 0)
digitalWrite(PE, LOW); // inicialmente Enable = 0
lcd_escribir(lcd_instruccion); // escribir primero parte alta
lcd_escribir(lcd_instruccion << 4); // escribir parte baja
}
//-------------------------------------------------------------------------------------------
void lcd_escribir(uint8_t lcd_byte) {
for (uint8_t i = 0; i <= 3; i++){
if (lcd_byte & (1 << (i + 4)))
digitalWrite(DB[i], HIGH); // cambiar a '1' si fuera necesario
else
digitalWrite(DB[i], LOW);
}
// tiempo de establecimiento de la dirección (40 nS)
digitalWrite(PE, HIGH); // Preparar permiso de escritura por flanco descendente.
delayMicroseconds(1); // tiempo de establecimiento de los datos (80 nS) y anchura de PE (230 nS)
digitalWrite(PE, LOW); // completar impulso de escritura
delayMicroseconds(1); // tiempo de retención de los datos (10 nS) y tiempo del ciclo de PE (500 nS)
}