sábado, 14 de fevereiro de 2015

Usando display de 4X20 (4 linhas por 20 caracteres) com o 16F877A - XC8

Olá, neste exemplo vou demonstrar como usar um display de LCD 4X20 com o pic 16F877A no compilador XC8, vale lembra que os arquivos com a extensão ".c" e ".h" deve estar na mesma pasta em que é criado o arquivo main(), pois assim o compilador encontra esses arquivos,  veja que no meu código principal chamei apenas os arquivos ".h" pois os outros arquivos são chamados automaticamente pelo compilador, mas caso isso não aconteça vá na aba de projetos "source files"  e clicando no mouse como botão direito escolha a opção "add existing item...", e escolha o arquivo ".c", vamos ao Código fonte :

Código fonte do arquivo "main.c":
/*                         Usando display LCD 4X20
 * File:   main.c
 * Author: Aguivone
 *
 * Created on 14 de Fevereiro de 2015, 13:28
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config_cpu.h"
#include "lcd_4X20_16F.h"
#include<delays.h>

/*
 * 
 */
void main()
{
///configuração das porta do microcontrolador///////////////////////
    TRISA = 0;//todas são saidas
    TRISB = 0;//configura portB   como saida
    TRISD = 0;//todas são saidas
    TRISC = 0;//todas são saidas
    TRISE = 0;//todas são saidas
    PORTA = 0;
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    PORTC = 0;
    PORTD = 0;
    PORTE = 0;
    ADCON0 = 0X00;//desabilita modulo ADC
    ADCON1 = 0X07;//desliga portas analogicas
    ////////////////////////////////////////////////////////////////////
    inicializar_LCD();
    GIE = 0; //desabilita GIE: Global Interrupt Enable bit
    escolhe_pos_do_cursor(1,0);//linha 1 posiçao 0
    imprime_LCD("escrevendo na linha1");
    escolhe_pos_do_cursor(2,0);//linha 2 posiçao 0
    imprime_LCD("escrevendo na linha2");
    escolhe_pos_do_cursor(3,0);//linha 3 posiçao 0
    imprime_LCD("escrevendo na linha3");
    escolhe_pos_do_cursor(4,0);//linha 4 posiçao 0
    imprime_LCD("escrevendo na linha4");
    for(;;)
    {
       // faz nada!
    }

}
Código fonte do arquivo "config_cpu.h":

/*
 * File:   config_cpu.h
 * Author: aguivone
 *
 * Created on 25 de Agosto de 2014, 16:24
 */

#ifndef CONFIG_CPU_H
#define    CONFIG_CPU_H

/*******************************configuraçôes do pic ****************************************************/
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = ON         //Codigo de proteção de firwmware




#define _XTAL_FREQ 20000000//usado para rotinas de  delays


#endif    /* CONFIG_CPU_H */

Código fonte do arquivo "lcd_4X20_16F.h":

The HTML source code is below.

/* 
 * File:   lcd_4X20_16F.h
 * Author: aguivone
 *
 * Created on 06 de fevereiro de 2015, 16:25
 */

#ifndef    LCD_4X20_16F_H
#define    LCD_4X20_16F_H

// ************************************************************************************
// Prototipos de funçoes
// ***********************************************************************************
extern void Saida_LCD(char a);
extern void comando_LCD(char a);
extern void limpar_LCD(void);
extern void escolhe_pos_do_cursor(char a, char b);
extern void inicializar_LCD(void);
extern void escreve_caracter(char a);
extern void imprime_LCD(char *a);
extern void rotaciona_LCD_direita();
extern void rotaciona_LCD_esquerda();
extern void long_to_char_LCD(unsigned long quant,int linha,int posicao);
extern void int_to_char_LCD(int quant,int linha,int posicao,int dig);

//#include "lcd_4X20_16F.c" //quando não reconhecer automaticamente usar este recurso


#endif    /*LCD_4X20_16F_H*/

Código fonte do arquivo "lcd_4X20_16F.c":

/*
 *                          FUNÇOES USADAS NO DISPLAY DE LCD
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 16F877A
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  10/02/2015.
 */
//Biblioteca para fazer a comunicação com o display de LCD 16X2
//usando o modo 4 bits
//testada com a familia PIC16F mas pode facilmente ser usada para outras familias de pic
#include <xc.h>
#include "config_cpu.h"
#include<delays.h>

//configuracao dos pinos usado para comunicar com o display, onde os defines são os nomes dos pinos do display.

#define RS RD2
#define EN RD3
//pinos de dados
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
//
//funçoes desta biblioteca
//
void Saida_LCD(char a)
{
    if(a & 1)
        {D4 = 1;}
    else
        {D4 = 0;}
        if(a & 2)
        {D5 = 1;}
    else
        {D5 = 0;}
        if(a & 4)
        {D6 = 1;}
    else
        {D6 = 0;}
        if(a & 8)
        {D7 = 1;}
    else
        {D7 = 0;}

}
void comando_LCD(char a)
{
    RS = 0;             // => RS = 0
    Saida_LCD(a);
    EN  = 1;             // => E = 1
        __delay_ms(4);       //tempo necessario para display reconhecer
        EN  = 0;             // => E = 0
}

void limpar_LCD(void)
{
    comando_LCD(0);
    comando_LCD(1);
}

void escolhe_pos_do_cursor(char a, char b)
{
    char temp,z,y;
    if(a == 1)
    {
      temp = 0x80 + b;
        z = temp>>4;
        y = temp & 0x0F;
        comando_LCD(z);
        comando_LCD(y);
    }
    else if(a == 2)
    {
        temp = 0xC0 + b;
        z = temp>>4;
        y = temp & 0x0F;
        comando_LCD(z);
        comando_LCD(y);
    }
        if(a == 3)
    {
      temp = 0x94 + b;
        z = temp>>4;
        y = temp & 0x0F;
        comando_LCD(z);
        comando_LCD(y);
    }
    else if(a == 4)
    {
        temp = 0xD4 + b;
        z = temp>>4;
        y = temp & 0x0F;
        comando_LCD(z);
        comando_LCD(y);
    }
}

void inicializar_LCD()
{
  Saida_LCD(0x00);
   __delay_ms(20);
  comando_LCD(0x03);
  __delay_ms(5);
  comando_LCD(0x03);
  __delay_ms(11);
  comando_LCD(0x03);
  /////////////////////////////////////////////////////
  comando_LCD(0x02);
  comando_LCD(0x02);
  comando_LCD(0x08);
  comando_LCD(0x00);
  comando_LCD(0x0C);
  comando_LCD(0x00);
  comando_LCD(0x06);
}

void escreve_caracter(char a)
{
   char temp,y;
   temp = a&0x0F;//pega a parte baixa do byte
   y = a&0xF0;//pega parte alta do byte
   RS = 1;             // => RS = 1
   Saida_LCD(y>>4);             //Envia a parte alta mas antes rotaciona 4 vezes
   EN = 1;
   __delay_us(40);
   EN = 0;
   Saida_LCD(temp);// envia a parte baixa
   EN = 1;
   __delay_us(40);
   EN = 0;
}

void imprime_LCD(char *a)
{
    int i;
    for(i=0;a[i]!='\0';i++)
       escreve_caracter(a[i]);
}

void rotaciona_LCD_direita()
{
    comando_LCD(0x01);
    comando_LCD(0x0C);
}

void rotaciona_LCD_esquerda()
{
    comando_LCD(0x01);
    comando_LCD(0x08);
}

void long_to_char_LCD(unsigned long quant,int linha,int posicao)//valor, posicão inicial,linha a ser usada
{
       char convert_char2='0';
       char convert_char3='0';
       char convert_char4='0';
       escolhe_pos_do_cursor(linha,posicao);//linha 1 posiçao 1
       if(quant <10)
       {
         convert_char2=' ';
         convert_char3=' ';
       }
       else
       {
           if(quant <100)
            {
              convert_char2=' ';
            }
       }

       while(quant>=100)
        {
         quant=quant-100;
         convert_char2++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        convert_char3++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         convert_char4++;
         }
          escolhe_pos_do_cursor(linha,posicao);//linha , posiçao
          escreve_caracter(convert_char2);
          escolhe_pos_do_cursor(linha,posicao+1);//linha , posiçao
          escreve_caracter(convert_char3);
          escolhe_pos_do_cursor(linha,posicao+2);//linha , posiçao
          escreve_caracter(convert_char4);
}
void int_to_char_LCD(int quant,int linha,int posicao,int dig)//valor, posicão inicial,linha a ser usada,numero de digitos
{
       char convert_char3='0';
       char convert_char4='0';
       escolhe_pos_do_cursor(linha,posicao);//linha 1 posiçao 1


       while(quant>=10)
        {
         quant=quant-10;
        convert_char3++;
         }
       while(quant>=1)
        {
           quant=quant-1;
           convert_char4++;
         }

          if(dig == 2)
          {
           escolhe_pos_do_cursor(linha,posicao);//linha , posiçao
           escreve_caracter(convert_char3);
           escolhe_pos_do_cursor(linha,posicao+1);//linha , posiçao
           escreve_caracter(convert_char4);
          }
          else
          {
            escolhe_pos_do_cursor(linha,posicao);//linha , posiçao
            escreve_caracter(convert_char4);
          }
}

A simulação: