// Librería para LCD SERIAL 2x16.
// Programador: Moyano Jonathan.
// Fecha: Junio de 2013.
// Versión: v1.1
// Revisión: r0.5
// Definir pines antes de ejecutar las funciones del LCD.
#define LCD_E PIN_A5
#define LCD_CK PIN_A4
#define LCD_DAT PIN_A3
#define LIGHT PIN_A2
// Definición de funciones:
void lcd_send_nibble(int8 nibble, int rs_bit); // Envía medio nibble de datos al display.
void lcd_send_byte(int8 address, int8 n); // Envía un dato de 8 bits al display.
void lcd_init(void); // Inicializa el LCD.
void lcd_gotoxy(int8 x, int8 y); // Posiciona el cursor.
void lcd_putc(char c); // Envía un caracter al LCD.
void lcd_cursor_shift_right(void); // Desplaza el cursor a la derecha.
void lcd_cursor_shift_left(void); // Desplaza el cursor a la izquierda.
void lcd_clear(void); // Borramos la pantalla del LCD.
// Definiciones y declaración de variables.
int8 RS_bit;
int8 lcd_line=0x00;
#define lcd_tipo 2 // 0=5x7, 1=5x10, 2=2 Líneas o más de caracteres.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
// Macros.
#define LIGHT_ON output_high(LIGHT); // Enciende backlight.
#define LIGHT_OFF output_low(LIGHT); // Apaga Backligth.
int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_tipo << 2), // Modo: 4-bits, 2+ líneas, 5x8 puntos.
0xC, // Encendido del display.
1, // Limpia display.
6 // Incrementa cursor.
};
// Funciones internas.
void lcd_send_nibble(int8 nibble, int rs_bit)
{
int x;
if(RS_bit==1){nibble=nibble|0x10;}
for(x=0;x<5;x++){
output_bit(LCD_DAT,shift_right(&nibble,1,0));
delay_cycles(1);
output_low(LCD_CK);
delay_us(1);
output_high(LCD_CK);}
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}
void lcd_send_byte(int8 address, int8 n)
{
RS_bit=0;
delay_us(100);
if(address){RS_bit=1;}else{RS_bit=0;}
delay_cycles(1);
output_low(LCD_E);
lcd_send_nibble(n >> 4,RS_bit);
lcd_send_nibble(n & 0xF,RS_bit);
}
// Funciones de usuario.
void lcd_init(void)
{
int8 i;
RS_bit=0;
output_low(LCD_E);
delay_ms(20);
// Enciende el backlight.
LIGHT_ON
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03,RS_bit);
delay_ms(5);
}
lcd_send_nibble(0x02,RS_bit);
for(i=0; i < sizeof(LCD_INIT_STRING); i++){
lcd_send_byte(0, LCD_INIT_STRING[i]);
delay_ms(5);}
}
void lcd_gotoxy(int8 x, int8 y){
int8 address;
switch(y)
{
case 1:
address = LCD_LINE_1_ADDRESS;
break;
case 2:
address = LCD_LINE_2_ADDRESS;
break;
default:
address = LCD_LINE_1_ADDRESS;
break;
}
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1, ++lcd_line);
break;
case '\b' : lcd_send_byte(0,0x10);
break;
case '\t' : lcd_send_byte(0,0x14);
break;
case '\r' : lcd_send_byte(0,0x18);
break;
case '\v' : lcd_send_byte(0,0x1C);
break;
default : lcd_send_byte(1,c);
break;
}
}
void lcd_cursor_shift_right(void){
lcd_send_byte(0,0x10|0x08|0x04);
}
void lcd_cursor_shift_left(void){
lcd_send_byte(0,0x10|0x08|0x00);
}
void lcd_clear(void)
{
lcd_send_byte(0,0x01);
delay_ms(250);
}