martes, 14 de octubre de 2014

LCD CON EL PIC16F84A EN XC8

          En el siguiente vídeo se comenta como utilizar una pantalla LCD de 16x2 con un microcontrolador PIC, el cual se programa con el XC8, este programa no ofrece drivers para controlar las pantallas LCD con los pic de gama baja como el PIC16F84A, por lo que es necesario crear un driver para el control de las pantallas LCD; el XC8  si que tiene un driver para el manejo de las pantallas LCD, pero está preparado para que se utilice con los microcontroladores pic de gama alta como el PIC18F4550.


           El código utilizado para controlar el LCD se agregará en los programas como un archivo de cabecera, en este caso el nombre del archivo de cabecera es lcd.h, pero el nombre se puede cambiar.

            En este caso se ha programado para que los pines de control de la pantalla LCD sea a través de los pines RA0, RA1, y RA2 del PIC; y los pines
para el envío de datos u ordenes se hacen por los pines RB4, RB5, RB6, RB7,del PIC, esto se puede modidficar para que sean a través de otros pines.

              También se deja mas abajo el código de cabecera para los retardos.

               El código de cabecera para el control del LCD es el siguiente:

#ifndef     LCD_H
#define LCD_H

#include "tiempo.h"              ///Se incluye para los retardos

#define rs             PORTAbits.RA0             //Esto lo puedes
#define tris_rs     TRISAbits.TRISA0         //modificar si quieres utilizar
#define rw            PORTAbits.RA1            //otros pines del PIC
#define tris_rw     TRISAbits.TRISA1        //para los bits de control del LCD
#define e              PORTAbits.RA2
#define tris_e      TRISAbits.TRISA2

#define db4           PORTBbits.RB4              //Esto lo puedes modificar si quieres
#define tris_db4    TRISBbits.TRISB4          //que los pines para el envio de datos 
#define db5           PORTBbits.RB5             //u ordenes sean a través de otro puerto
#define tris_db5    TRISBbits.TRISB5        //pero es este caso siempre tendrá que 
#define db6           PORTBbits.RB6             //ser el nibble alto del puerto que utilices.
#define tris_db6    TRISBbits.TRISB6
#define db7           PORTBbits.RB7
#define tris_db7    TRISBbits.TRISB7

void lcd_inicia();
void lcd_pulso();
void lcd_orden(unsigned int);
void lcd_caracter(unsigned int );
void lcd_mensaje(char*);
void lcd_limpiar();
void lcd_acasa();
void lcd_ubicate(char,char);

void lcd_inicia(){
    tris_rs=0;
    tris_rw=0;
    tris_e=0;
    tris_db4=0;
    tris_db5=0;
    tris_db6=0;
    tris_db7=0;
    rs=0;
    rw=0;
    e=0;
    db4=0;
    db5=0;
    db6=0;
    db7=0;

    delay_ms(20);
    PORTB=0X03<<4;                           //Esto también deberá modificarce, 
    lcd_pulso();                                       //dependiendo del puerto que utilices para
    delay_us(4100);                                 //el envio de datos u ordenes.
    PORTB=0X03<<4;
    lcd_pulso();
    delay_us(4100);
    PORTB=0X03<<4;
    lcd_pulso();
    delay_us(150);
    PORTB=0X02<<4;//a 4 bits
    lcd_pulso();

    lcd_orden(0x28);//a 4 bits,2 lineas, 5x7 puntos
    delay_us(80);
    lcd_orden(0x0c);//display encendido,no muestra cursor,sin parpadeo
    delay_us(80);
    lcd_orden(0x01);//Limpia pantalla;
    delay_ms(2);
    lcd_orden(0x06);//incremento a la derecha, sin desplazamiento de display
    delay_us(80);
}

void lcd_pulso(){   //función para habilitar el LCD
    e=1;
    delay_us(40);
    e=0;
    delay_us(40);
}

void lcd_orden(unsigned int orden){   //Función para enviar ordenes al LCD
    rs=0;
    //Se modificará  si se usa un puerto diferente al PORTB
    PORTB=(((((PORTB>>4&0x0f)|0x0f)&(orden>>4&0x0f))<<4)|(PORTB&0x0f));
    lcd_pulso();
    PORTB=(((((PORTB>>4&0x0f)|0x0f)&(orden&0x0f))<<4)|(PORTB&0x0f));
    lcd_pulso();
}

void lcd_caracter(unsigned int caracter){   //Función para enviar caracteres al LCD

    rs=1;
    //Se modificará  si se usa un puerto diferente al PORTB
    PORTB=(((((PORTB>>4&0x0f)|0x0f)&(caracter>>4&0x0f))<<4)|(PORTB&0x0f));
    lcd_pulso();
    PORTB=(((((PORTB>>4&0x0f)|0x0f)&(caracter&0x0f))<<4)|(PORTB&0x0f));
    lcd_pulso();
    rs=0;
}

void lcd_mensaje(char* cadena){  //Función para enviar cadenas de caraacteres al LCD
    while(*cadena != 0x00){
        lcd_caracter(*cadena);
        cadena++;
    }
}

void lcd_limpiar(){     //Función para limpiar la pantalla LCD
    lcd_orden(0x01);
    delay_ms(2);

}

void lcd_acasa(){        //Función par enviar el cursor al inicio de la pantalla
    lcd_orden(0x02);
    delay_us(40);
}

void lcd_ubicate(char linea,char columna){  //Función para ubicar el cursor
    lcd_acasa();                         //en cualquier ubicación del LCD
    if (linea==1){
        for(char i=1; i<columna; i++){
            lcd_orden(0x14);
        }
    }
    if(linea==2){
        for (char i=1;i<(columna+40);i++){
            lcd_orden(0x14);
        }
    }
}
#endif


El código para los tiempos en XC8 es el siguiente:

#ifndef TIEMPO_H
#define TIEMPO_H

void delay_ms(unsigned int);
void delay_us(unsigned int);

void delay_ms(unsigned int tiempo){
    for(int i=0;i<tiempo;i++){
        __delay_ms(1);
    }
}

void delay_us(unsigned int tiempo){
    for(int i=0;i<tiempo;i++){
        __delay_us(1);
    }
}


#endif /* TIEMPO_H */

                                                                                                                     Atte: Benny.

No hay comentarios:

Publicar un comentario