Utilizando Módulos LCD Alfanuméricos com o RL78

Olá pessoal,

Neste post apresento um conjunto de funções simples para utilizar módulos de display LCD alfanuméricos (compatíveis com controlador HD44780) com os microcontroladores RL78. As definições iniciais do arquivo LCD.c pressupõem que o display está conectado da seguinte forma: pinos de dados D4 a D7 do LCD conectados a porta P7 (P70 a P73), pino de ENABLE do LCD conectado ao pino P54 do RL78 e pino RS do LCD conectado ao pino P55 do RL78. O pino R/W do LCD deverá ser mantido aterrado (como é o caso do display da RSK). Além disso, a comunicação é feita apenas no modo de 4 bits.

//************************************************************************
//* LCD.C - Biblioteca de manipulação de módulo LCD no RL78
//* Autor: Fábio Pereira
//************************************************************************
// As definições a seguir são utilizadas para acesso aos pinos do display
#ifndef PIN_LCD_EN
#define PIN_LCD_EN P5_bit.no4      // pino enable do LCD
#define PIN_LCD_EN_DIR PM5_bit.no4 // direção do pino enable
#define PIN_LCD_RS P5_bit.no5      // pino rs do LCD
#define PIN_LCD_RS_DIR PM5_bit.no5 // direção do pino rs
#define PORT_LCD_DATA4 P7
#define PORT_LCD_DATA4_DIR PM7
#endif

#define CPU_CLOCK 32000

// Endereço da segunda linha na RAM do LCD
#define LCD_LIN2 0x40

// Definições utilizadas para configuração do display
#define CURSOR_ON 2
#define CURSOR_OFF 0
#define CURSOR_BLINK 1
#define CURSOR_FIXED 0
#define DISPLAY_ON 4
#define DISPLAY_OFF 0
#define DISPLAY_8x5 0
#define DISPLAY_10x5 4
#define LINES_2 8
#define LINES_1 0

//**************************************************************************
//* Função de atraso (aproximadamente em ms)
//**************************************************************************
void LCD_delay_ms(unsigned char time)
{
  unsigned int temp;
  for (;time;time--) for (temp=CPU_CLOCK/9;temp;temp--) __no_operation();
}

//**************************************************************************
//* Função de envio de um nibble para o display
//**************************************************************************
void LCD_send4(char data)
{
  // coloca os quatro bits nas saidas
  PORT_LCD_DATA4 = data & 0x0F;
  // pulsa a linha enable
  PIN_LCD_EN = 1;
  PIN_LCD_EN = 0;
}

//**************************************************************************
//* Escreve um byte no display
//**************************************************************************
//* Argumentos de chamada:
//* char endereco : 0 se instrução, 1 se dado
//* char dado : dado ou comando a ser escrito
//**************************************************************************
void LCD_send8(char addr, char data )
{
  // configura a linha rs dependendo do modo selecionado
  PIN_LCD_RS = addr;
  LCD_delay_ms(1);
  // envia a primeira parte do byte
  LCD_send4(data >> 4);
  // envia a segunda parte do byte
  LCD_send4(data & 0x0f);
}

//**************************************************************************
//* Inicializa o display
//**************************************************************************
//* Argumentos de chamada:
//* char modo1 : modo do display (número de linhas e tamanho dos caracteres
//* char modo2 : modo do display (estado do cursor e do display)
//**************************************************************************
void LCD_init(char md1, char md2 )
{
  unsigned char temp;
  // configura os pinos como saídas
  PIN_LCD_EN_DIR = 0;
  PIN_LCD_RS_DIR = 0;
  PORT_LCD_DATA4_DIR = 0xF0;
  // coloca os pinos em nível lógico 0
  PORT_LCD_DATA4 = 0;
  PIN_LCD_RS = 0;
  PIN_LCD_EN = 0;
  LCD_delay_ms(15);
  // envia uma seqüência de 3 vezes 0x03 e depois 0x02 para configurar o
  // módulo no modo de 4 bits
  for(temp=3;temp;temp--)
  {
    LCD_send4(3);
    LCD_delay_ms(5);
  }
  LCD_send4(2);
  // envia códigos de inicialização do display
  LCD_send8(0,0x20 | md1);
  LCD_send8(0,0x08 | md2);
  LCD_send8(0,1);
  LCD_send8(0,6);
}

//**************************************************************************
//* Posiciona o cursor no display
//**************************************************************************
//* Argumentos de chamada:
//* char x : coluna a ser posicionado o cursor (iniciando em 0)
//* char y : linha a ser posicionado o cursor (0 ou 1)
//**************************************************************************
void LCD_pos_xy(char x, char y)
{
  unsigned char addr;
  addr = y * 64 + x;
  LCD_send8(0,0x80|addr);
}

//**************************************************************************
//* Função de escrita de um caractere no display
//**************************************************************************
//* Argumentos de chamada :
//* char c : caractere a ser escrito
//**************************************************************************
//* Observações :
//* \f apaga o conteúdo do display
//* \n e \r retornam o cursor para a primeira coluna da segunda linha
//**************************************************************************
void LCD_write_char(char data)
{
  switch (data)
  {
    case '\f' :
      LCD_send8(0,1);
      LCD_delay_ms(5);
      break;
    case '\n' :
    case '\r' :
      LCD_pos_xy(1,2);
      break;
    default :
      LCD_send8(1,data);
  }
}

//**************************************************************************
//* Escreve uma string no display
//**************************************************************************
//* Argumentos de chamada:
//* char *c : um ponteiro para um caractere
//**************************************************************************
void LCD_write_string (char *data)
{
  while (*data)
  {
    LCD_write_char(*data);
    data++;
  }
}

A seguir temos um pequeno programa para demonstrar a utilização das funções acima. Ele foi desenhado para ser utilizado com o display da placa RSK do RL78/G13.

#include "ior5f100le.h"
#include "ior5f100le_ext.h"
#include "intrinsics.h"
#include "myRL78.h"
#include "lcd.c"

// Configura watchdog
#pragma location = "OPTBYTE"
__root __far const char opbyte0 = WDT_OFF; 
// Configura detector de baixa tensão
#pragma location = "OPTBYTE"
__root __far const char opbyte1 = LVD_OFF; 
// oscilador 4MHz flash low speed
#pragma location = "OPTBYTE"
__root __far const char opbyte2 = FLASH_HS | CLK_32MHZ;
// debug ativado, com apagamento em caso de falha de autenticação
#pragma location = "OPTBYTE"
__root __far const char opbyte3 = DEBUG_ON_ERASE; 

/* Configura security ID */
#pragma location = "SECUID"
__root __far const char senha[10] = {0,0,0,0,0,0,0,0,0,0};

void main(void)
{
  LCD_init(DISPLAY_8x5|LINES_2,DISPLAY_ON|CURSOR_OFF|CURSOR_FIXED);
  LCD_write_string("RL78/G13");
  LCD_pos_xy(0,1);
  LCD_write_string("LCD 8x2");
  while(1);
}

Leave a Reply