Você está na página 1de 11

PIC: Conversor A/D e LCD

OBJETIVOS
• Compreender a operação do conversor A/D do PIC;
• Aprender a utilizar as funções do drive de LCD ;
• Desenvolver uma IHM usando o LCD e o teclado da placa de experimentos;

CONVERSOR A/D
O módulo do conversor A/D possui 8 entradas analógicas, que possuem um capacitor de sample-
and-hold. A saída do sample-and-hold é conectada a entrada do conversor A/D a partir de um
multiplex 8 x 1. O conversor A/D gera uma palavra binária de 10 bits para representar o valor de
tensão na entrada analógica selecionada.
O módulo A/D tem duas entradas de tensão de referência (alta e baixa), que são selecionadas por
software, entre algumas opções de combinação pré-estabelecidas. Uma característica apenas
presente no módulo conversor A/D é que o mesmo pode operar mesmo o PIC estando no modo
SLEEP. Para operar neste modo o sinal de clock do conversor A/D (CAD) deve ser derivado do
oscilador RC interno do PIC.
O conversor A/D possui quatro registradores:
• Registrador do byte mais significado do resultado da conversão (ADRESH);
• Registrador do byte menos significado do resultado da conversão (ADRESL);
• Registrador de controle 0 (ADCON0) e
• Registrador de controle 1.

Os registradores ADRESH:ADRESL contém os 10 bits do resultado da conversão. Quando a


mesma é concluída, o resultado é carregado nesses registradores, o bit GO/DONE (bit 2 do Reg.
ADCON0) é resetado e o flag de interrupção, bit ADIF, é setado.
Após a configuração do módulo como desejado, o canal cujo sinal analógico deve ser convertido,
deve ser selecionado antes da conversão ser iniciada. Os canais de entrada analógicos devem ter
seus correspondentes bits TRIS ajustado para que os pinos das portas A e E se comportem como
entradas. Após o período de aquisição do sinal ter finalizado (aproximadamente 20µs) a
conversão A/D pode ser iniciada conforme os seguintes passos:

1. Configure o módulo A/D


• Configure os pinos de entrada analógica, as tensões de referência e os pinos de I/O
digital (ADCON1);
• Selecione o canal de entrada analógica (ADCON0);
• Selecione a freqüência do sinal de clock do conversor A/D (ADCON0);
• Ative o módulo A/D;
2. Configure a interrupção do módulo A/D (se desejado);
• Resete o bit ADIF;
• Sete o bit ADIE;
• Sete o bit GIE;
3. Aguarde o tempo de aquisição requerido;
4. Inicie a conversão

1
• Sete o bit GO/DONE (ADCON0)
5. Aguarde o tempo de conversão ter transcorrido;
• Realize um POLLING no bit GO/DONE, verificando se o seu valor é zero
(indicativo de fim de conversão A/D);
• ou aguarde pela interrupção gerada pelo módulo A/D ao fim da conversão;
6. Leia o par de registradores (ADRESH:ADRESL), resete o bit ADIF se a interrupção do
conversor A/D está sendo utilizada;
7. Para realizar uma nova conversão retorne ao passo 1 ou 2 (antes de uma nova conversão
ser iniciada, deve ser aguardado um tempo de 2TAD, que é o tempo de conversão por bit,
cujo valor é definido na tabela 1).

O conversor A/D necessita de no mínimo 12 TAD para realizar uma conversão de 10 bits. A fonte
do clock do conversor A/D é selecionada por software entre as possibilidades abaixo:
• 2Tosc
• 8Tosc
• 32Tosc
• Oscilador RC interno

Para uma conversão correta, o clock do conversor A/D deve ser selecionado para garantir um TAD
mínimo de 1.6µs. A tabela 1 mostra os valores de TAD em função da seleção da fonte do clock.

Tabela1 – TAD x Máxima freqüência de conversão

Se o bit GO/DONE for resetado durante uma conversão, esta será abortada. Os registradores de
resultado do módulo A/D não serão atualizados com a parcialmente concluída conversão. Assim,
os registradores ADRESH:ADRESL continuaram armazenando o valor da última conversão
concluída (ou o último valor escrito para os registradores ADRESH:ADRESL). Após uma
conversão ser abortada, um tempo de 2TAD é necessário antes de uma nova conversão ser
iniciada. Após este tempo, a aquisição do canal selecionado é automaticamente iniciada.
O par de registradores ADRESH:ADRESL comporta 16 bits, assim, o valor convertido de 10 bits
pode ser justificado a direita ou à esquerda, de acordo com o bit seleção de formato do conversor
A/D (ADFM), que controla a justificação. Os bits extras não utilizados são carregados com “0”
(zeros). Quando o módulo A/D não estiver sendo utilizado, os registradores ADRESH:ADRESL
podem ser usados como dois registradores de propósito geral de 8 bits.

2
Justificação do resultado da conversão A/D

Diagrama de blocos do conversor A/D

3
Registrador ADCON0 - Controla a operação do módulo A/D.

4
Registrador ADCON1 – Configura a função dos pinos das portas (A e E)

Os registradores ADCON1 e TRIS controlam a operação dos pinos das portas A/D. Os pinos das
portas que serão entradas analógicas devem ter seus correspondentes bits TRIS setados. Se o bit
está resetado, o nível de tensão da saída digital será convertido. A operação do conversor A/D
independe do estado dos bits CHS2:CHS0 e dos bits TRIS

Observações:
1 – Quando o registrador da porta é lido, qualquer pino configurado como um canal de entrada
analógica será lido como zero (nível baixo). Pinos configurados como entradas digitais irão se
converter em entradas analógicas. Níveis analógicos em uma entrada configurada como digital,
não afetarão a precisão da conversão.

2 – Níveis analógicos em qualquer pino que é definido como uma entrada digital (incluindo os
pinos AN7:AN0) podem fazer com que o buffer de entrada consuma corrente que está fora das
especificações do dispositivo.

5
Registradores associados com o módulo do conversor A/D

As rotinas abaixo implementam as funções utilizadas para escrever


caracteres e/ou mensagens em um LCD (Display de Cristal Líquido) de 16
colunas por 2 linhas.

/*=====================================================================
=======================================================================
ARQUIVO - DRIVER: LCD_16x2_LIB.C
DATA DE CRIAÇÃO: 03/11/2003
REVISÃO: 1.0
DATA DA ULTIMA REV: 03/12/2004
ULTIMA REV: 1.1
MICROCONTROLADOR: FAMILIA PIC

FUNÇÃO:

DESCRIÇÃO: BIBLIOTECA DE MANIPULAÇÃO DO DISPLAY DE CRISTAL


LÍQUIDO (LCD 16X2).

AUTOR: TÉC. LÚCIO HÉLIO

=======================================================================
=====================================================================*/

#ifndef CS_LCD

#define CS_LCD PIN_E0 // Pino de Controle "CS - CHIP


//SELECT" do LCD --------- (pino 6).
#define RS_LCD PIN_E1 // Pino de Controle "RS - REGISTER
//SELECT" do LCD ----- (pino 4).
#define D4_LCD PIN_D4 // Pino do Barramento de Dados "D4 - Dado
//4" do LCD --- (pino 11).
#define D5_LCD PIN_D5 // Pino do Barramento de Dados "D5 - Dado
//5" do LCD --- (pino 12).
#define D6_LCD PIN_D6 // Pino do Barramento de Dados "D6 - Dado
//6" do LCD --- (pino 13).
#define D7_LCD PIN_D7 // Pino do Barramento de Dados "D7 - Dado
//7" do LCD --- (pino 14).

6
#endif

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 linhas


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

// A constante abaixo define a seqüência de inicialização do LCD.


byte CONST seq_ini_lcd[4] = {0x20 | (lcd_type << 2), 0x0c, 1, 6};

/*=====================================================================
FUNÇÃO: ENVIA_NIBBLE_LCD()
PARÂMETROS: BYTE, DADO...
RETORNO: BYTE, NENHUM.

DESCRIÇÃO: ENVIA UM DADO DE QUATRO BIT´S PARA O BARRAMENTO DO


DISPLAY.

=====================================================================*/
void envia_nibble_lcd( byte dado )
{

output_bit(D4_LCD,bit_test(dado,0)); // Coloca os quatro bits nas


// saidas.
output_bit(D5_LCD,bit_test(dado,1));
output_bit(D6_LCD,bit_test(dado,2));
output_bit(D7_LCD,bit_test(dado,3));

output_high(CS_LCD); // Dá um pulso no pino de Enable (CS).


output_low(CS_LCD);
}

/*=====================================================================

FUNÇÃO: ENVIA_BYTE_LCD()
PARÂMETROS: BYTE, ENDERECO, DADO...
RETORNO: BYTE, NENHUM.

DESCRIÇÃO: ENVIA UM DADO DE QUATRO BIT´S PARA O BARRAMENTO DO


DISPLAY.

=====================================================================*/
void envia_byte_lcd( boolean endereco, byte dado )
{

output_low(RS_LCD); //Coloca o pino "RS" em "0".


output_bit(RS_LCD,endereco); //Configura o pino "RS" dependendo do
//modo selecionado.

delay_us(100); // Aguarda 100 us.

7
output_low(CS_LCD); // Desabilita o Display.
envia_nibble_lcd(dado >> 4); // Envia a primeira parte do byte.
envia_nibble_lcd(dado & 0x0f); // Envia a segunda parte do byte.
}

/*=====================================================================

FUNÇÃO: INI_LCD()
PARÂMETROS: BYTE, NENHUM.
RETORNO: BYTE, NENHUM.

DESCRIÇÃO: ROTINA DE INICIALIZAÇÃO DO LCD.

=====================================================================*/
void ini_lcd_16x2()
{
byte conta;

output_low(CS_LCD);
output_low(D4_LCD);
output_low(D6_LCD);
output_low(D7_LCD);
output_low(RS_LCD);

output_low(CS_LCD);

delay_ms(15);

// Envia uma seqüência de 3 vezes o valor "0x03" e depois o valor


// "0x02" para configurar o barramento do LCD no modo de 4 bits.
for(conta = 1 ;conta <= 3 ; ++conta)
{
envia_nibble_lcd(3);
delay_ms(5);
}

envia_nibble_lcd(2);

// Envia uma "string" de inicialização do Display.


for(conta = 0; conta <=3 ; ++conta)
envia_byte_lcd(0,seq_ini_lcd[conta]);
}

/*=====================================================================

FUNÇÃO: XY_LCD()
PARÂMETROS: BYTE, X,Y.
RETORNO: BYTE, NENHUM.

DESCRIÇÃO: ROTINA DE...

=====================================================================*/

8
void posicao_xy_lcd( byte x, byte y)
{
byte endereco;

if(y != 1)
endereco = lcd_seg_lin;
else
endereco = 0;

endereco += x-1;
envia_byte_lcd(0,0x80|endereco);
}

/*====================================================================

FUNÇÃO: EXIBE_LCD()
PARÂMETROS: BYTE, C...
RETORNO: BYTE, NENHUM.

DESCRIÇÃO: ROTINA PARA EXIBIR TEXTOS (CARACTERES) E COMANDOS.

=====================================================================*/
void exibe_lcd( char caracter)
{
switch (caracter)
{
case '\f' : // Envia um byte de Comando de Limpar (CLEAR) o
//Display.
envia_byte_lcd(0,1);
delay_ms(2);
break;

case '\n' :
posicao_xy_lcd(1,2);
break;

case '\b' :
envia_byte_lcd(0,10);
break;

// Envia um Caracter (ASCII) para o Display.


default:
envia_byte_lcd(1,caracter);
break;

}
}

Referências
1 – PIC16F87X Datasheet – Microchip Technology Incorporated. USA. Nov 1999.

9
PREPARAÇÃO

1 – Descreva como ficam distribuídos os 10 bits da palavra digital gerada pelo conversor A/D,
após uma conversão, quando é utilizada a justificação à direita e a esquerda.

2 - Considerando que o conversor A/D realiza uma conversão de 10bits no tempo mínimo (12Tad)
e que o clock do PIC é de 4MHz, determine que opção para os bits ADCS2: ADCS1: ADCS0
deve ser escolhida na tabela 1, para essa freqüência de Clock e qual o tempo total de conversão,
baseado na seleção de ADCS2: ADCS1: ADCS0 e no clock do PIC.

3 - Descreva a operação realizada por cada uma das funções abaixo e também o que representa
cada opção dos parâmetros da função em termos do funcionamento do bloco ao qual a função está
associada (quando houver):
SETUP_ADC (mode)
mode: ADC_OFF
ADC_CLOCK_DIV_2
ADC_CLOCK_DIV_8
ADC_CLOCK_DIV_32
ADC_CLOCK_INTERNAL

SETUP_ADC_PORTS (value)
value: NO_ANALOGS
ALL_ANALOG
AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF – VRefh=A3
AN0_AN1_AN2_AN3_AN4
AN0_AN1_AN2_AN4_VSS_VREF – VRefh=A3
AN0_AN1_AN3
AN0_AN1_VSS_VREF – VRefh=A3
AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF – VRefh=A3 VRefl=A2
AN0_AN1_AN2_AN3_AN4_AN5
AN0_AN1_AN2_AN4_AN5_VSS_VREF – VRefh=A3
AN0_AN1_AN4_AN5_VREF_VREF – VRefh=A3 VRefl=A2
AN0_AN1_AN4_VREF_VREF – VRefh=A3 VRefl=A2
AN0_AN1_VREF_VREF – VRefh=A3 VRefl=A2
AN0
AN0_VREF_VREF – VRefh=A3 VRefl=A2

READ_ADC (mode)
mode: ADC_START_AND_READ
ADC_START_ONLY
ADC_READ_ONLY

SET_ADC_CHANNEL (chan)

4 – Elabore um programa em C para o PIC 16F877 que incremente uma variável do tipo “LONG”
a cada 524ms. Utilize a interrupção do “Overflow” do Timer 1, ajustando o Timer1 para gerar um
overflow no período indicado acima. Na rotina de interrupção devem ser implementadas as
seguintes operações:
a) Incremento da variável do tipo “LONG” a cada 524ms;
b) Escrita da mensagem “Contagem = <valor da variável “LONG”>”, na linha superior do
display, a cada 524ms. O termo entre < > corresponde ao valor da variável, que deve aparecer
após o texto “Contagem =”;

10
Implemente também uma rotina, utilizando a interrupção do “CAPTURE” do bloco CCPx, para
identificar quando um botão é pressionado (transição de 1 para 0). Na rotina do “CAPTURE”,
SET/RESET um flag (variável do tipo “SHORT”), que libera ou inibi o incremento do valor da
variável do tipo “LONG” na interrupção do Timer 2, segundo a seguinte lógica:
Flag setado (igual a 1) – libera contagem;
Flag resetado (igual a 0) – inibe contagem (congela a contagem);
A rotina deverá funcionar da seguinte forma: o flag inicia a execução com zero, quando o botão
for pressionado pela primeira vez, o seu valor muda para 1. Após uma segunda ativação do botão
o valor do flag volta para zero e na seqüência o mesmo fica trocando de estado cada vez que o
botão for pressionado.

5 – Escreva uma rotina em C que faça a leitura do valor de um sinal analógico aplicado na
entrada AN0 a cada 524 ms. A cada leitura o valor lido (de 10 bits) deve ser apresentado no
display através da seguinte mensagem: “Valor Lido: XXX”, onde os caracteres XXX
correspondem ao valor de 10 bits, no formato hexadecimal. Utilize a rotina de interrupção do
Timer1 da questão anterior para implementar a leitura/escrita da mensagem a cada 524ms

11