Codigo:
////////////////////////////////////////////////////////////////////////////
//// LCD_MOD.C ////
//// Driver para módulos LCD microcontrolados ////
//// ////
//// Inspirado en librería CCS ////
//// Adaptado por Fernando Nuño García y Miguel Ángel José Prieto para ////
//// funcionamiento con el LCD integrado en la placa PICDEM-2-PLUS. ////
//// Adaptado por Jaime Fernández-Caro para usar LCD de 20x4 ////
//// ////
//// Funciones definidas ////
//// ////
//// lcd_init() Inicialización,llamar antes de cualquier otra función////
//// ////
//// lcd_putc(c) Muestra c en la posicion siguiente del LCD. ////
//// Caracteres de control: ////
//// f Borra display ////
////
Sitúa cursor al comienzo de la línea 2 ////
//// Retrocede el cursor una posición ////
//// Avanza el cursor una posición ////
//// Retrocede una posición la pantalla visible ////
//// v Avanza una posición la pantalla visible ////
//// ////
//// ////
//// lcd_gotoxy(x,y) Sitúa escritura en posición del LCD ////
//// (posición 1,1: arriba a la izquierda) ////
//// ////
//// lcd_getc(x,y) Devuelve carácter en posición x,y del LCD ////
//// ////
////////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,1997 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
////////////////////////////////////////////////////////////////////////////
// Conexión a 7 pines del MCU: 3 de control / interface de datos de 4 bits:
//
// Líneas de control asignadas
// RC0 enable
// RC1 rw
// RC2 rs
//
// Líneas de Datos
// RA0 D4
// RA1 D5
// RA2 D6
// RA3 D7
//
//
struct lcd_pines_control { // Estructura que se define para facilitar acceso
boolean enable; // y asociarlos a los 3 bits más bajos del PORTC
boolean rw; // asignamos luego a esta estructura el PORTC
boolean rs; // rs (1º corresponde al menos significativo
boolean nada; // a los pines de control del LCD
int otros:4;
} lcd_control;
struct lcd_pines_datos { // Hacemos lo mismo con esta estructura para el PORTA
int datos:4; // los 4 bits más bajos son los de datos
int no_usados:4;
} lcd_datos;
/*
#byte lcd_control = 0x07 // Ponemos la estructura entera en el PORTC
#byte trisc = 0x87 // Registro de dirección de datos
#byte lcd_datos = 0x05 // Lo mismo para los datos, en el PORTA
#byte trisa = 0x85 // Registro de dirección de datos
*/
#byte lcd_control = 0xF82 // Ponemos la estructura entera en el PORTC
#byte trisc = 0xF94 // Registro de dirección de datos
#byte lcd_datos = 0xF80 // Lo mismo para los datos, en el PORTA
#byte trisa = 0xF92 // Registro de dirección de datos
//Prototipos de las funciones posteriores
void lcd_init();
byte lcd_read_byte();
void lcd_send_nibble(byte n);
void lcd_send_byte(byte address, byte n);
void lcd_gotoxy(byte x, byte y);
void lcd_putc(char c);
char lcd_getc(byte x, byte y);
void lcd_clr_line(char fila);
///////////////////////////////////////////////////////////////////////////////////////////
/// Función que inicializa el LCD, se deberían cambiar bits para cambiar configuracion
///////////////////////////////////////////////////////////////////////////////////////////
void lcd_init() {
byte i;
trisc&=0b11111000; // Asignamos salidas en RC0, RC1 y RC2, resto puerto como estaba
trisa&=0b11110000; // Lo mismo para RA0 a RA3
lcd_control.rs = 0;
lcd_control.rw = 0;
lcd_control.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
lcd_send_byte(0,0b00101000); ///Se envía Function set 0 0 1 DL N F - -
lcd_send_byte(0,0b00001100); ///Se envía Display on/off 0 0 0 0 1 D C B
lcd_send_byte(0,0b00000001); //Se envía Clear Display
lcd_send_byte(0,0b00000110); //Se envía Entry Mode set 0 0 0 0 0 1 I/D S//
// DL: datos 4 bits(0); 8 bits (1) / N: 2 líneas (1); 1 línea (0) / F: 5x10 (1); 5x8 (0)
// D: display on (1); off (0) / C: cursor on (1); off (0) / B: parpadeo pos.cursor (1); no (0)
// I/D: incremento en R/W (1) o decremento (0) / S: acompaña desplaz.display (1); no (0)
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Lee el byte señalado por el puntero, 1º parte alta, 2º parte baja
// Si al llamar a esta función rs=0, devuelve busy flag (+signif.) y dirección actual
/////////////////////////////////////////////////////////////////////////////////////////////
byte lcd_read_byte()
{
byte low,high;
trisc&=0b11111000; //Las señales de control siguen siendo salidas, el resto lo que sean
trisa|=0b00001111; //Las de datos pasan a ser entradas, las demas igual
lcd_control.rw = 1;
delay_cycles(1);
lcd_control.enable = 1;
delay_cycles(1);
high = lcd_datos.datos;
lcd_control.enable = 0;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(1);
low = lcd_datos.datos;
lcd_control.enable = 0;
trisa&=0b11110000; // Dejamos RD0 a RD3 como salidas
return( (high<<4) | low);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Envía medio byte, los 4 bits más bajos de n
// Necesario poner rs y rw de modo adecuado y entrar con enable=0
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_send_nibble( byte n )
{
lcd_datos.datos = n;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(2);
lcd_control.enable = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Envía un byte (n) al registro de instrucciones (si address=0) o reg. de datos (address=1)
// Utiliza lcd_send_nibble(n) enviando primero nibble alto del byte
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_send_byte( byte address, byte n )
{
lcd_control.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ; //Mientras esté ocupado el LCD, espera
lcd_control.rs = address;
delay_cycles(1);
lcd_control.rw = 0;
delay_cycles(1);
lcd_control.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0x0F);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Sitúa el contador de direcciones en la DDRAM (para lectura o escritura posterior)
// x puede ir de 1 a 40, posición dentro de una línea (16 visibles)
// y puede ser 1 (línea 1) o 2 (línea 2)
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_gotoxy( byte x, byte y)
{
byte posicion;
switch(y)
{
case 1 : posicion=0x80;break;
case 2 : posicion=0xc0;break;
case 3 : posicion=0x94;break;
case 4 : posicion=0xd4;break;
}
posicion+=x-1;
lcd_send_byte(0,0x80|posicion); //Las direcciones de la DDRAM empiezan por 1xxxxxxx
}
////////////////////////////////////////////////////////////////////////////////////////////
// Envía un carácter c a la DDRAM del LCD, también algunos caracteres de control
////////////////////////////////////////////////////////////////////////////////////////////
void lcd_putc( char c)
{
switch (c)
{
case "f" : lcd_send_byte(0,1); //Limpia la pantalla
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); //Coloca puntero en 1ª posicion de la 2ª línea
break;
case "" : lcd_send_byte(0,0x10); //Retrocede una posición el cursor
break;
case " " : lcd_send_byte(0,0x14); //Avanza una posición el cursor
break;
case "" : lcd_send_byte(0,0x18); //Retrocede una posición la pantalla visible
break;
case "v" : lcd_send_byte(0,0x1C); //Avanza una posición la pantalla visible
break;
default : lcd_send_byte(1,c); //Envía caracter a DDRAM,
break; //Si es una tira, los envía todos uno a uno
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Devuelve el carácter situado en la posición x,y de la DDRAM
///////////////////////////////////////////////////////////////////////////////////////////
char lcd_getc( byte x, byte y) {
char value;
lcd_gotoxy(x,y);
lcd_control.rs=1;
value = lcd_read_byte();
lcd_control.rs=0;
return(value);
}
////////////////////////////////////////////////////////////////////////////////////
// Limpia la linea correspondiente y se situa al principio de la misma //
////////////////////////////////////////////////////////////////////////////////////
void lcd_clr_line(char fila)
{
int j;
lcd_gotoxy(1,fila);
for (j=0;j<40;j++) lcd_putc(" ");
lcd_gotoxy(1,fila);
}
Codigo:
/****************************************************************************
LCDC2.C
Code snippet to drive a standard LCD using 4-bit mode (data D4-D7).
***************************************************************************/
.
.
.
// The six bus pins are defined here.
// this example happens to use PIC port B3, B4, B5, B6 for LCD data
// and port B5 for LCD ENABLE and port B6 for LCD RS.
#define LCD_D4 PIN_B1
#define LCD_D5 PIN_B2
#define LCD_D6 PIN_B3
#define LCD_D7 PIN_B4
#define LCD_EN PIN_B5
#define LCD_RS PIN_B6
.
.
.
.
.
.
// misc display defines
#define LINE_1 0x00
#define LINE_2 0x40
#define CLEAR_DISP 0x01
// prototype statements
#separate void LCD_Init ( void );
#separate void LCD_SetPosition ( unsigned int cX );
#separate void LCD_PutChar ( unsigned int cX );
#separate void LCD_PutCmd ( unsigned int cX );
#separate void LCD_PulseEnable ( void );
#separate void LCD_SetData ( unsigned int cX );
// whatever pins you assign to the display
// MUST be in a bus that is a CCS type "standard_io".
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
.
.
.
.
.
.
// code start here
void main ( void )
{
char cX;
cX = 1; // set number
LCD_Init(); // set up LCD for 4-wire bus, etc.
LCD_PutCmd ( CLEAR_DISP ); // clear screen
LCD_SetPosition ( LINE_1 + 0 ); // set line and offset on line
printf ( LCD_PutChar, "Test #%u", cX ); // display message
LCD_SetPosition ( LINE_2 + 5 ); // set line and offset on line
printf ( LCD_PutChar, "2nd test" ); // display message
while ( 1 ); // stop
}
.
.
.
.
.
.
/* SIX LCD-SPECIFIC FUNCTIONS ARE BELOW============================== */
#separate void LCD_Init ( void )
{
LCD_SetData ( 0x00 );
delay_ms ( 200 ); /* wait enough time after Vdd rise */
output_low ( LCD_RS );
LCD_SetData ( 0x03 ); /* init with specific nibbles to start 4-bit mode */
LCD_PulseEnable();
LCD_PulseEnable();
LCD_PulseEnable();
LCD_SetData ( 0x02 ); /* set 4-bit interface */
LCD_PulseEnable(); /* send dual nibbles hereafter, MSN first */
LCD_PutCmd ( 0x2C ); /* function set (all lines, 5x7 characters) */
LCD_PutCmd ( 0x0C ); /* display ON, cursor off, no blink */
LCD_PutCmd ( 0x01 ); /* clear display */
LCD_PutCmd ( 0x06 ); /* entry mode set, increment & scroll left */
}
#separate void LCD_SetPosition ( unsigned int cX )
{
/* this subroutine works specifically for 4-bit Port A */
LCD_SetData ( swap ( cX ) | 0x08 );
LCD_PulseEnable();
LCD_SetData ( swap ( cX ) );
LCD_PulseEnable();
}
#separate void LCD_PutChar ( unsigned int cX )
{
/* this subroutine works specifically for 4-bit Port A */
if ( !cSkip )
{
output_high ( LCD_RS );
LCD_SetData ( swap ( cX ) ); /* send high nibble */
LCD_PulseEnable();
LCD_SetData ( swap ( cX ) ); /* send low nibble */
LCD_PulseEnable();
output_low ( LCD_RS );
}
}
#separate void LCD_PutCmd ( unsigned int cX )
{
/* this subroutine works specifically for 4-bit Port A */
LCD_SetData ( swap ( cX ) ); /* send high nibble */
LCD_PulseEnable();
LCD_SetData ( swap ( cX ) ); /* send low nibble */
LCD_PulseEnable();
}
#separate void LCD_PulseEnable ( void )
{
output_high ( LCD_EN );
delay_us ( 3 ); // was 10
output_low ( LCD_EN );
delay_ms ( 3 ); // was 5
}
#separate void LCD_SetData ( unsigned int cX )
{
output_bit ( LCD_D4, cX & 0x01 );
output_bit ( LCD_D5, cX & 0x02 );
output_bit ( LCD_D6, cX & 0x04 );
output_bit ( LCD_D7, cX & 0x08 );
}
Codigo:
/************************************************************************/
/* POOR"s (universal) LCD interface V1.4b */
/* simple and complete LCD routines by Andrea Bonzini */
/************************************************************************/
/* */
/* Please report any bug or suggestion at zypkin@inwind.it */
/* */
/************************************************************************/
/* */
/* This code will interface to a standard LCD controller */
/* like the Hitachi HD44780. */
/* It has been tested and works correctly with the followings */
/* LCD types: */
/* 1x8, 2x8, 1x16, 2x16, 2x20, 4x16, 4x20 */
/* */
/* */
/* !!! WARNINGS !!! */
/* */
/* This routines had been written to meet minimum hardware */
/* requirements...so you can use it even when your main */
/* application has left a few I/O lines not on the same port*/
/* To let this you have the following restriction and benefits: */
/* */
/* 1) LCD works only in 4 bit mode. */
/* 2) You can use any Output pin of your MCU, you have only */
/* to change pin assignments in the define section. */
/* 3) R/W select is not available so you must ground LCD"s R/W pin */
/* */
/* */
/* !!! NOTE !!! */
/* */
/* These routines use delay.c */
/* */
/************************************************************************
USER"S ROUTINES DESCRIPTION:
LCD_INIT() -----------> initilalize the LCD.
You must call it the first time you use the LCD
and before any other LCD routines.
LCD_CLEAR() ----------> Clears and Home LCD.
LCD_CMD("char") ------> Send a command to the LCD.
See LCD datasheet for the complete
list of commands.
LCD_GOTO(line,pos) ---> Set the Cursor to a specified Line and position.
Lines available are from 1 to 4. Pos available
starts from 1 to max available on your LCD.
LCD_PUTCH("char") ----> Write a character on LCD (ASCII representation).
LCD_PUTS("string"---> Write a string on LCD.
LCD_PUTUN(number) ---> Write an Unsigned Number on LCD.
It works both with INT (16bit) and CHAR (8bit).
LCD_PUTSN(number) ---> Write a Signed Number on LCD (with Sign if <0).
It works both with INT (16bit) and CHAR (8bit).
/************************************************************************/
/* */
/* !!! ATTENTION !!! */
/* Follow these simple instructions to configure your LCD module */
/* */
/* 1) check your hardware to determine which lines to use */
/* (you need 6 output lines). */
/* 2) set properly TRIS registers in your main code to configure */
/* the 6 lines as outputs. */
/* 3) In the next step use the defines to set the 6 lines as your */
/* hardware requires. */
/* 4) Set LCD Rows and Columns number using the define as shown */
/* 5) You are ready...your LCD will work!!!*/
/* */
/************************************************************************/
/************************************************************************/
/* Use this includes if these files are not included in your main code */
/************************************************************************/
//#include "pic.h"
//#include "delay.c"
/************************************************************************/
/* Use the following defines to set the lines as your hardware requires */
/* ...you can use ANY output line of the MCU, even on several ports*/
/************************************************************************/
#define LCD_RS RB4 // Register select
#define LCD_EN RB5 // Enable
#define LCD_D4 RB0 // LCD data 4
#define LCD_D5 RB1 // LCD data 5
#define LCD_D6 RB2 // LCD data 6
#define LCD_D7 RB3 // LCD data 7
/************************************************************************/
/* Now you have only to write LCD Rows and Columns number */
/************************************************************************/
/* !!! NOTE !!! */
/* Some 1x16 LCD works as 2x8!!! ...be sure how to configure */
/* yours, see its datasheet!!! */
/************************************************************************/
#define LCD_ROWS 2 // valid numbers are: 1,2
// (set to 2 for 2 or more rows)
#define LCD_COLS 20 // valid numbers are: 8,16,20
/************************************************************************/
/* */
/* YOUR LCD IS NOW READY TO WORK!!!*/
/* YOU CAN IGNORE THE FOLLOWING CODE */
/* ENJOY !!! */
/* */
/************************************************************************/
/************************************************************************/
/* Use the following defines to send fast command */
/* to the LCD */
/* EX: LCD_CMD(LCD_line2); will set the cursor on line 2 */
/* You can add fast command of your own!!! */
/************************************************************************/
/* */
/* !!! NOTE !!! */
/* DON"T CHANGE THE DEFINES WITHIN #if-#endif */
/* */
/************************************************************************/
#define LCD_CLR 0x01 // Clear Display
#define LCD_HOME 0x02 // Cursor to Home position
/************************************************************************/
#if (LCD_COLS==20)
#define LCD_line1 0x80 // Line 1 position 1
#define LCD_line2 0xC0 // Line 2 position 1
#define LCD_line3 0x94 // Line 3 position 1 (20 char LCD)
#define LCD_line4 0xD4 // Line 4 position 1 (20 char LCD)
#else
#define LCD_line1 0x80 // Line 1 position 1
#define LCD_line2 0xC0 // Line 2 position 1
#define LCD_line3 0x90 // Line 3 position 1 (16 char LCD)
#define LCD_line4 0xD0 // Line 4 position 1 (16 char LCD)
#endif
/************************************************************************/
/****************************************/
/* Enable LCD to read data */
/****************************************/
void LCD_STROBE (void)
{
LCD_EN = 1;
DelayUs(1);
LCD_EN=0;
}
/****************************************/
/* Write a nibble to the LCD */
/****************************************/
void LCD_NIBBLE_OUT (unsigned char c )
{
if ( c & 0b10000000 )
LCD_D7=1;
else LCD_D7=0;
if ( c & 0b01000000 )
LCD_D6=1;
else LCD_D6=0;
if ( c & 0b00100000 )
LCD_D5=1;
else LCD_D5=0;
if ( c & 0b00010000 )
LCD_D4=1;
else LCD_D4=0;
LCD_STROBE();
}
/****************************************/
/* Write a byte to the LCD (4 bit mode) */
/****************************************/
void LCD_WRITE (unsigned char c)
{
LCD_NIBBLE_OUT(c);
c <<= 4;
LCD_NIBBLE_OUT(c);
DelayUs(50);
}
/****************************************/
/* send a command to the LCD */
/****************************************/
void LCD_CMD (char c)
{
LCD_RS = 0; // write command
LCD_WRITE(c);
}
/****************************************/
/* GoTO specified line and position */
/****************************************/
void LCD_GOTO (char line,char pos)
{
switch(line)
{
case 1: LCD_CMD((LCD_line1-1)+pos);
break;
case 2: LCD_CMD((LCD_line2-1)+pos);
break;
case 3: LCD_CMD((LCD_line3-1)+pos);
break;
case 4: LCD_CMD((LCD_line4-1)+pos);
}
}
/****************************************/
/* Clear and Home LCD */
/****************************************/
void LCD_CLEAR (void)
{
LCD_CMD(LCD_CLR);
DelayMs(3);
}
/****************************************/
/* Write one character to the LCD */
/****************************************/
void LCD_PUTCH (char c)
{
LCD_RS = 1; // write characters
LCD_WRITE(c);
}
/****************************************/
/* Write numbers to the LCD */
/****************************************/
void LCD_PUTUN (unsigned int c)
{
unsigned char t1,i,wrote;
unsigned int k;
wrote=0;
for (i=4;i>=1;i--)
{
switch(i){
case 4: k=10000;
break;
case 3: k=1000;
break;
case 2: k=100;
break;
case 1: k=10;
}
t1=c/k;
if((wrote)||(t1!=0))
{
LCD_PUTCH(t1+"0");
wrote=1;
}
c-=(t1*k);
}
LCD_PUTCH(c+"0");
}
/****************************************/
void LCD_PUTSN (signed int c)
{
if(c<0)
{
LCD_PUTCH("-");
c*=(-1);
}
LCD_PUTUN(c);
}
/****************************************/
/* Write a string to the LCD */
/****************************************/
void LCD_PUTS (const char * s)
{
LCD_RS = 1; // write characters
while(*s)
LCD_WRITE(*s++);
}
/****************************************/
/* Initialize LCD */
/****************************************/
void LCD_INIT (void)
{
LCD_RS = 0; // write control bytes
DelayMs(15); // power on delay
LCD_D4=1;
LCD_D5=1;
LCD_D6=0;
LCD_D7=0;
LCD_STROBE();
DelayMs(5);
LCD_STROBE();
DelayUs(100);
LCD_STROBE();
DelayMs(5);
LCD_D4=0; // set 4 bit mode
LCD_STROBE();
DelayUs(40);
#if (LCD_ROWS==1)
LCD_WRITE(0b00100000); // 4 bit mode, 1 line, 5x8 font
#else
LCD_WRITE(0b00101000); // 4 bit mode, 2 or more lines, 5x8 font
#endif
LCD_WRITE(0b00001000); // display off
LCD_WRITE(0b00001100); // display on, curson off, blink off
LCD_WRITE(0b00000110); // shift entry mode, display not shifted
}
/************************************************************************/
#undef LCD_ROWS
#undef LCD_COLS
/************************************************************************/
/* !!! END !!! */
/* THANKS FOR EXAMINING MY CODE*/
/************************************************************************/
/* */
/* Please report any bug or suggestion at zypkin@inwind.it */
/* */
/************************************************************************/