Apostila Linguagem C para PIC
Apostila Linguagem C para PIC
Apostila Linguagem C para PIC
Linguagem C
SUMÁRIO .....................................................................................................................................................................3
RECURSOS BÁSICOS: EXEMPLO 1 BOTÃO E LED ............................................................................................5
RECURSOS DO LIVRO ..................................................................................................................................................5
LÓGICA DO EXEMPLO ...................................................................................................................................................5
ESQUEMA ELÉTRICO....................................................................................................................................................6
FLUXOGRAMA ..............................................................................................................................................................7
CÓDIGO ......................................................................................................................................................................8
EXERCÍCIOS PROPOSTOS ..........................................................................................................................................10
ANOTAÇÕES ..............................................................................................................................................................11
RECURSOS BÁSICOS: EXEMPLO 2 PISCA – PISCA VARIÁVEL .....................................................................13
RECURSOS DO LIVRO ................................................................................................................................................13
LÓGICA DO EXEMPLO .................................................................................................................................................13
ESQUEMA ELÉTRICO..................................................................................................................................................14
FLUXOGRAMA ............................................................................................................................................................15
CÓDIGO ....................................................................................................................................................................16
EXERCÍCIOS PROPOSTOS ..........................................................................................................................................18
ANOTAÇÕES ..............................................................................................................................................................19
RECURSOS BÁSICOS: EXEMPLO 3 CONTADOR HEXADECIMAL ..................................................................20
RECURSOS DO LIVRO ................................................................................................................................................20
LÓGICA DO EXEMPLO .................................................................................................................................................20
ESQUEMA ELÉTRICO..................................................................................................................................................21
FLUXOGRAMA ............................................................................................................................................................22
CÓDIGO ....................................................................................................................................................................25
EXERCÍCIOS PROPOSTOS ..........................................................................................................................................28
ANOTAÇÕES ..............................................................................................................................................................29
RECURSOS AVANÇADOS: EXEMPLO 4 MAXIMIZAÇÃO DE PINOS DE I/O...................................................30
RECURSOS DO LIVRO ................................................................................................................................................30
LÓGICA DO EXEMPLO .................................................................................................................................................30
ESQUEMA ELÉTRICO..................................................................................................................................................31
FLUXOGRAMA ............................................................................................................................................................32
CÓDIGO ....................................................................................................................................................................36
EXERCÍCIOS PROPOSTOS ..........................................................................................................................................40
ANOTAÇÕES ..............................................................................................................................................................41
RECURSOS AVANÇADOS: EXEMPLO 5 VARREDURA DE DISPLAY .............................................................42
RECURSOS DO LIVRO ................................................................................................................................................42
LÓGICA DO EXEMPLO .................................................................................................................................................42
ESQUEMA ELÉTRICO..................................................................................................................................................44
FLUXOGRAMA ............................................................................................................................................................45
CÓDIGO ....................................................................................................................................................................50
EXERCÍCIOS PROPOSTOS ..........................................................................................................................................57
ANOTAÇÕES ..............................................................................................................................................................58
RECURSOS AVANÇADOS: EXEMPLO 6 CONTROLE DO LCD ............................................................................59
RECURSOS DO LIVRO ................................................................................................................................................59
LÓGICA DO EXEMPLO .................................................................................................................................................59
ESQUEMA ELÉTRICO..................................................................................................................................................60
FLUXOGRAMA ............................................................................................................................................................61
CÓDIGO ....................................................................................................................................................................68
EXERCÍCIOS PROPOSTOS ..........................................................................................................................................76
ANOTAÇÕES ..............................................................................................................................................................77
RECURSOS AVANÇADOS: EXEMPLO 7 CONVERSOR ANALÓGICO DIGITAL..............................................78
RECURSOS DO LIVRO ................................................................................................................................................78
LÓGICA DO EXEMPLO .................................................................................................................................................78
+5V
RESET
+5V
10K MC1
1 32
MCLR VDD
2 31
RA0 VSS +5V
3 40
4
RA1 RB7
39 RB1
RA2 RB6
5
RA3 RB5
38 RB0
6 RA4 RB4 37
7 36
RA5 RB3 10K 330R
8 35
RE0 RB2
+5V 9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12
13
VSS RD6 29
28
S1 L2
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
WATCHDOG, PRESCALER.
LIMPA WATCHDOG
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este software está preparado para demonstrar o controle dos pinos de I/O
// este primeiro programa demonstrará o estado de um botão por meio de um led.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição das variáveis internas do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
//Este programa não utiliza nenhuma variável de usuário
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
//Este programa não utiliza nenhuma constante de usuário
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
//Este programa não utiliza nenhum flag de usuário
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As saídas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do Hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Microcontrolador *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main ()
{
setup_counters(RTCC_INTERNAL, WDT_2304MS);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Loop principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
while(TRUE)
{
RESTART_WDT();
if(!botao) // testa botão
{
led = 1; // Se botão = 0, então led = 1
}
else led=0; // caso contrário, led = 0
}
// FIM DO PROGRAMA
}
1.6 -
+5V
RESET
+5V
10K MC1
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
8 35
+5V RE0 RB2
9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
+5V +5V
10K 10K
L3 L4
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS, NÃO BOTÃO S1 SIM
WATCHDOG, PRESCALER. PRESS.?
INCREMENTA TEMPO
COMPLEMENTA PORTB
A
NÃO BOTÃO S2 SIM
PRESS.?
SIM
TEMPO = MIN?
NÃO
DECREMENTA TEMPO
CARREGA A VARIÁVEL
CONTADOR COM O VALOR
DA VARIÁVEL TEMPO
ROTINA DE DELAY
LAÇO FOR
NÃO
B CONTADOR ≠ 0
SIM
DELAY (10MS)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este software demonstrará a utilização da função de delay e a inversão de portas
//a frequência de oscilação dos leds é controlada pelos botões S1 (UP) e S2 (DOWN).
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição das variáveis internas do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877A.h> // microcontrolador utilizado
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos
fusíveis
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definições para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000, RESTART_WDT) // diretiva para o uso da função delay
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
int contador = 0 ;
int tempo = 9;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
//Este programa não utiliza constantes
#define max 255 // Limite de ajuste do tempo
#define min 10
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
//Este programa não utiliza nenhum flag de usuário.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As saídas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Microcontrolador *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main ()
{
setup_counters(rtcc_internal,wdt_2304ms);
set_tris_a(0b11111111);
set_tris_b(0b11110011);
set_tris_c(0b11111111);
set_tris_d(0b11111111);
set_tris_e(0b00000111);
porta = 0x00;
portb = 0x0f; // carrega portb com valor inicial
portc = 0x00;
portd = 0x00;
porte = 0x00;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Loop principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
while(TRUE)
{
RESTART_WDT();
} // FIM DO PROGRAMA
220R
+5V DS4
a
+5V b a
c
d f g b
RESET e
10K f
MC1 g e c
Dp d
1 32 Dp
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7 220R
4
RA2 RB6
39 BC337
5 38
RA3 RB5 4,7K
6 RA4 RB4 37
7 36
RA5 RB3
8 35
+5V RE0 RB2
9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
+5V +5V
10K 10K
RB0 RB1
S1 S2
PIC16F877
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
WATCHDOG, PRESCALER.
LIMPA WATCHDOG
C NÃO
NÃO
Filtro ≠ 0 ?
Decrementa o Filtro
NÃO
Contador ≠ Max ?
SIM
Incrementa o contador
Consulta tabela de conversão e
atualiza o display
B NÃO
NÃO
Filtro ≠ 0 ?
Decrementa o Filtro
NÃO
Contador ≠ Min ?
SIM
Decrementa o contador
Consulta tabela de conversão e
atualiza o display
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Contador hexadecimal que utiliza dois botões para incrementar e decrementar
// o valor da variável "contador". O contador está limitado pelas constantes min e max.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877A.h> // microcontrolador utilizado
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos
fusíveis
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definições para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000, RESTART_WDT)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
#bit bt_UP_press = flags.0
#bit bt_DOWN_press = flags.1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As saídas devem ser associadas a nomes para facilitar a programação e
// futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tabela de Valores *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
byte const tabela[16] = {
//PGFEDCBA ; POSIÇÃO RELATIVA AOS SEGMENTOS
0b00111111, // 0H - 0
0b00000110, // 1H - 1
0b01011011, // 2H - 2
0b01001111, // 3H - 3
0b01100110, // 4H - 4
0b01101101, // 5H - 5
0b01111101, // 6H - 6
0b00000111, // 7H - 7
0b01111111, // 8H - 8
0b01101111, // 9H - 9
0b01110111, // AH - A
0b01111100, // BH - B
0b00111001, // CH - C
0b01011110, // DH - D
0b01111001, // EH - E
0b01110001}; // FH - F
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Microcontrolador *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
setup_counters(rtcc_internal, wdt_2304ms);
set_tris_a(0b11111111);
set_tris_b(0b11101111);
set_tris_c(0b11111111);
set_tris_d(0b00000000);
set_tris_e(0b00000111);
porta = 0x00;
portb=(0b00010000); // seleciona display ds4
portc = 0x00;
portd = (tabela[contador]); // mostra no display valor inicial do contador
porte = 0x00;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão 0 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if (!botao_UP) // O botão UP está pressionado ?
{ // sim,
if (!(bt_UP_press)) // O botão UP já foi tratato ?
{ // não.
if (filtro0 !=0) // Fim do filtro do botão UP ?
{
filtro0--; // Não, então decrementa o filtro
}
else // Sim, Faz a ação do botão
{
bt_UP_press = 1; // Marca que o botão está pressionado
if (contador != max)
{
contador++; // incrementa o contador
portd = (tabela[contador]); // consulta tabela, atualiza
// display
}
}
}
}
else
{ // botão 0 liberado
filtro0 = t_filtro; // inicia o filtro do botão 0
bt_UP_press = 0; // marca que o botão foi liberado
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão 1 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if (!botao_DOWN) // testa botão DOWN
{ // botão DOWN pressionado
if (!(bt_DOWN_press)) // o botão DOWN já foi tratato ?
{ // não
if (filtro1 !=0) // Fim do filtro do botão DOWN ?
{
filtro1--; // não, então decrementa o filtro
}
else // SIM. Faz a ação do botão
{
bt_DOWN_press = 1; // marca que o botão está pressionado
if (contador != min)
{
contador--; // decrementa o contador
portd = (tabela[contador]);// consulta tabela, atualiza
// display
}
}
}
}
else
{ // botão 1 liberado
filtro1 = t_filtro; // inicia o filtro do botão 1
bt_DOWN_press = 0; // marca que o botão foi liberado
}
}
}
Além disso, o sistema possui um filtro, regulado pela constante FILTRO_BOTAO, para evitar o
debounce da tecla. Este filtro garante que a tecla fique pressionada pelo tempo de FILTRO_BOTAO
x 2048µs.
Quanto à freqüência do buzzer, esta será controlada por TMR2. Calibramos os valores de pre e
postscale para que a freqüência da interrupção do TMR2 varie entre 100Hz e 2kHz, com a variação
de PR2 entre 16 e 240:
+5V
RESET
+5V
10K MC1
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
BUZZER 8 35
+5V RE0 RB2
9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
L1 L2 L3 L4
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
WATCHDOG, PRESCALER.
LIGA AS INTERRUPÇÕES
LIMPA WATCHDOG
NÃO SIM
INT DE TMR0?
TRATA TMR2
DESLIGA A SAÍDA DO
LIGA A SAÍDA DO BUZZER
BUZZER
FIM DA INTERRUPÇÃO
CHECA BOTÃO S1
NÃO
Reinicia Filtro Botão S1 PRESS ?
SIM
Limpa Flag de botão
pressionado (Status Leds)
Fim do Filtro ?
NÃO
SIM
CHECA BOTÃO S2
CHECA BOTÃO S3
CHECA BOTÃO S4
SIM
FIM DA INTERRUPÇÃO
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este software está preparado para ler quatro botões e tocar o buzzer com
//duração variavel conforme a tecla pressionada, além de acender o led
//indicando a última tecla pressionada.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E
//FUTURAS ALTERAÇÕES DO HARDWARE.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tabela de Valores *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
byte const tabela[16] = {255,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configuração do Microcontrolador *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// A rotina principal simplesmente limpa o WDT, pois toda a lógica do
// programa é tratada dentro das interrupções.
void main()
{
setup_adc_ports (no_analogs);
setup_counters(rtcc_internal , rtcc_div_8);
setup_timer_2 (t2_div_by_16,per,1);
set_tris_a(0b11011111);
set_tris_b(0b11110000);
set_tris_c(0b11111111);
set_tris_d(0b11111111);
set_tris_e(0b00000111);
porta=(0b00000000);
portb=(0b00000000);
portc=(0b00000000);
portd=(0b00000000);
porte=(0b00000000);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RTCC);
#priority timer0,timer2 // prioridade para a int de trm0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina de Tratamento de interrupção de TMR0 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta interrupção ocorrerá a cada 2048us.
// O filtro dos botões tem duração de 40ms (2048us x 20) e são decrementados a cada
// interrupção.
// Esta interrupção é responsável por converter os pinos dos botões em entrada, salvar
// a condição dos botões em variável temporária e converter os pinos em saída
// novamente.
#int_rtcc
void trata_int_tmr0()
{
set_tris_b(0b00001111); // configura os pinos como entrada para
// testar os botões
delay_cycles(4); // aguarda 4 ciclos de máquina para a
// estabilização do portb
status_botoes = portb; // lê o status dos botoes, salva em variável
// temporária
set_tris_b(0b00000000); // configura os pinos como saída para
// controle dos leds
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão 1 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão 2 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão 3 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if (!botao3) // testa botão 3
{ // botão 3 está pressionado ?
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão 4 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if (!botao4) // testa botão 4
{ // botão 4 está pressionado ?
filtro4--; // Sim, então decrementa o filtro
if (filtro4 == 0) // fim do filtro do botão 4 ?
{
botao4_press = 1; // marca que o botão está pressionado
}
}
else
{ // botão 4 liberado
filtro4 = t_filtro; // inicia o filtro do botão 4
botao4_press = 0; // marca que o botão foi liberado
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Atualiza Leds conforme botões pressionados *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
portb = status_leds; // atualiza os leds
if (status_leds == 0)
{
per = 0xff;
setup_timer_2 (t2_div_by_16,per,1);
disable_interrupts (INT_TIMER2);
buzzer = 0;
}
else
{
per = (tabela[status_leds]);// consulta tabela e inicializa timer2.
setup_timer_2 (t2_div_by_16,per,1);
enable_interrupts (INT_TIMER2); // habilita interrupção de timer2.
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina de Tratamento de interrupção de TMR2 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Está interrupção só irá ocorrer quando alguma tecla estiver pressionada,
// o periodo de ocorrência depende do botão ou da conbinação de botões pressionados,
// ela irá inverter o pino de I/O do buzzer a cada interrupção.
#int_timer2
void trata_int_tmr2()
{
if (buzzer != 0) // o buzzer está ligado ?
{
buzzer = 0; // sim, então desliga
}
else
{
buzzer = 1; // não, então liga
}
}
L1 Descrição
Aceso Temporizador em contagem regressiva
Apagado Temporizador paralisado
Botão Descrição
S2 Incrementa o valor inicial em 1 segundo
S3 Decrementa o valor inicial em 1 segundo
S4 Inicia e paralisa o temporizador
Para isso, configuramos o prescale de TMR1 em 1:8 e iniciamos o contador com o valor total
menos o desejado para a contagem (65.536 – 62.500). Desta maneira a interrupção acontecerá a
cada 0,5 segundo. Para podermos contar 1 segundo foi criado uma variável auxiliar denominada
DIVISOR_TMR1.
Cada vez que o sistema entrar na interrupção de TMR1 e o contador auxiliar (DIVISOR_TMR1)
terminar, o tempo é decrementado, começando pela unidade e chegando até a milhar, se for
necessário. Quando o tempo termina (0000) tanto o led quanto o TMR1 são desligado.
Neste exemplo está sendo utilizado o tratamento Manual de interrupções, neste modo nós
devemos providenciar todo o código necessário para o tratamento da interrupção, tais como: salvar
contexto, restaurar contexto, limpar os flags de indicação de interrupção e criar os registradores
para as rotinas de salvar e restaurar contexto. A prioridade de tratamento da interrupção depende
da seqüência de teste dos flags de int, que também é de responsabilidade do programador.
Para este tipo de tratamento estamos utilizando a diretiva #int global.
+5V
RESET
10K
MC1
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
8 35
+5V RE0 RB2
9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
S2 S3 S4
L1
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
WATCHDOG, PRESCALER.
Configura Timer1
Liga as interrupções
Limpa WATCHDOG
SIM
BOTÃO UP PRESS.? Trata Botão UP
NÃO
NÃO
NÃO
NÃO SIM
INT DE TMR0?
SWITCH CASE
Recarrega Timer1
Incrementa ponteiro de seleção
de Display, desliga display do
Atualiza Display da SIM milhar, consulta tabela de
Unidade? conversão para sete
segmentos, liga display da
decrementa contador de int. unidade
NÃO
SIM NÃO
NÃO
SIM
Desabilita interrupção de
Timer1
FIM DA INTERRUPÇÃO
SIM SIM
Timer Ligado ? Timer Ligado ?
NÃO NÃO
NÃO NÃO
Fim do Filtro ? Fim do Filtro ?
SIM SIM
SIM SIM
A A
SIM
Ação já foi executada ?
NÃO
NÃO
Filtro terminou ?
SIM
NÃO
Timer ligado ?
SIM
SIM
Timer é igual a zero ? Apaga led de indicação de
Timer ligado
NÃO
Desabilita interrupção de
Timer1
Acende Led de indicação de
Timer ligado
Carrega Timer1 A
Carrega contador de
interrupções
NÃO NÃO
Unidade = 10 ? Unidade = 0XFF ?
SIM SIM
NÃO NÃO
Dezena = 10 ? Dezena = 0XFF ?
SIM SIM
NÃO NÃO
centena = 10 ? centena = 0XFF ?
SIM SIM
NÃO NÃO
Milhar = 10 ? Milhar = 0XFF ?
SIM SIM
Return Return
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definições para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08
#byte porte=0x09
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição de SFR's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#bit tmr1if = 0x0c.0 // tmr1if é o bit 0 do sfr pir1
#bit t0if = 0x0b.2 // t0if é o bit 2 do sfr intcon
#bit tmr1ie = 0x8c.0 // tmr1ie é o bit 0 do fsr pie1
#byte status = 0x03 // define endereço do reg de status
#byte fsr = 0x04 // define endereço do reg de fsr
#byte pclath = 0x0a // define endereço do reg de pclath
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E
//FUTURAS ALTERAÇÕES DO HARDWARE.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função de decremento do Timer *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
decrementa_timer()
{
unidade --;
if (unidade == 0xff)
{
unidade = 9;
dezena --;
}
if (dezena == 0xff)
{
dezena = 9;
centena --;
}
if (centena == 0xff)
{
centena = 9;
milhar --;
}
if (milhar == 0xff)
{
milhar = 9;
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função de incremento do Timer *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
incrementa_timer()
{
unidade ++;
if (unidade == 10)
{
unidade = 0;
dezena ++;
}
if (dezena == 10)
{
dezena = 0;
centena ++;
}
if (centena == 10)
{
centena = 0;
milhar ++;
}
if (milhar == 10)
{
milhar = 0;
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina de Tratamento de interrupção de TMR0 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta interrupção ocorrerá a cada 256us.
#inline
trata_tmr0()
{
t0if = 0;
switch(display) // início da varredura dos display´s
{
case 0:
display++; // incrementa a variável de varredura
disp3 = 0; // desliga o display 3
portd = (converte[unidade]); // atualiza o portd
disp0 = 1; // liga o display 0
break; // sai
case 1:
display++; // incrementa a variável de varredura
disp0 = 0; // desliga o display 0
portd = (converte[dezena]); // atualiza o portd
disp1 = 1; // liga o display 1
break; // sai
case 2:
display++; // incrementa a variável de varredura
disp1 = 0; // desliga o display 1
portd = (converte[centena]); // atualiza o portd
disp2 = 1; // liga o display 2
break; // sai
case 3:
display = 0; // inicia a variável de varredura
disp2 = 0; // desliga o display 2
portd = (converte[milhar]); // atualiza o portd
disp3 = 1; // liga o display 3
break; // sai
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para restaurar contexto *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
restaura_contexto()
{
#asm
MOVF PCLATH_TEMP,W
MOVWF PCLATH // RECUPERA REG. PCLATH (PAGINAÇÃO)
MOVF FSR_TEMP,W
MOVWF FSR // RECUPERA REG. FSR (END. INDIRETO)
SWAPF STATUS_TEMP,W
MOVWF STATUS // RECUPERA REG. STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W // RECUPERA REG. WORK
#endasm
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configuração do Microcontrolador *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
setup_adc_ports (no_analogs);
setup_counters(rtcc_internal, wdt_2304ms);
setup_timer_1 (t1_internal | t1_div_by_8);
set_tris_a(0b11111111);
set_tris_b(0b00001110);
set_tris_c(0b11111111);
set_tris_d(0b00000000);
set_tris_e(0b00000111);
porta=(0b00000000);
portb=(0b00000000);
portc=(0b00000000);
portd=(0b00000000);
porte=(0b00000000);
enable_interrupts(INT_RTCC );
enable_interrupts(GLOBAL);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Loop principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
loop:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão de decremento (down) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão de Start / Stop *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
trata_up:
if (estado_timer == 0) // o timer está parado?
{
filtro --; // decrementa o filtro
if (filtro == 0) // fim do filtro do botão?
{
turbo --; // decrementa o turbo da tecla
if (turbo == 0) // sim, fim do turbo do botão ?
{
turbo = turbo_tecla; // carrega o turbo
incrementa_timer(); // incrementa o timer
}
}
}
goto loop;
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
trata_dowm:
if (estado_timer == 0) // o timer está parado?
{
filtro --; // decrementa o filtro
if (filtro == 0) // fim do filtro do botão?
{
turbo --; // decrementa o turbo da tecla
if (turbo == 0) // sim, fim do turbo do botão ?
{
turbo = turbo_tecla; // carrega o turbo
decrementa_timer(); // decrementa o timer
}
}
}
goto loop;
trata_start_stop:
if (filtro != 0) // o timer está parado?
{
filtro --; // decrementa o filtro
if (filtro == 0) // fim do filtro do botão?
{
if (estado_timer != 0) // sim, o timer está ligado ?
{
estado_timer = 0; // indica timer parado
tmr1ie = 0; // desliga o tratamento de interrupção de timer1
}
else
{
if((unidade!=0)||(dezena!=0)||(centena!=0)||(milhar != 0))
// timer está zerado?
{
estado_timer = 1;// não, indica que o timer está contando
contador = 2; // carrega contador auxiliar
set_timer1(delta_timer1); // carrega timer 1
tmr1if = 0; // limpa flag de int tmr1
tmr1ie = 1; // liga o tratamento de interrupção de timer1
}
}
}
}
goto loop;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função de Tratamento de interrupções *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Todo o tratamento de interrupção é feito manualmente.
// As funções salva contexto e restaura contexto foram feitas em assembler
// Observe que a prioridade das interrupções é realizada através do comando IF
// e a ordem do teste determina a prioridade no tratamento da interrupção.
#int_global
Void trata_int()
{
salva_contexto();// salva os registradores antes do tratamento da int
else // não,
{
if (tmr1if) // É int de tmr1 ?
{
trata_tmr1(); // sim, trata tmr1
}
} // não.
1. Mude a rotina para que o temporizador conte de forma crescente e desligue quando chegar a
zero.
2. Altere a rotina de temporização para que o timer seja decrementado a cada 1 minuto.
3. Mude a rotina do timer para que ele funcione como um cronômetro com um botão de start e
um de reset.
S e l e c i o n e T a r e f a
P r e s s M e n u
c t r d o s l e d s
c t r d o v e n t
Uma vez que a tela de controle foi escolhida, pressione a tecla enter para entrar na tela de
controle, de acordo com a tela selecionada poderemos visualizar as seguintes telas:
c t r d o s l e d s
O N > O F F
V e n t i l a d o r
O N > O F F
Na tela de controle, deve se pressionar enter para escolher a opção desejada, ON ou OFF,
quando a tecla for pressionada o símbolo “>” será deslocado para a condição desejada.
7
DB0 VDD 2 10K
8
DB1 VO 3
9 VSS 1
1 DB2
0
1 DB3
1
1 DB4
4
2
1 DB5 RS RS
6
13 DB6 EN
5
4 DB7 R/W
EN
LCD
+5V
10K
RESET +5V
MC1
3
1
MCLR VDD 2
3
2 RA0 VSS 1
4
3 0
RA1 RB7 3
4
RA2 RB6 9
3
5
RA3 RB5 8
3
6 RA4 RB4 7
3
7
RA5 RB3 6
3
RS 8 RE0 RB2 5
+5V EN 9
3
RE1 RB1 4
10 33
1 RE2 RB0 3
1 VDD RD7 0
1 2
2 VSS RD6 9
1 2
3 OSC1 RD5 8
1 2
1 OSC2
4 RD4 7
2
1 RC0
5 RD3 2
2
4MHz 6 RC1
1 RD2 1
2
7 RC2 RD1 0
1 1
2 RC3
8 RD0 9
2
3 RC4 RC7 6
2 2
4 RC5 RC6 5
16F877
A
RB2 RB3
+5V +5V
330R 330R
10K 10K
S1 S2
MINI VENTILADOR
1N4148
BC337
4,7K
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
W ATCHDOG, PRESCALER.
Configura Timer0
Inicializa LCD
Tela principal
Habilita as interrupções
Limpa W ATCHDOG
SIM
Escreve tela principal ? Tela principal
NÃO
SIM
BOTÃO MENUPRESS.? Trata Botão Menu
NÃO
NÃO
Incrementa contador de
interrupções
Temp1 = 40
SIM
NÃO
Zera contador de interrupções
SW IT CH CASE
NÃO
NÃO
SIM
Ação já foi executada ?
NÃO
Decrementa Filtro
SIM NÃO
Fim do Filtro ?
SIM NÃO
Contador de Tela < 2
SIM
Ação já foi executada ?
NÃO
Decrementa Filtro
SIM NÃO
Fim do Filtro ?
Re-inicia time-out
Switch Case
SIM
Tela 1 do Menu ?
SIM
Tela 2 do Menu
Return
Beep
NÃO Return
Liga Beep
Delay
Desliga Beep
Delay
Switch Case
SIM
Tela 1 do Enter ?
SIM
Tela 2 do Enter
SIM
Tela 3 do Enter
SIM
Tela 4 do Enter
Return A
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// O arquivo de definições do pic utilizado deve ser referenciado para que
//os nomes definidos pela Microchip possam ser utilizados, sem a necessidade
//de redigitação.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definições para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
long int filtro = t_filtro; // inicia filtro dos botões
int flags1 = 0; // registrador de flags
int contador_tela = 0; // contador para seleção de tela
int time_out = 0; // registrador para contagem de tempo de time-out
int contador,temp1,temp2; // variaveis para a rotina de int de Timer0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E
//FUTURAS ALTERAÇÕES DO HARDWARE.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina que envia um COMANDO para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina que envia um DADO a ser escrito no LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void limpa_lcd()
{
comando_lcd(0x01); // limpa lcd
delay_ms (2);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicialização do Display de LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
comando_lcd(0x30); // envia comando para inicializar display
delay_ms(4); // espera 4 milisengundos
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função de Bip´s *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
{
long int conta_bip; // define variável local
conta_bip = tempo / periodo; // contabiliza quantas vezes terá
// que fazer o loop de bip´s
while (conta_bip) // faça o loop até acabar o conta_bip
{
buzzer = 1; // liga o buzzer
delay_ms(periodo/2); // conta tempo para o período escolhido
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tela Principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void tela_principal()
{
comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0
printf (escreve_lcd, "Seleciona Tarefa"); // imprime mensagem no lcd
comando_lcd(0xC0); // posiciona o cursor na linha 1, coluna 2
printf (escreve_lcd, " Press Menu "); // imprime mensagem no lcd
f_tela_principal = 1; // indica que a tecla foi atualizada
time_out = 0; // re-inicia contagem do tempo de time-out
}
void tela_menu()
{
limpa_lcd();
comando_lcd(0x82); // posiciona o cursor na linha 0, coluna 2
printf (escreve_lcd, "ctr dos leds"); // imprime mensagem no lcd
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Seleção de tela após pressionar a tecla enter *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void tela_ctr_led()
{
limpa_lcd();
comando_lcd(0x82); // posiciona o cursor na linha 0, coluna 2
printf (escreve_lcd, "ctr dos leds"); // imprime mensagem no lcd
if (!led1)
{
comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7
escreve_lcd(0x3e); // envia simbolo "maior" para o lcd
comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3
escreve_lcd(' '); // envia simbolo "espaço" para o lcd
}
else
{
comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3
escreve_lcd(0x3e); // envia simbolo "maior" para o lcd
comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7
escreve_lcd(' '); // envia simbolo "espaço" para o lcd
}
}
void tela_ctr_ventilador()
{
limpa_lcd();
comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 3
printf (escreve_lcd, "Ventilador"); // imprime mensagem no lcd
if (!ventilador)
{
comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7
escreve_lcd(0x3e); // envia simbolo "maior" para o lcd
comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3
escreve_lcd(' '); // envia simbolo "espaço" para o lcd
}
else
{
comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3
escreve_lcd(0x3e); // envia simbolo "maior" para o lcd
comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7
escreve_lcd(' '); // envia simbolo " " para o lcd
}
}
void sel_tela_menu()
{
switch(contador_tela)
case 1:
tela_menu();
comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0
escreve_lcd(0x7e); // envia simbolo "seta" para o lcd
break; // retorna
case 2:
tela_menu();
comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0
escreve_lcd(0x7e); // envia simbolo "seta" para o lcd
break; // retorna da função
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Seleção das telas após pressionar Enter *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void sel_tela_enter()
{
switch(contador_tela)
case 1:
tela_ctr_led();
contador_tela = 3;
break; // retorna da função
case 2:
tela_ctr_ventilador();
contador_tela = 4;
break; // retorna da função
case 3:
if (!led1)
{
led1 = 1; // acende o led
bip(50,2);
comando_lcd(0xc3);// posiciona o cursor na linha 1, coluna 3
escreve_lcd(0x3e);// envia simbolo "maior" para o lcd
comando_lcd(0xc7);// posiciona o cursor na linha 1, coluna 7
escreve_lcd(' ');// envia simbolo "espaço" para o lcd
else
{
led1 = 0; // apaga o led
comando_lcd(0xc7);// posiciona o cursor na linha 1, coluna 7
escreve_lcd(0x3e);// envia simbolo "maior" para o lcd
comando_lcd(0xc3);// posiciona o cursor na linha 1, coluna 3
escreve_lcd(' ');// envia simbolo "espaço" para o lcd
bip(50,2);
delay_ms(250);
bip(50,2);
}
break; // retorna da função
if (!ventilador)
{
bip(750,2);
ventilador = 1; // liga o ventilador
comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3
escreve_lcd(0x3e); // envia simbolo "maior" para o lcd
comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7
escreve_lcd(' '); // envia simbolo "espaço" para o lcd
}
else
{
bip(1000,2);
ventilador = 0; // desliga o ventilador
comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7
escreve_lcd(0x3e); // envia simbolo "maior" para o lcd
comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3
escreve_lcd(' '); // envia simbolo "espaço" para o lcd
}
break; // retorna da função
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
setup_adc_ports (no_analogs);
setup_counters (rtcc_internal, WDT_2304MS);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
loop:
while(TRUE) // rotina principal
{
RESTART_WDT(); // incia o watch-dog timer
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Verifica se algum botão foi pressionado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if (!f_tela_principal)
{
tela_principal();
}
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão S1 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
trata_menu:
//ligar time - out
if (filtro != 0) // Ação já foi executada?
{
filtro --; // não, decrementa o filtro
if (filtro == 0) // fim do filtro do botão?
{ // sim, executa tarefa
if (contador_tela < 2) // De selecionar a próxima tarefa?
{
contador_tela ++;// sim, incrementa contador de seleção de tarefa
sel_tela_menu(); // seleciona a tela de menu
time_out = 0; // re-inicia contagem do tempo de time-out
}
else // não,
{
contador_tela = 1;// Volta para a primeira tela do menu
sel_tela_menu(); // carrega a tela de menu
time_out = 0; // re-inicia contagem do tempo de time-out
}
}
}
goto loop; // sim, volta para o loop principal
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão S2 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
trata_enter:
if (filtro != 0) // Ação já foi executada?
{
filtro --; // não, decrementa o filtro
if (filtro == 0) // fim do filtro do botão?
{
sel_tela_enter(); // sim, carrega a tela de seleção de tarefa
time_out = 0; // re-inicia contagem do tempo de time-out
}
}
goto loop;
}
default:
contador = 0;
}
} // não, sai da int.
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
Valor máximo da
resolução do AD (10 bits)
+5V
- 4,7K 330R
P2 + RA1
10K
LM358 +5V
1uF
7
DB0 VDD 2 10K
8
DB1 VO 3
9 VSS 1
DB2
10
DB3
11
DB4 RS
12 4
DB5 RS
13 6
DB6 EN EN
14 5
DB7 R/W
LCD
+5V
RESET 10K
+5V
MC1
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
RS 8 RE0 RB2
35
+5V EN 9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
WATCHDOG, PRESCALER.
Configura AD:
RA0,RA1 e RA3 como entradas analógicas.
adc = 10 bits
Tensão de Refêrencia interna (VDD e VSS)
Frequencia de conversão = fosc / 32
Selecionado Canal 1
Módulo ligado
Inicializa LCD
LIMPA WATCHDOG
Inicia e lê o resultado da
conversão
Divide resultado da
multiplicação por 1023
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este exemplo foi elaborado para explicar o funcionamento do módulo de
// conversão analógico digital interno do PIC. É convertido o valor analógico
// presente no pino RA2 do microcontrolador, sendo que este valor pode ser
// alterado através do potenciômetro P2 da placa MCLAB2. O valor da conversão
// A/D é ajustado numa escala de 0 à 5V e mostrado no LCD.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// O arquivo de definições do pic utilizado deve ser referenciado para que
//os nomes definidos pela Microchip possam ser utilizados, sem a necessidade
//de redigitação.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definições para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000, RESTART_WDT)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
float conversao = 0; // armazena o resultado da conversão AD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As saídas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina que envia um COMANDO para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina que envia um DADO a ser escrito no LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void limpa_lcd()
{
comando_lcd(0x01); // limpa lcd
delay_ms (2);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tela Principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void tela_principal()
{
comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 3
printf (escreve_lcd, "Voltimetro"); // imprime mensagem no lcd
comando_lcd(0xcd); // posiciona o cursor na linha 1, coluna 14
printf (escreve_lcd, " V"); // imprime mensagem no lcd
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
setup_adc_ports (RA0_RA1_RA3_analog);
setup_adc (adc_clock_div_32);
setup_counters (rtcc_internal, WDT_2304MS);
set_adc_channel (1); // seleciona o canal 1 do AD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
loop:
while(TRUE) // rotina principal
{
RESTART_WDT(); // incia o watch-dog timer
conversao = read_adc(); // inicia conversão AD
conversao = (conversao * 5); // faz regra de 3 para converter o valor,
conversao = (conversao / 1023); // das unidades de AD em Volts.
comando_lcd(0xC2); // posiciona o cursor na linha 1, coluna 2
printf (escreve_lcd,"%1.9f", conversao);// envia dados para o display de LCD
// 1 número inteiro e 9 casas decimais.
1. Mude a configuração do A/D para que ele retorne apenas os 8 bits mais significativos.
2. Altere a função de escrita no LCD para que ela imprima apenas 3 casas depois da virgula.
3. Mude a configuração do A/D para que ele realize as conversões com a Fosc/8.
Então antes de utilizar o PWM, estude o funcionamento do Módulo CCP para um melhor
aproveitamento.
Este conhecimento pode ser adquirido através do livro Conectando o PIC.
7 VDD 2 10K
DB0
8
DB1 VO 3
9 VSS 1
DB2
10
DB3
11
DB4
4
12
DB5 RS RS
13 6
DB6 EN
14 5
DB7 R/W
EN
LCD
+5V
10K
RESET
+5V
MC1
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
RS 8 RE0 RB2
35
+5V EN 9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
TACOMETRO 23
RC4 RC7
26
24 25
RC5 RC6
16F877A
+5V +5V +5V +5V
S1 S2 S3 S4
+Vcc
MINI VENTILADOR
1N4148
+5V
+5V
BC337
4,7K
150R 10K
1K
SIR381583F RPT38PT3F
TACOMETRO
BC337
1K
M A IN
C O N FIG U R AÇ Õ E S IN IC IAIS
T R IS , P O R T AS ,
W A T C H D O G , P R E SC A LE R .
C onfigura T im er0
Inic ializa LC D
Lim pa W AT C H D O G
S IM
E sc reve tela princ ipal ? T ela principal
NÃO
S IM
B O T Ã O U P P R ES S.? T rata B otão U P
N ÃO
BO T ÃO D O W N S IM
T rata B otão D O W N
P R ES S .?
N ÃO
N ÃO
G rava D ados em SIM
S alva dados em EE PR O M
E E PR O M ?
N ÃO
N ÃO
A tualiza P wm
SIM SIM
Ação já foi executada ? Ação já foi executada ?
NÃO NÃO
NÃO NÃO
Fim do Filtro ? Fim do Filtro ?
SIM SIM
A A
NÃO
FIM DA INTERRUPÇÃO
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este exemplo foi elaborado para explicar o funcionamento do módulo de
// PWM e da escrita da EEPROM interna do microcontrolador. Um ventilador terá
// a sua velocidade controlada através do PWM, o valor ajustado poderá ser
// salva na memória EEPROM e restaurado através dos botões.
// A velocidade do ventilador é medida em rotações por segundo, através do
// timer1 e mostrada no lcd.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa EEPROM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#rom 0x2100 = {0x03,0xe8} // carrega eeprom com valor inicial, inicia PWM com 97%
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
float duty_cycle = 0; // armazena o resultado da conversão AD
long int duty_cycle1 = 0; // armazena o resultado da conversão AD
long int periodo_pulso = 0; //
long int rotacao = 0; // rps do ventilador
int end = 0; // variável para endereçamento da eeprom
int flags1 = 0; // flags
int filtro = t_filtro; // inicia filtro dos botões
int temp1 = 125; // variável aux para int de tmr0
int turbo = 1; // inicia turbo das teclas
int dado; // variável de dados para eeprom
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08
#byte porte=0x09
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As saídas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função que envia um COMANDO para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void limpa_lcd()
{
comando_lcd(0x01); // limpa lcd
delay_ms (2);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função de inicialização do Display de LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
comando_lcd(0x30); // envia comando para inicializar display
delay_ms(4); // espera 4 milisengundos
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para imprimir a Tela Principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void tela_principal()
{
comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0
printf (escreve_lcd, "Duty cycle RPS"); // imprime mensagem no lcd
void salva_dados()
{
write_eeprom (end,dado);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Lê Dados na EEPROM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// lê o dado na eeprom no endereço indicado através da variável "end",
// o dado lido é carregado na variável "dado".
le_dados(end)
{
dado = read_eeprom (end);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Atualiza PWM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void atualiza_pwm()
{
set_pwm2_duty(periodo_pulso); // atualiza duty cicle do PWM
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
loop:
while(TRUE) // rotina principal
{
RESTART_WDT(); // incia o watch-dog timer
if (atualiza_lcd != 0)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão de incremento (UP) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão de decremento (down) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão ler dados da EEPROM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento do Botão salvar dados na EEPROM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} // fecha while
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina de Tratamento de interrupção de TMR0 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta interrupção ocorrerá a cada 8ms.
// A variável auxiliar temp1 será utilizada para contar 125 interrupções,
// totalizando 1 segundo. Quando isto ocorrer, a variável rotação será carregada
// com o valor de rotações por segundo do ventilador.
#int_rtcc
void trata_int_tmr0(void)
{
set_rtcc(256-125);
if (temp1 == 0 ) // ja passou 1 segundo?
{ // Sim,
rotacao = get_timer1(); // le valor do timer 1
set_timer1 (0); // zera timer 1
rotacao = (rotacao / 7);
// divide por 7 (quantidade de palhetas do ventilador)
atualiza_lcd = 1; // habilita atualização do LCD
temp1 = 125; // re-inicia temp1
}
else // Não,
{
temp1 --; // decrementa temp1
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1. Mude a freqüência do PWM para que possamos ajustar o Duty cycle de 0 a 100%.
2. Ative os dois PWM`s um para o ventilador e outro para a resistência.
+5V
+5V
1uF
7
DB0 VDD 2 10K
8
DB1 VO 3
9 VSS 1
DB2
10
DB3
+5V 11
DB4 RS
12 4
DB5 RS
13 6
DB6 EN EN
14 5
DB7 R/W
RESET
+5V
10K MC1 LCD
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
8 35
+5V RE0 RB2
RS 9 34
+5V RE1 RB1
EN 10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
10K 10K 16 21
1 A0 VCC
8 RC1 RD2
2 7
4MHz 17 20
A1 WP RC2 RD1
3 A2 6 18 19
SCL RC3 RD0
4 GND 5 23 26
SDA RC4 RC7
24 25
RC5 RC6
24C04
16F877A
+5V
1uF
1uF
1 C1+
3 C1 -
1uF
4 C2+ +C 2
5 C2 - -C 6
12
1K
13 T1IN T1OUT
14 R1OUT R1IN 11
8 9 +5V
T2IN T2OUT
7 R2OUT R2IN 10
15 16
GND VCC 1uF
3 2 5
MAX-232
CONECTOR
DB9 FEMEA
MAIN
CONFIGURAÇÕES INICIAIS
TRIS, PORTAS,
W ATCHDOG, PRESCALER.
Inicializa LCD
Tela principal
Habilita as interrupções
Limpa W ATCHDOG
SIM
Inicia coleta de dados ? Coleta Dados
NÃO
SIM
Deve transmitir dados
TX Dados para o PC
para o PC ?
NÃO
NÃO
NÃO
Chegou comando do
PC ?
SIM
NÃO
Tarefa = para coleta de dados
Escreve no LCD:
"Coletando Dados"
Lê Dados do AD
Salva em EEPROM Serial
NÃO
Fim da Coleta de Dados ?
SIM
Escreve no LCD:
"Pronto para TX"
Return
Escreve no LCD:
"TX para o PC"
SIM
Escreve no LCD:
"Fim da Trans..."
Escreve no LCD:
"Press Inicio"
delay de 1 segundo
Return
delay 10ms
Return
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este exemplo foi elaborado para explicar as funcões de I2C do compilador
// CCS. Neste exemplo iremos coletar dados do AD e armazenar estes dados na
// EEPROM externa (24c04), estes dados serão enviados ao PC para a
// visualização dos mesmos. O PC controlará as funções do coletor de dados.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configuração do Módulo I2C *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configuração da USART *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constante internas do tipo Enumeração *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum selecao_de_tarefa
{
aguarda_comando, coleta_de_dados, transmite_para_pc, parar_coleta
}tarefa;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08
#byte porte=0x09
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
#bit atualiza_lcd = flags1.0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As saídas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
#bit rs = porte.0 // via do lcd que sinaliza recepção de dados ou comando
#bit enable = porte.1 // enable do lcd
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para escrita na EEPROM externa I2C *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
escr_mem_serial ()
{
i2c_start(); // Condição de início
i2c_write(ctrl_escr); // Envia o byte de controle de leitura
i2c_write(end_low); // Envia endereço baixo
i2c_write(dado); // Escreve dado na E²PROM
i2c_stop(); // Condição de parada
delay_ms(10); // espera a gravação estar completa
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para leitura na EEPROM externa I2C *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
le_mem_serial ()
{
i2c_start(); // Condição de início
i2c_write(ctrl_escr); // Envia o byte de controle de leitura
i2c_write(end_low); // Envia endereço baixo
i2c_start(); // Nova condição de início
i2c_write(ctrl_le); // Envia o byte de controle de leitura
dado = i2c_read(0); // lê o dado armazenado na E²PROM
i2c_stop(); // Condição de parada
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função que envia um DADO a ser escrito no LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void limpa_lcd()
{
comando_lcd(0x01); // limpa lcd
delay_ms (2);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função de inicialização do Display de LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
comando_lcd(0x30); // envia comando para inicializar display
delay_ms(4); // espera 4 milisengundos
comando_lcd(0x30); // envia comando para inicializar display
delay_us(100); // espera 100 microsengundos
comando_lcd(0x30); // envia comando para inicializar display
comando_lcd(0x38); // liga o display, sem cursor e sem blink
limpa_lcd(); // limpa lcd
comando_lcd(0x0c); // display sem cursor
comando_lcd(0x06); // desloca cursor para a direita
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para imprimir a Tela Principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void tela_principal()
{
limpa_lcd()
comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0
printf (escreve_lcd, "Coletor de dados"); // imprime mensagem no lcd
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina para coleta de dados *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina para transmitir dados para o PC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
tx_dados_pc()
{
comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0
printf (escreve_lcd, " TX para o PC "); // imprime mensagem no lcd
do
{
le_mem_serial (); // le dados da eeprom
printf ("%x\r\n",dado); // envia ao PC o valor da eeprom externa
end_low +=1; // incrementa endereço, seleciona nova posição
delay_ms(100); // delay de 100 ms
}while (end_low != 0); // fim da transmissão de dados
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tratamento de recepção serial *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void recebe_comando()
{
if (kbhit())
{
comando = getc();
if (comando == 0x55) // recebeu o camando de coleta de dados ?
{
tarefa = coleta_de_dados; // sim, libera coleta de dados
}
if (comando == 0xaa) // recebeu o camando de transmissão de dados ?
{
tarefa = transmite_para_pc; // sim, transmite dados para o PC
}
if (comando == 0x7f) // recebeu o camando para cancelar coleta de dados ?
{
tarefa = parar_coleta; // sim, cancela coleta de dados
}
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
loop:
while(true) // rotina principal
{
RESTART_WDT(); // incia o watch-dog timer
recebe_comando();
if (tarefa == coleta_de_dados) // inicia coleta de dados ?
{
end_low = 0; // sim, carrega endereço inicial
coleta_dados(); // executa função de coleta de dados
}
if (tarefa == transmite_para_pc)// inicia transmissão de dados para o PC ?
{
end_low = 0; // sim, carrega endereço inicial
tx_dados_pc(); // executa função de transmissão de dados
}
if (tarefa == parar_coleta) // cancela coleta de dados ?
{
end_low = 0; // sim, carrega endereço inicial
tarefa = aguarda_comando; // espera envio de comando do PC
tx_pc = 11; // fim da coleta de dados
tx_dados_pc(); // envia comando para o PC
}
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1. Mude a rotina de coleta de dados para que seja armazenado na EEPROM um valor de 0 à
5V e não um valor de 0 a 255. Implemente a regra de três necessária.
2. Altere a configuração do A/D para que ele retorne os 10 bits do resultado da conversão e
salve este dado na EEPROM.
+5V
RESET 10K
+5V
MC1
1 32
MCLR VDD
2 31
RA0 VSS
3 40
RA1 RB7
4 39
RA2 RB6
5 38
RA3 RB5
6 RA4 RB4 37
7 36
RA5 RB3
RS 8 RE0 RB2
35
+5V EN 9 34
RE1 RB1
10 33
RE2 RB0
11 30
VDD RD7
12 29
VSS RD6
13 28
OSC1 RD5
14 27
OSC2 RD4
15 22
RC0 RD3
16 21
4MHz RC1 RD2
17 20
RC2 RD1
18 19
RC3 RD0
23 26
RC4 RC7
24 25
RC5 RC6
16F877A
+5V
1uF
1uF
1 C1+
3 C1 -
1uF
4 C2+ +C 2
5 C2 - -C 6
12
1K
13 T1IN T1OUT
14 R1OUT R1IN 11
8 9 +5V
T2IN T2OUT
7 R2OUT R2IN 10
15
GND VCC 16 1uF
3 2 5
MAX-232
CONECTOR
DB9 FEMEA
Inicializa a variável
X=0
NÃO
X < (2 * PI)
SIM
LIMPA W ATCHDO G
Y = seno (x)
Incrementa a variável X
X = x + 0,01
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este software foi desenvolvido para mostrar a implementação de funções
// matemáticas, como exemplo estamos calculando o seno e enviando para o
// PC os valores de "x" e "y" para serem plotados.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição dos I/O's e opções de configuração *
* das funções para periféricos *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Carrega bibliteca Matemática *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <math.h> // microcontrolador utilizado
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos
fusíveis
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definições para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configuração da Usart *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização das variáveis *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Neste bloco estão definidas as variáveis globais do programa.
float y;
float x;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de constantes facilita a programação e a manutenção.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Declaração dos flags de software *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//A definição de flags ajuda na programação e economiza memória RAM.
//Este programa não utiliza nenhum flag de usuário
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08
#byte porte=0x09
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENTRADAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// As entradas devem ser associadas a nomes para facilitar a programação e
//futuras alterações do hardware.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SAÍDAS *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E
//FUTURAS ALTERAÇÕES DO HARDWARE.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
setup_adc_ports (no_analogs); // desliga as entradas analógicas
setup_counters (rtcc_internal, wdt_2304ms);// tmr0 clock interno, ps: 1:64
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
while(TRUE)
{
x=0;
while(x < 2*PI)
{
restart_wdt(); // limpa wdt
y = sin (x); // calculo da função
printf ("X=%1.3f",x); // envia ao PC o valor de x
printf (" ");
printf ("Y=%1.3f\r\n",y); // envia ao PC o valor de y
x = x + 0.01; // incrementa x
}
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */