Você está na página 1de 8

/* ************************************************************

*
* 2138_LCD_ADC:
* Utiliza o Timer T0 escrever um valor obtido utilizando o
* conversor A/D (AD0.0) a cada 1s em um display LCD.
*
************************************************************** */

#include "C:/lpc213x.h"
#include "C:/comandos.h"

/* Frequencia efetiva do clock 20MHz */


#define SYSCLK 20000000

/* Definição dos pinos do microcontrolador correspondentes


* aos pinos que controlam o LCD.
*/
#define lcd_rs_1 IOSET1=BIT19
#define lcd_rs_0 IOCLR1=BIT19
/* Pino não ligado à placa.
*/
//#define lcd_rw_1 FIO1SET=BIT29
//#define lcd_rw_0 IOCLR1=BIT29
#define lcd_enable_1 IOSET1=BIT18
#define lcd_enable_0 IOCLR1=BIT18
#define lcd_D4_1 IOSET1=BIT20
#define lcd_D4_0 IOCLR1=BIT20
#define lcd_D5_1 IOSET1=BIT21
#define lcd_D5_0 IOCLR1=BIT21
#define lcd_D6_1 IOSET1=BIT22
#define lcd_D6_0 IOCLR1=BIT22
#define lcd_D7_1 IOSET1=BIT23
#define lcd_D7_0 IOCLR1=BIT23
#define lcd_comando() lcd_rs_0
#define lcd_dado() lcd_rs_1

/* A rotina espera tem um loop para gastar tempo */


/* Esta maneira de esperar não é recomendada porque o tempo não pode
ser determinado */
/* Espera t ms
*/
void espera(unsigned int t)
{
unsigned int tf;
tf = T0TC + t; /* tf = Valor futuro do T0TC */
while(tf != T0TC); /* espera ate que tf==T0TC */
}

/* Envia um byte para o módulo LCD.


*/
void lcd_envia_byte(unsigned char n) {
lcd_enable_0;
if ( n&0x10 ) { lcd_D4_1; } else { lcd_D4_0; }
if ( n&0x20 ) { lcd_D5_1; } else { lcd_D5_0; }
if ( n&0x40 ) { lcd_D6_1; } else { lcd_D6_0; }
if ( n&0x80 ) { lcd_D7_1; } else { lcd_D7_0; }
espera(8);
lcd_enable_1;
espera(8);
lcd_enable_0;
if ( n&0x01 ) { lcd_D4_1; } else { lcd_D4_0; }
if ( n&0x02 ) { lcd_D5_1; } else { lcd_D5_0; }
if ( n&0x04 ) { lcd_D6_1; } else { lcd_D6_0; }
if ( n&0x08 ) { lcd_D7_1; } else { lcd_D7_0; }
espera(1);
lcd_enable_1;
espera(1);
lcd_enable_0;
}

/* Função que inicializa o módulo LCD.


*/
void lcd_init(void) {
unsigned char i;
/* Seta todos os pinos utilizados pelo LCD como saída.
*/
IODIR1|=(BIT18|BIT19|BIT20|BIT21|BIT22|BIT23);
/* Zera todos os pinos utilizados. */
//lcd_rw_0;
lcd_D4_0;
lcd_D5_0;
lcd_D6_0;
lcd_D7_0;
lcd_rs_0;
lcd_enable_0;
/* Aguarda tempo necessário para leitura do comando pelo
* módulo LCD.
*/
espera(15);
/* Prepara envio de comando para o módulo LCD.
*/
lcd_comando();
/* Escreve comando b0011 ou 0x03 nos dados no módulo LCD 3x
* (através do loop) para configurar modo de 4 bits. */
lcd_D4_1;
lcd_D5_1;
lcd_D6_0;
lcd_D7_0;
for (i=0;i<3;i++)
{
/* Envia o comando.
*/
lcd_enable_1;
espera(4);
lcd_enable_0;
espera(4);
}
/* Altera o comando para b0010 ou 0x02 e finaliza a
* configuração do modo 4 bits.
*/
lcd_D4_0;
lcd_D5_1;
lcd_D6_0;
lcd_D7_0;
/* Envia o comando.
*/
lcd_enable_1;
espera(4);
lcd_enable_0;
espera(4);
/* Prepara envio de comando para o módulo LCD.
*/
lcd_comando();
/* Envia sequência de inicialização para o módulo LCD. */
lcd_envia_byte(0x28);
lcd_envia_byte(0x06);
lcd_envia_byte(0x0C);
lcd_envia_byte(0x01);
}

/* Envia um caracter para o módulo LCD.


*/
void lcd_putc(char c) {
switch (c) {
/* Caso em que o comando que limpa a tela é enviado. */
case '\f':
lcd_comando();
lcd_envia_byte(0x01);
espera(8);
lcd_envia_byte(0x80);
break;
/* Casos em que o comando de ir para segunda linha é
* enviado.
*/
case '\n':
case '\r':
lcd_rs_0;
lcd_envia_byte(0xC0);
break;
/* Caso em que o comando de ir para a primeira linha é
* enviado.
*/
case '\b': // vai para a primeira linha
lcd_rs_0;
lcd_envia_byte(0x80);
break;
/* Caso em que o caracter lido é enviado para o módulo LCD.
*/
default:
lcd_dado(); // caractere
lcd_envia_byte(c);
break;
}
}

/* Procedimento que envia uma string para o display LCD.


*/
void lcd_puts(char *s){
while( *s!=0x00 ){
lcd_putc(*s);
s++;
}
}

/* Procedimento que coloca o cursor na posição X, Y.


* X - Coluna.
* Y - Linha.
*/
void lcd_goto_xy(char x,char y){
if ( y==0x01 ) {
// Linha 1, coluna X
lcd_comando();
lcd_envia_byte( 0x80|x );
} else {
// Linha 2 , coluna X
lcd_comando();
lcd_envia_byte( 0xC0|x );
}
}

/* Procedimento utilizado para alterar as opções referentes ao


* cursor.
*/
void lcd_cursor( char cmd ) {
lcd_comando();
lcd_envia_byte( cmd );
}

/* Procedimento utilizado para converter um número inteiro para


* string e apresentar no display LCD.
*/
void escreveValor(int x)
{
int c;
c=x;
c = x/1000;
lcd_putc((c) + '0');
x = x-(c*1000);
c = x/100;
lcd_putc((c) + '0');
x = x-(c*100);
c = x/10;
lcd_putc((c) + '0');
x = x-(c*10);
c = x%10;
lcd_putc((c) + '0');
}

/* Procedimento responsável por atualizar os registradores


* do PLL.
*/
void atualizaPLL()
{
/* PLLFEED - Registrador responsável pela alteração dos
* registradores do PCON.
* Deve ser carregado com o valor 0xAA e depois 0x55.
* (Sequência descrita no manual do lpc2138)
*/
PLLFEED = 0x000000AA;
PLLFEED = 0x00000055;
}

void inicializa(void)
{
/* PLLCFG - Registrador de configuração do PLL.
* MSEL - Bit 0 a 4 - Valor do multiplicador PLL.
* PSEL - Bit 5 a 6 - Valor do divisor PLL.
* Para configurar a frequência de trabalho para 60 MHz:
* MSEL = 3; (3*20MHz) = 60MHz
* PSEL = 2; 156 < (60*2*P) < 320, logo P = 2.
*/
PLLCFG = 0x23;
/* PLLCON - Registrador de controle do PLL.
* PLLE - Bit 0 - Habilita ou desabilita o PLL.
* PLLC - Bit 1 - Habilita conexão do PLL à fonte de clock
* configurada.
* Inicialmente, habilitamos o PLL setando o bit 0.
*/
PLLCON = 0x01;

/* Procedimento responsável por atualizar os registradores


* do PLL.
*/
atualizaPLL();

/* PLLSTAT - Registrador responsável pelo Status do PLL.


* MSEL - Bit 0 a 4 - Fornece o valor do MSEL em uso.
* PSEL - Bit 5 a 6 - Fornece o valor do PSEL em uso.
* Bit 7 - Não utilizado.
* PLLE - Bit 8 - Fornece o estado do PLL (ativo ou não).
* PLLC - Bit 9 - Fornece o estado da conexão do PLL.
* PLOCK - Bit 10 - Quando 0 o PLL ainda não alterou os
* parametros fornecidos. Quando 1 o PLL alterou os
* parametros P e M para os fornecidos.
* Obs: alterar = comitar, salvar.
*/
while (!(PLLSTAT & 0x00000400));

/* PLLCON - Registrador de controle do PLL.


* PLLE - Bit 0 - Habilita ou desabilita o PLL.
* PLLC - Bit 1 - Habilita conexão do PLL à fonte de clock
* configurada.
* Agora, deixamos o bit 0 ativo e ativamos o bit 1 para
* conectar o PLL ao clock externo (cristal de 20MHz).
*/
PLLCON = 0x03;

/* Procedimento responsável por atualizar os registradores


* do PLL.
*/
atualizaPLL();

/* VPBDIV - Registrador que controla o divisor para gerar a


* frequência para os periféricos conectados ao barramento
* VPB. (Carregado com 0 funciona a 1/4 da velocidade do
* processador que foi definida acima como 60MHz).
*/
VPBDIV = 0x00;

/* Funções do Módulo Acelerador de Memória desabilitadas */


MAMCR = 0x00;

/* Para um sistema com o clock maior que 40MHz 3 CCLK são


* recomendados, logo MAMTIM = 3;
*/
MAMTIM = 3;

/* Funções do Módulo Acelerador de Memória habilitadas


* Com as configurações ajustadas pode-se iniciar o Módulo
* Acelerador de Memória.*/
MAMCR=2;
}
int main (void)
{
/* tempo - variável utilizada para armazenar o tempo de inicio
* presente no registrador T0TC.
* c - variável utilizada para contagem dos segundos.
*/
int tempo;
int c=0;
/* Chamada ao procedimento que inicializa algumas configurações
* de dispositivos presentes no microcontrolador.
*/
inicializa();
/* Comando que liga a energia do Timer0.
*/
PCONP |= 2;
/* Desabilita o Timer0.
*/
T0TCR = 0;
/* Configura o incremento do prescaler para 1000x por segundo.
*/
T0PR = SYSCLK/1000 - 1;
/* Reseta o Timer0.
*/
T0TCR = 2;
/* Inicia o Timer0.
*/
T0TCR = 1;
/* Chama o procedimento que inicializa o display LCD.
*/
lcd_init();
/* Procedimento que envia uma string para o módulo LCD.
*/
lcd_puts("\fA/D 0.0:\r\n");
lcd_goto_xy(0x00,0x02);
lcd_puts("Variar A/D.");
/* Seta o pino onde o LED3 encontra-se ligado como saída.
*/
set_bit(IO0DIR,12);

/* PCONP - Registrador que controla o ligamento dos periféricos.


* Liga o bit correspondente ao pino que liga o conversor A/D.
* Bit PCAD = 12
*/
set_bit(PCONP,12);
/* AD0CR - Registrador que controla o conversor A/D.
* SEL - Bit 0 a 7 - Seleciona o canal A/D utilizado.
* Foi setado o bit 0 para seleção do canal 0.
* CLKDIV - Bit 8 a 15 - Valor que somado + 1 será utilizado
* como divisor do PCLK (Deve ser menor ou igual a 4.5MHz).
* Foi setado o valor 5 para que 12/(5+1) = 2 MHz.
* BURST - Bit 16 - Escolhe entre conversão automática ou
feita
* manualmente.
* Foi setado o bit para conversão automática.
* CLKS - Bit 17 a 19 - Escolha da precisão e velocidade das
* conversões no modo Burst.
* Foi setado o valor 0 para modo 11 clocks / 10 bits.
* PDN - Bit 21 - Coloca o conversor em atividade ou descanso.
* START - Bit 24 a 26 - Controla as conversões no modo manual
* (em que Burst encontra-se desativado).
* EDGE - Bit 27 - Escolha de borda de subida ou descida no
modo
* manual quando utiliza-se interrupções externas.
*/
AD0CR = 0x00211001;
/* PINSEL1 - Seleção de pinos para periféricos no registrador 1.
* Bit 22 a 23 - P0.27 - Setado como 01 para AD0.0.
* clear_bit(PINSEL1,23) - limpa bit 15 para caso esteja
setado
* set_bit(PINSEL,22) - seta bit 14.
*/
clear_bit(PINSEL1,23);
set_bit(PINSEL1,22);

/* Armazena o tempo atual no contador do Timer0.


*/
tempo=T0TC;
do {

/* Verifica se já passou 1/2s.


*/
if(T0TC == tempo+500)
/* Liga LED1.
*/
set_bit(IO0SET,12);
/* Verifica se já passou 1s.
*/
if(T0TC == tempo+2000)
{
/* Desliga LED1.
*/
set_bit(IO0CLR,12);
/* Atualiza a variável tempo para mais 1s.
*/
tempo += 2000;
/* Procedimento que coloca o cursor na linha 1,
* coluna 11.
*/
lcd_goto_xy(0x09,0x01);

/* AD0STAT - Registrador com o Status do conversor


A/D.
* Done0:7 - Bit 0 a 7 - Quando bit setado indica que
* conversão está completa (não tem conversão em
* andamento).
*/
while(test_bit(AD0DR,31)==0);
/* AD0DR0 - Guarda o valor obtido com a conversão.
* Bit 6-15 - Valor obtido na última conversão.
*/
c = AD0DR;
/* Operações para limpar o valor obtido deixando
apenas
* a parte que contem o valor da conversão (presentes
* entre os bits 6-15).
*/
c = (c >> 6);
c = c & 0x03FF;

/* Procedimento que escreve a contagem no display


LCD. */
escreveValor(c);
/* Procedimento que adiciona o caracter 's' após a
* contagem
*/
/* Condição que pega a contagem no registrador T0TC
* para evitar estouro de memória (soma não ficar
* infinita).
* Zera a contagem.
*/
}
} while(1);
return 0;
}

/* Estas rotinas sao chamados pelo crt.S.


Devem existir, mas ainda nao estao sendo usadas */
void UNDEF_Routine(){}
void SWI_Routine(){}
void FIQ_Routine(){}