P. 1
Apostila Linguagem C Para PIC

Apostila Linguagem C Para PIC

5.0

|Views: 4.449|Likes:
Publicado porleinat5532
Apostila de Linguagem C para pic
Apostila de Linguagem C para pic

More info:

Published by: leinat5532 on Aug 14, 2010
Direitos Autorais:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

08/14/2013

pdf

text

original

Sections

Curso de Linguagem C

Rinaldo Câmara Gonçalves Labtools – Mosaico Didactic Division Revisão 2

Sumário
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 Linguagem C para PIC 3

ESQUEMA ELÉTRICO..................................................................................................................................................79 FLUXOGRAMA ............................................................................................................................................................80 CÓDIGO ....................................................................................................................................................................82 EXERCÍCIOS PROPOSTOS ..........................................................................................................................................86 ANOTAÇÕES ..............................................................................................................................................................87 RECURSOS AVANÇADOS: EXEMPLO 8 CONTROLE DO PWM E EEPROM INTERNA ..................................88 RECURSOS DO LIVRO ................................................................................................................................................88 LÓGICA DO EXEMPLO .................................................................................................................................................88 ESQUEMA ELÉTRICO..................................................................................................................................................89 FLUXOGRAMA ............................................................................................................................................................90 CÓDIGO ....................................................................................................................................................................93 EXERCÍCIOS PROPOSTOS ..........................................................................................................................................99 ANOTAÇÕES ............................................................................................................................................................100 RECURSOS AVANÇADOS: EXEMPLO 9 COLETOR DE DADOS ....................................................................101 RECURSOS DO LIVRO ..............................................................................................................................................101 LÓGICA DO EXEMPLO ...............................................................................................................................................101 ESQUEMA ELÉTRICO................................................................................................................................................102 FLUXOGRAMA ..........................................................................................................................................................103 CÓDIGO ..................................................................................................................................................................109 EXERCÍCIOS PROPOSTOS ........................................................................................................................................114 ANOTAÇÕES ............................................................................................................................................................115 RECURSOS AVANÇADOS: EXEMPLO 10 FUNÇÕES MATEMÁTICAS..............................................................116 RECURSOS DO LIVRO ..............................................................................................................................................116 LÓGICA DO EXEMPLO ...............................................................................................................................................116 ESQUEMA ELÉTRICO................................................................................................................................................117 FLUXOGRAMA ..........................................................................................................................................................118 CÓDIGO .................................................................................................................................................................119 EXERCÍCIOS PROPOSTOS ........................................................................................................................................121 ANOTAÇÕES ............................................................................................................................................................122

4

Linguagem C para PIC

Recursos Básicos: Exemplo 1
1.1 - Recursos do Livro

Botão e Led

Para o bom entendimento deste nosso primeiro exemplo são necessários os conhecimentos de programação em linguagem C, comandos de controle de Fluxo (cap.7 do livro Programação em C), declaração de variáveis, constantes e tipos de dados (cap.5 do livro Programação em C), diretivas de configuração dos pinos de I/O (cap.10-pág.170, cap.11.5; 11.6-pág.202; 11.7 e cap.12.2-pág. 250 do livro Programação em C).

1.2 - Lógica do exemplo
Nosso exemplo será composto de um programa capaz de ler um botão e controlar um led. Com o botão S1 pressionado o led L2 acende, com o botão S1 liberado o led L2 apaga. Veremos os primeiros comandos para controle de fluxo de um programa e como ler uma entrada e acionar uma saída, fundamental já que estamos trabalhando com um microcontrolador. Neste exemplo você verá o comando WHILE, (Faça enquanto for verdadeiro) sendo utilizado para o controle de fluxo de nossa rotina principal, forçando um loop infinito. O comando IF ELSE, (Se verdadeiro {comando}, Se falso {comando}), realiza o teste do botão e determina o caminho a ser seguido, se acende ou apaga o led. Caso o botão esteja pressionado o teste determina que o led deve acender, caso contrário o led será apagado. Para o teste do botão está sendo utilizado o operando “!” (NOT), para botão pressionado temos nível lógico zero no pino de I/O, neste caso o teste com o comando IF será verdadeiro para botão pressionado e falso para botão liberado.

Linguagem C para PIC

5

1.3 - Esquema Elétrico

+5V

RESET 10K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 23 24

MC1
MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5 VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

+5V

RB0
10K

RB1

330R

+5V

S1

L2

4MHz

16F877A

6

Linguagem C para PIC

1.4 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

A LIMPA WATCHDOG

NÃO

BOTÃO S1 PRESS.?

SIM

APAGA LED L2

ACENDE LED L2

A

Linguagem C para PIC

7

1.5 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 1 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * Este software está preparado para demonstrar o controle este primeiro programa demonstrará o estado de um botão * * * * * * * * * * * * * * * * */ dos pinos de I/O por meio de um led.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #use #use #use #use #byte #byte #byte #byte #byte fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e) porta portb portc portd porte = = = = = 0x05 0x06 0x07 0x08 0x09

8

Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit

* * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programação do hardware. // Estado do botão // 1 -> Liberado // 0 -> Pressionado

* * */ e

botao = portb.0

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // As saídas devem ser associadas a nomes para facilitar a programação //futuras alterações do Hardware. #bit led = portb.1 // Led correspondente ao botão // 1 -> Led ligado // 0 -> Led desligado

* * */ e

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () { setup_counters(RTCC_INTERNAL, WDT_2304MS); set_tris_a(0b11111111); set_tris_b(0b11111101); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; // // // // // // configuração dos pinos de I/O

limpa limpa limpa limpa limpa

porta portb portc portd porte

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); if(!botao) { led = 1; } else led=0; } }

// testa botão // Se botão = 0, então led = 1 // caso contrário, led = 0 // FIM DO PROGRAMA

1.6 -

Linguagem C para PIC

9

1.7 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 1. Utilize as funções do Compilador para controlar o Led, OUTPUT_HIGH e OUTPUT_LOW. 2. Altere a lógica do programa para que o led acenda com o botão liberado e apague com o botão pressionado. 3. Troque o pino de I/O que controla o botão, por exemplo, utilize o pino RB3. 4. Com o botão pressionado acenda o led 2 e apague o led 3, para o botão liberado apague o led 2 e acenda o led 3.

10 Linguagem C para PIC

1.8 - Anotações

Linguagem C para PIC

11

Recursos Básicos: Exemplo 2
1.9 - Recursos do Livro

Pisca – Pisca Variável

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, funções do compilador para controle de atraso (cap.11.4 pág. 195 do livro Programação em C), Operadores para criação de expressões lógicas e aritméticas (cap.6 do livro Programação em C), diretivas de configuração para uso de função de atraso (cap.10, pág.169 do livro Programação em C).

1.10 - Lógica do exemplo
A finalidade de nosso exemplo é demonstrar a inversão de portas e a utilização da função de delay da Linguagem C. Através dos botões S1 e S2, Up e Down é possível ajustar a freqüência de oscilação dos Leds 3 e 4 da placa McLab2. As constantes min e max determinam os limites, máximos e mínimos de ajuste da freqüência de oscilação. Para a inversão das portas está sendo utilizado o operador lógico “~”, (NOT, complemento de 1), com este operando estaremos invertendo bit a bit o conteúdo do registrador portb. A função delay_ms gera um atraso de milisegundos usando o ciclo de máquina, ou seja, o programa fica travado nesta função até o tempo desejado. O camando For (inicialização, teste condicional, incremento) é utilizado para controle do laço da rotina de delay, definindo a quantidades de vezes que o laço será executado, nesta rotina não utilizaremos a opção de inicialização do comando For, sendo a mesma executada fora do laço.

Linguagem C para PIC

13

1.11 - Esquema Elétrico

+5V

RESET 10K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 23 24

MC1
MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5 VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

+5V

4MHz

16F877A

+5V

+5V

10K

10K

RB0 S1

RB1 S2

RB2
330R

RB3
330R

L3

L4

14 Linguagem C para PIC

1.12 - Fluxograma
A MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

NÃO

BOTÃO S1 PRESS.?

SIM

INICIALIZA PORTB COM 0X0F B LIMPA WATCHDOG

SIM

TEMPO = MAX?

NÃO

INCREMENTA TEMPO COMPLEMENTA PORTB

A NÃO BOTÃO S2 PRESS.? SIM

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

B

NÃO

CONTADOR ≠ 0

SIM DELAY (10MS)

Linguagem C para PIC

15

1.13 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 2 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Este software demonstrará a utilização da função de delay e //a frequência de oscilação dos leds é controlada pelos botões * * * * * * * * * * * * */ a inversão de portas 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 //Este programa não utiliza constantes #define max 255 // Limite de ajuste do #define min 10 * * * * * * * * * * * * * * * * * * * * * * * * */ e a manutenção. tempo

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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) #byte #byte #byte #byte porta portb portc portd = = = = 0x05 0x06 0x07 0x08

16 Linguagem C para PIC

#byte porte = 0x09 /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit botao_0 #bit botao_1

* * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programação do hardware. = portb.0 // Estado do botão_0 // 1 -> Liberado // 0 -> Pressionado = portb.1 // Estado do botão_1 // 1 -> Liberado // 0 -> Pressionado

* * */ e

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // As saídas devem ser associadas a nomes para facilitar a programação //futuras alterações do hardware.

* * */ e

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 portb portc portd porte = = = = = 0x00; 0x0f; 0x00; 0x00; 0x00; // carrega portb com valor inicial

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); portb = ~portb; if (!botao_0) // { if (tempo != max) // { tempo = tempo + 1; // } } // // complemanta o portb O botão_0 foi pressionado? sim, tempo é diferente de max? não, incrementa tempo botão_0 liberado, testa botão 1

if (!botao_1) // O botão 1 foi pressionado ? { if (tempo != min) // sim, tempo é diferente de min? { tempo = tempo - 1; // não, decrementa tempo } } // botão_1 liberado contador = tempo; // carrega contador for (;contador!=0; contador--) // contador é diferente de 0? se sim // decrementa contador e executa o comando delay_ms(10); // comando: delay de 10 milisegundos. } } // FIM DO PROGRAMA

Linguagem C para PIC

17

1.14 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 1. Implemente a inversão de portas para que o led 3 e o led 4 pisquem alternadamente. 2. Utilize a forma reduzida para incrementar e decrementar a variável tempo. 3. Troque a função delay_ms por delay_us e ajuste as constantes para obter o mesmo ajuste de freqüência. 4. Substitua o comando For pelo comando While.

18 Linguagem C para PIC

1.15 - Anotações

Linguagem C para PIC

19

Recursos Básicos: Exemplo 3
1.16 - Recursos do Livro

Contador Hexadecimal

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos nos exemplos anteriores e tabela de constante (cap.12.21 pág. 309 do livro Programação em C).

1.17 - Lógica do exemplo
Através dos botões S1 e S2 o contador será incrementado ou decrementado, e o seu valor mostrado no display de sete segmentos ds4. A finalidade de nosso exemplo é demonstrar a implementação de tabelas utilizando a memória de programa, sendo está tabela uma matriz unidimensional, nossa tabela fará a conversão de BCD para sete segmentos, realizando a função de um circuito decodificador. Para o devido tratamento dos botões, neste exemplo foi implementada uma rotina de filtro para cada botão evitando o problema de debouncing, além do filtro foi criado um flag, para cada botão, que tem a função de indicar se a tecla está pressionada ou liberada. Desta forma para que o contador seja incrementado ou decrementado o botão deve ser pressionado e depois liberado. A variável contador será utilizada como indexador da tabela de constante, assim sendo para o contador igual à zero, será retornado o código de sete segmentos para o número zero e assim por diante.

20 Linguagem C para PIC

1.18 - Esquema Elétrico

220R +5V +5V RESET 10K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

MC1
MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5 VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

a b c d e f g Dp

DS4
a f e d g b c Dp

220R 4,7K

BC337

+5V

4MHz

16 17 18 23 24

16F877A

+5V

+5V

10K

10K

RB0 S1

RB1 S2

PIC16F877

Linguagem C para PIC

21

1.19 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

INICIALIZA PORTB COM 0X10 B LIMPA WATCHDOG

A

22 Linguagem C para PIC

A

NÃO

BOTÃO S1 PRESS.?

SIM

Re-carrrega o Filtro do Botão Marca botão liberado

O botão já estava pressionado ?

SIM

C

NÃO

NÃO

Filtro ≠ 0 ?

Marca Botão pressionado

SIM

Decrementa o Filtro NÃO

Contador ≠ Max ?

SIM Incrementa o contador Consulta tabela de conversão e atualiza o display

C

Linguagem C para PIC

23

C

NÃO

BOTÃO S2 PRESS.?

SIM

Re-carrrega o Filtro do Botão Marca botão liberado

O Botão já estava pressionado ?

SIM

B

NÃO

NÃO

Filtro ≠ 0 ?

Marca Botão pressionado

SIM

Decrementa o Filtro NÃO

Contador ≠ Min ?

SIM Decrementa o contador Consulta tabela de conversão e atualiza o display

B

24 Linguagem C para PIC

1.20 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * Exemplo 3 * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * // // * * * * * * * * */

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #define t_filtro 400 #define min 0 #define max 15 // tamanho do filtro // valor mínimo para o contador // valor máximo para o contador

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int contador=min; // long int filtro0=t_filtro; // long int filtro1=t_filtro; // int flags=0; // inicia contador com mínimo inicia filtro do bot1 inicia filtro do bot2 limpa os flags

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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)

Linguagem C para PIC

25

#byte #byte #byte #byte #byte

porta portb portc portd porte

= = = = =

0x05 0x06 0x07 0x08 0x09 * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programação do hardware. // Estado do botão UP // 1 -> Liberado // 0 -> Pressionado * * */ e

/* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit

botao_UP = portb.0

#bit

botao_DOWN = portb.1 // Estado do botão DOWN // 1 -> Liberado // 0 -> Pressionado * * */ e

/* * * // //

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * As saídas devem ser associadas a nomes para facilitar a programação 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;

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

26 Linguagem C para PIC

* Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 } } }

Linguagem C para PIC

27

1.21 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 1. 2. 3. 4. Modifique o programa para que o contador conte de 1 a 5. Implemente um botão para reset do contador. Altere a tabela para que as posições de A a F da tabela apaguem o display. Mude a contagem do dsp4 para o display dsp3.

28 Linguagem C para PIC

1.22 - Anotações

Linguagem C para PIC

29

Recursos Avançados: Exemplo 4
1.23 - Recursos do Livro

Maximização de Pinos de I/O

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos nos exemplos anteriores e mais, funções do compilador para controle de interrupção, tratamento automático (cap.12 pág.254 do livro Programação em C), controle do processador (cap.11 pág.223 do livro Programação em C), manipulação de Timers (cap.11.8 pág.211 do livro Programação em C), diretivas de configuração para uso de interrupções, #int_xxx e #priority (cap.10, pág.161 e pág.166 do livro Programação em C).

1.24 - Lógica do exemplo
Nosso exemplo será composto de um programa capaz de ler quatro botões e tocar o buzzer com uma freqüência diferente para cada combinação de botões. Para cada botão existe um led ligado no mesmo pino, que será utilizado para indicar os botões pressionados no momento. Utilizaremos os timers e duas interrupções para controlarmos a freqüência de leitura dos botões e a freqüência do buzzer: • Timer 0: controlará a freqüência de varredura dos botões; • Timer 2: controlará a freqüência do som. O som será feito excitando o buzzer com uma onda quadrada de freqüência variável. Variaremos esta freqüência alterando o valor de PR2, que controla o estouro deste timer. Desta forma, nosso programa principal será um loop infinito sem efeito algum. Somente ficaremos esperando o acontecimento das interrupções. Para a varredura dos botões ajustaremos a interrupção de TMR0 para aproximadamente 500Hz: Ciclo de Máq. 1 µs Prescale 8 Conta TMR0 256 Auxiliar Período 2048 µs Freqüência 488 Hz

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: Ciclo de Máq. 1 µs 1 µs Prescale 16 16 Postscale 1 1 PR2 16 240 Período 256 µs 3840 µs Freqüência 3906 Hz 260 Hz

Para facilitar a implementação, a cada interrupção inverteremos o estado do pino de acionamento do buzzer. Desta forma, a freqüência deste será equivalente à metade da freqüência da interrupção do TMR2. O Livro Conectando o PIC, possui um cápitulo dedicado a este assunto.

30 Linguagem C para PIC

1.25 - Esquema Elétrico

+5V

RESET 10K
1 2 3 4 5 6 7

MC1
MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5 VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

BUZZER

+5V

8 9 10 11 12 13 14 15 16 17 18 23 24

4MHz

16F877A

+5V

+5V

+5V

+5V

10K

10K

10K

10K

RB0

10K

RB1 S1

10K

RB2 S2

10K

RB3 S3

10K

330R

330R

330R

330R

S4

L1

L2

L3

L4

Linguagem C para PIC

31

1.26 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

LIGA AS INTERRUPÇÕES

LIMPA WATCHDOG

32 Linguagem C para PIC

INTERRUPÇÕES

NÃO

INT DE TMR0?

SIM

Trata TMR2

Trata TMR0

TRATA TMR2

NÃO

SAÍDA DO BUZZER ESTÁ LIGADA?

SIM

LIGA A SAÍDA DO BUZZER

DESLIGA A SAÍDA DO BUZZER

FIM DA INTERRUPÇÃO

Linguagem C para PIC

33

TRATA TMR0

Convetre pinos dos botões em entradas

Delay de 4 ciclos de máquina para estabilização do port

Lê todos os botões e guarda em variável temporária (STATUS_BOTÕES)

Converte pinos dos botões em saída

CHECA BOTÃO S1 NÃO

Reinicia Filtro

Botão S1 PRESS ?

Limpa Flag de botão pressionado (Status Leds)

SIM

Fim do Filtro ?

NÃO

SIM Marca flag de botão pressionado

CHECA BOTÃO S2

CHECA BOTÃO S3

CHECA BOTÃO S4

A

34 Linguagem C para PIC

AÇÃO DOS BOTÕES

A

Atualiza leds conforme botões pressionados

NÃO

Algum botão pressionado ?

SIM

Inicializa PER com 255

Consulta tabela conforme conbinação de botões pressionados

Deliga interrupção de TMR2

Inicializa TMR2

Desliga a saída do Buzzer

Liga Interrupção de TMR2

FIM DA INTERRUPÇÃO

Linguagem C para PIC

35

1.27 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * Exemplo 4 * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Este software está preparado para ler quatro botões e //duração variavel conforme a tecla pressionada, além de //indicando a última tecla pressionada. * * * * * * * * */

* * * * * * * * * * * * * * * * * * */ tocar o buzzer com acender o led

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 20 // tamanho do filtro

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int status_botoes = 0; int status_leds = 0; int per = 0; int int int int filtro1 filtro2 filtro3 filtro4 = = = = t_filtro; t_filtro; t_filtro; t_filtro; // armazena o estado lógico dos botões // atualiza leds conforme o botão pressionado // limitador de contagem do Timer2 // // // // inicia inicia inicia inicia filtro filtro filtro filtro do do do do botao1 botao2 botao3 botao4

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use #byte #byte #byte #byte #byte fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e) porta portb portc portd porte = = = = = 0x05 0x06 0x07 0x08 0x09

36 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programação do hardware. * * */ e

botao1 = status_botoes.0 // Estado do botão 1 // 1 -> Liberado // 0 -> Pressionado botao2 = status_botoes.1 // Estado do botão 2 // 1 -> Liberado // 0 -> Pressionado botao3 = status_botoes.2// Estado do botão 3 // 1 -> Liberado // 0 -> Pressionado botao4 = status_botoes.3 // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado * * */ E

#bit

#bit

#bit

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO //FUTURAS ALTERAÇÕES DO HARDWARE. #bit #bit #bit #bit #bit botao1_press botao2_press botao3_press botao4_press = = = = status_leds.0 status_leds.1 status_leds.2 status_leds.3

buzzer = porta.5

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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

Linguagem C para PIC

37

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer } } /* * * // // // // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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); delay_cycles(4); status_botoes = portb; set_tris_b(0b00000000);

// configura os pinos como entrada para // testar os botões // aguarda 4 ciclos de máquina para a // estabilização do portb // lê o status dos botoes, salva em variável // temporária // configura os pinos como saída para // controle dos leds

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) { filtro1--; if (filtro1 == 0) { botao1_press = 1; } } else { filtro1 = t_filtro; botao1_press = 0; } // // // // testa botão 1 botão 1 está pressionado ? Sim, então decrementa o filtro acabou o filtro do botão 1 ?

// marca que o botão está pressionado

// botão 1 liberado // inicia o filtro do botão 1 // marca que o botão foi liberado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao2) { filtro2--; if (filtro2 == 0) { botao2_press = 1; } } else { filtro2 = t_filtro; botao2_press = 0; } /* * * * * * * * * * * * * * * * * * * * * Tratamento do * * * * * * * * * * * * * * * * * * * * if (!botao3) { // // // // testa botão 2 botão 2 está pressionado ? Sim, então decrementa o filtro fim do filtro do botão 2 ?

// marca que o botão está pressionado

// botão 2 liberado // inicia o filtro do botão 2 // marca que o botão foi liberado * * * * * * * * * * * * * * * * Botão 3 * * * * * * * * * * * * * * * * */ // testa botão 3 // botão 3 está pressionado ?

38 Linguagem C para PIC

filtro3--; if (filtro3 == 0) { botao3_press = 1; } } else { filtro3 = t_filtro; botao3_press = 0; } /* * * * * * * * * * * * * * * * * * * * * Tratamento do * * * * * * * * * * * * * * * * * * * * if (!botao4) { filtro4--; if (filtro4 == 0) { botao4_press = 1; } } else { filtro4 = t_filtro; botao4_press = 0; }

// Sim, então decrementa o filtro // fim do filtro do botão 3 ? // marca que o botão está pressionado

// botão 3 liberado // inicia o filtro do botão 3 // marca que o botão foi liberado * * * * * * * * * * * * * * * * Botão 4 * * * * * * * * * * * * * * * * */ // testa botão 4 // botão 4 está pressionado ? // Sim, então decrementa o filtro // fim do filtro do botão 4 ? // marca que o botão está pressionado

// botão 4 liberado // inicia o filtro do botão 4 // 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 } }

Linguagem C para PIC

39

1.28 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 1. Utilize as funções disponíveis do Compilador para inverter o estado do buzzer. 2. Modifique o controle dos leds, os botões pares controlam os leds impares e os botões impares controlam os leds pares, conforme a tabela abaixo. Botão 1 Botão 2 Botão 3 Botão 4 Led 2 Led 1 Led 4 Led3

40 Linguagem C para PIC

1.29 - Anotações

Linguagem C para PIC

41

Recursos Avançados: Exemplo 5
1.30 - Recursos do Livro

Varredura de Display

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos nos exemplos anteriores e mais, funções do compilador para controle de interrupção, tratamento manual (cap.12 pág.254 do livro Programação em C), controle do processador (cap.11 pág.223 do livro Programação em C), manipulação de Timers (cap.11.8 pág.211 do livro Programação em C), introdução de código em assembly no programa em C (cap.10, pág.151 do livro Programação em C),retorno de valores em funções assembly (cap.9, pág.147 do livro Programação em C), diretivas de configuração para uso de interrupções, #int_global e #priority (cap.10, pág.162 e pág.166 do livro Programação em C).

1.31 - Lógica do exemplo
O exemplo desenvolvido para esta aula faz muito mais que simplesmente implementar a varredura dos displays. Trata-se de um contador regressivo de segundos, ou seja, um temporizador capaz de contar até 9.999 segundos. Para isso, utilizaremos os displays para indicar o valor atual do temporizador. A primeira tecla (S1) não possui nenhuma função. Por outro lado, o led relacionado a ela (L1) será utilizado para indicar o estado do temporizador: L1 Aceso Apagado Descrição Temporizador em contagem regressiva Temporizador paralisado

Os demais botões apresentam as funções de controle do temporizador: Botão S2 S3 S4 Descrição Incrementa o valor inicial em 1 segundo Decrementa o valor inicial em 1 segundo Inicia e paralisa o temporizador

Os botões de incremento e decremento operam de forma rotativa, isto é, comutam automaticamente entre 0000 e 9999. Outra característica destes botões é que eles executam suas funções repetidamente quando mantidos pressionados e só funcionam quando o temporizador está paralisado. Ao atingir o valor zero (0000) o temporizador é automaticamente paralisado, desligandose o led indicativo (L1). Para o sistema de varredura foram criadas 4 variáveis para armazenamento dos dígitos mostrados nos respectivos displays: UNIDADE, DEZENA, CENTENA e MILHAR. Estas variáveis representam o valor atual do temporizador e são incrementadas e decrementadas através dos botões. Na verdade, os botões alteram diretamente o valor da unidade. A lógica do sistema compara este valor com os limites (0 e 9) para alterar ou não os demais dígitos. A freqüência de varredura é controlada pela interrupção de Timer0. Ajustamos seus parâmetros para que a comutação entre displays (tempo da interrupção) seja de aproximadamente 4kHz: Ciclo de Máq. 1 µs
42 Linguagem C para PIC

Prescale 1

Conta TMR0 256

Auxiliar -

Período 256 µs

Freqüência 3900 Hz

A freqüência de varredura será a freqüência de comutação dividida pelo número de displays, que no nosso caso será de aproximadamente 1kHz. Dentro do tratamento da interrupção de TMR0 é desligado o display atual, carregado o valor do dígito correspondente ao display e ligado o display seguinte. Quanto à contagem dos segundos, utilizamos a interrupção de Timer1 para esta finalidade. Veja os ajustes dos parâmetros para esta interrupção: Ciclo de Máq. 1 µs Prescale 8 Conta TMR1 62500 Auxiliar 2 Período 1.000.000 µs Freqüência 1 Hz

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.

Linguagem C para PIC

43

1.32 - Esquema Elétrico
220R a b c d e f g Dp DS1
a f e d g b c Dp f e d

DS2
a g b c Dp f e

DS3
a g b c d Dp f e

DS4
a g b c d Dp

220R

Comum 1 BC337

Comum 2 BC337

Comum 3 BC337

Comum 4 BC337

+5V +5V RESET 10K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

4,7K

4,7K

4,7K

4,7K

MC1
MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5 VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

4MHz

16 17 18 23 24

16F877A

+5V

+5V

+5V

RB0
330R 10K 10K 10K

RB1 S2
L1

RB2 S3

RB3 S4

44 Linguagem C para PIC

1.33 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

Configura Timer1

Liga as interrupções A Limpa WATCHDOG

BOTÃO UP PRESS.?

SIM

Trata Botão UP

NÃO

BOTÃO DOWN PRESS.?

SIM

Trata Botão Down

NÃO

BOTÃO Start/Stop PRESS.?

SIM

Trata Botão Start/Stop

NÃO

Recarrega Filtro e turbo das teclas

Linguagem C para PIC

45

INTERRUPÇÕES

NÃO

INT DE TMR0?

SIM

SWITCH CASE Recarrega Timer1 Incrementa ponteiro de seleção de Display, desliga display do milhar, consulta tabela de conversão para sete segmentos, liga display da unidade

Atualiza Display da Unidade? decrementa contador de int. NÃO

SIM

Passou 1 segundo ?

NÃO

Atualiza Display da Dezena?

SIM

Incrementa ponteiro de seleção de Display, desliga display da unidade, consulta tabela de conversão para sete segmentos, liga display da dezena

SIM

NÃO

Recarrega contador de int. Atualiza Display da Centena? SIM

Incrementa ponteiro de seleção de Display, desliga display da dezena, consulta tabela de conversão para sete segmentos, liga display da centena

Decrementa Timer

NÃO

Timer Chegou a zero?

NÃO

Atualiza Display do milhar?

SIM

Zera ponteiro de seleção de Display, desliga display da centena, consulta tabela de conversão para sete segmentos, liga display do milhar

NÃO SIM

Desliga led de indicação de timer operando FIM DA INTERRUPÇÃO

Desabilita interrupção de Timer1

FIM DA INTERRUPÇÃO

46 Linguagem C para PIC

Trata Botão UP

Trata Botão DOWN

Timer Ligado ?

SIM

Timer Ligado ?

SIM

NÃO

NÃO

Decrementa Filtro

Decrementa Filtro

NÃO Fim do Filtro ? Fim do Filtro ?

NÃO

SIM

SIM

Decrementa Turbo

Decrementa Turbo

Fim do Temporizador para Turbo do Botão?

NÃO

Fim do Temporizador para Turbo do Botão?

NÃO

SIM

SIM

Recarrega temporizador para Turbo

Recarrega temporizador para Turbo

Incrementa Timer

Decrementa Timer

A

A

Linguagem C para PIC

47

Trata botão Start/Stop

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

Habilita interrupção de Timer 1

A

48 Linguagem C para PIC

Incrementa Timer

Decrementa Timer

Incrementa unidade

Decrementa unidade

NÃO Unidade = 10 ? Unidade = 0XFF ?

NÃO

SIM

SIM

Zera unidade Incrementa dezena

Unidade = 9 Decrementa dezena

NÃO Dezena = 10 ? Dezena = 0XFF ?

NÃO

SIM

SIM

Zera dezena Incrementa centena

Dezena = 9 Decrementa centena

NÃO centena = 10 ? centena = 0XFF ?

NÃO

SIM

SIM

Zera centena Incrementa milhar

Centena = 9 Decrementa milhar

NÃO Milhar = 10 ? Milhar = 0XFF ?

NÃO

SIM Zera milhar

SIM Milhar = 9

Return

Return

Linguagem C para PIC

49

1.34 - Código
/* * * * * * * * * * * * /* * * // // // // // // // // /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * Exemplo 5 * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Este exemplo foi preparado para demonstrar o funcionamento do TIMER de 16 bits do PIC (TMR1), da varredura de displays e do tratamento manual de int. Consiste num temporizador de segundos. dois botões foram utilizados para programar o tempo da contagem. Um outro botão foi utilizado para disparar o contador. O temporizador consegue contar até 9999 segundos, de forma que os 4 displays de 7 segmentos foram necessários. A contagem é regressiva. um led indica que o temporizador está operando. Quando o sistema chega a 0000 (ZERO) o led é desligado automaticamente. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ <16f877A.h> // microcontrolador utilizado

#include

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #define t_filtro 250 // tamanho do filtro #define turbo_tecla 60 #define delta_timer1 (65536 - 62500) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int int int int int int int int display = 0 ; contador = 2; filtro = t_filtro; turbo = 1; unidade = 9; dezena = 9; centena = 9; milhar = 9; int int int INT W_TEMP; STATUS_TEMP; FSR_TEMP; PCLATH_TEMP; // atualiza os displays // contador de interrupções de timer1 // inicia filtro dos botões // inicia turbo das teclas // variável unidade do timer de 1 seg // variável dezena do timer de 1 seg // variável centena do timer de 1 seg // variável milhar do timer de 1 seg // variáveis para salvar contexto

static static static static

50 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #byte #byte #byte #byte porta=0x05 portb=0x06 portc=0x07 portd=0x08 porte=0x09 * * * * * * * * * * * * * * * * * * * * * * */ o bit 0 do sfr pir1 bit 2 do sfr intcon o bit 0 do fsr pie1 do reg de status do reg de fsr do reg de pclath

/* * * * * * * * * * * * * * * * * * * * * * * * * * * Definição de SFR's * * * * * * * * * * * * * * * * * * * * * * * * * * #bit tmr1if = 0x0c.0 // tmr1if é #bit t0if = 0x0b.2 // t0if é o #bit tmr1ie = 0x8c.0 // tmr1ie é #byte status = 0x03 // define endereço #byte fsr = 0x04 // define endereço #byte pclath = 0x0a // define endereço

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programação do hardware. // Estado do botão up // 1 -> Liberado // 0 -> Pressionado // Estado do botão down // 1 -> Liberado // 0 -> Pressionado * * */ e

bt_up = portb.1

#bit

bt_down

= portb.2

#bit

bt_start_stop = portb.3 // Estado do botão start_stop // 1 -> Liberado // 0 -> Pressionado * * */ E

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO //FUTURAS ALTERAÇÕES DO HARDWARE. #bit estado_timer = portb.0 // led de estado do timer // 1 -> timer contando // 0 -> timer parado // seleção do display unidade (0) // seleção do display dezena // seleção do display centena (2) // seleção do display milhar (3)

#bit #bit #bit #bit

disp0 disp1 disp2 disp3

= portb.4 = portb.5 = portb.6 = portb.7

(1)

Linguagem C para PIC

51

/* * * * * * * * * * * * * * * * * * * * * * * * Tabela de Valores * * * * * * * * * * * * * * * * * * * * * * * byte const converte[11] = { //PGFEDCBA 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111, 0b00000000}; /* * * * * * * * * * * * * * Função * * * * * * * * * * * * * 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 * * * * * * * * * * * * * 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; } }

* * * * * * * * * * * * * * * * * * * * * * * * * * */ POSIÇÃO RELATIVA AOS SEGMENTOS // 0H - 0 // 1H - 1 // 2H - 2 // 3H - 3 // 4H - 4 // 5H - 5 // 6H - 6 // 7H - 7 // 8H - 8 // 9H - 9 // blank

* * * * * * * * * * * * * * * * * * * * * * * de decremento do Timer * * * * * * * * * * * * * * * * * * * * * * * */

* * * * * * * * * * * * * * * * * * * * * * * de incremento do Timer * * * * * * * * * * * * * * * * * * * * * * * */

52 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de tratamento de interrupção de Timer1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 0,5 segundos, a rotina de tratamento é executada a // cada 2 interrupções (contador). #inline trata_tmr1() { set_timer1(delta_timer1); // carraga timer1 tmr1if = 0; // limpa flag de interrupção contador --; // decrementa contador de interrupções if (contador == 0) { set_timer1(delta_timer1); // carraga timer1 contador = 2; // carrega contador de int decrementa_timer(); if((unidade==0)&&(dezena==0)&&(centena==0)&&(milhar==0))// timer está zerado? { estado_timer = 0; // sim, apaga o led e tmr1ie = 0; // desliga tratamento de interrupção de timer1 } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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++; // disp0 = 0; // portd = (converte[dezena]); disp1 = 1; // break; // case 2: display++; // disp1 = 0; // portd = (converte[centena]); disp2 = 1; // break; // case 3: display disp2 = portd = disp3 = break; } } = 0; // 0; // (converte[milhar]); 1; // // incrementa a variável de varredura desliga o display 0 // atualiza o portd liga o display 1 sai incrementa a variável de varredura desliga o display 1 // atualiza o portd liga o display 2 sai inicia a variável de varredura desliga o display 2 // atualiza o portd liga o display 3 sai

Linguagem C para PIC

53

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para salvar contexto * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ salva_contexto() { #asm MOVWF W_TEMP // SALVA REGISTRADOR DE TRABALHO E SWAPF STATUS,W // DE STATUS DURANTE O TRATAMENTO MOVWF STATUS_TEMP // DA INTERRUPÇÃO. MOVF FSR,W MOVWF FSR_TEMP // SALVA REGISTRADOR FSR MOVF PCLATH,W MOVWF PCLATH_TEMP // SALVA REGISTRADOR PCLATH CLRF PCLATH // LIMPA REGISTRADOR PCLATH, SELECIONA PAGINA 0 CLRF STATUS // LIMPA REGISTRADOR STATUS #endasm } /* * * * * * * * * * * * * * * * * * * * * * * * * * Função para restaurar contexto * * * * * * * * * * * * * * * * * * * * * * * * * restaura_contexto() { #asm MOVF PCLATH_TEMP,W MOVWF PCLATH // RECUPERA REG. MOVF FSR_TEMP,W MOVWF FSR // RECUPERA REG. SWAPF STATUS_TEMP,W MOVWF STATUS // RECUPERA REG. SWAPF W_TEMP,F SWAPF W_TEMP,W // RECUPERA REG. #endasm } * * * * * * * * * * * * * * * * * * * * * * */

PCLATH (PAGINAÇÃO) FSR (END. INDIRETO) STATUS WORK

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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: while(TRUE) { RESTART_WDT(); // rotina principal // incia o watch-dog timer

54 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de incremento (UP) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_up) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de decremento (down) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_down) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de Start / Stop * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_start_stop) // testa botão start_stop { goto trata_start_stop; // desvia para a rotina para ligar ou // desligar o timer } filtro = t_filtro; turbo = 1; } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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; // testa botão down trata_dowm;// desvia para a rotina de decremento do timer // testa botão up trata_up;// desvia para a rotina de incremento do timer

Linguagem C para PIC

55

//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 if (t0if) { trata_tmr0(); } else // É int de tmr0 ? // sim, trata tmr0

// não, { if (tmr1if) // É int de tmr1 ? { trata_tmr1(); // sim, trata tmr1 } } // não. // restaura contexto e sai da int.

restaura_contexto(); }

56 Linguagem C para PIC

1.35 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 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.

Linguagem C para PIC

57

1.36 - Anotações

58 Linguagem C para PIC

Recursos Avançados: Exemplo 6 Controle do LCD
1.37 - Recursos do Livro
Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, controle do LCD (cap.12.7.2 pág. 310 do livro Programação em C).

1.38 - Lógica do exemplo
Este exemplo foi criado para demonstrar a inicialização de LCD de 2 linhas por 16 caracteres utilizando 8 vias de dados, e como enviar dados e comandos para o LCD. O exemplo controla o acionamento de leds e do ventilador através de um MENU, tecla S1, de escolha de opções, onde será possível escolher as opções de ligar ou desligar através da tecla ENTER, tecla S2. A escolha das telas será controlada pelo comando SWITCH do compilador C. Após o programa ser carregado a seguinte tela será visualizada no display: T a r e f a S e l e c i o n e P r e s s M e n u Quando a tecla S1 é pressionada a mensagem é trocada indicando as opções de controle, pressionando a tecla menu é possível escolher entre controle de leds e controle do ventilador. O controle selecionado é indicado por uma seta . c t r c t r d o s d o l e d s 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.

Linguagem C para PIC

59

1.39 - Esquema Elétrico
+5V

7 8 9 1 0 1 1 1 2 1 3 1 4

DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7

VDD 2 VO 3 VSS 1 RS 6 EN 5 R/W
4

10K

RS EN

LCD +5V

RESET

10K MC1
MCLR RA0 RA1 4 RA2 5 RA3 6 RA4 7 RA5 8 RE0 9 RE1 10 1 RE2 1 VDD 1 2 VSS 1 3 OSC1 1 4 OSC2 1 5 RC0 1 6 RC1 1 7 RC2 1 8 RC3 2 3 RC4 2 4 RC5
2 3 1 3 2 3 1 4 0 3 9 3 8 3 7 3 6 3 5 3 4 33 3 0 2 9 2 8 2 7 2 2 2 1 2 0 1 9 2 6 2 5

+5V
VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6

+5V

RS EN

4MHz

16F877 A RB2
+5V +5V 330R 330R

RB3

10K +Vcc

10K

RB0 S1

RB1 S2

L3

L4

1N4148

4,7K

60 Linguagem C para PIC

MINI VENTILADOR BC337

1.40 - Fluxograma
MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, W ATCHDOG, PRESCALER.

Configura Timer0

Inicializa LCD

Tela principal

Habilita as interrupções A Limpa W ATCHDOG

Escreve tela principal ?

SIM

Tela principal

NÃO

BOTÃO MENUPRESS.?

SIM

Trata Botão Menu

NÃO

BOTÃO ENTER PRESS.?

SIM

Trata Botão ENTER

NÃO

Recarrega Filtro dos Botões

Linguagem C para PIC

61

INT ERRUPÇÕ ES

Declara Variáveis locais

Incrementa contador de interrupções

Temp1 = 40

SIM

NÃO

Zera contador de interrupções SW IT CH CASE

Controle do Led2

SIM

Verifica se o led 1 está aceso Se sim: Pisca o Led 2 a cada 1 segundo. Se não: Apaga o led 2.

NÃO

Controle do T ime - out da tela principal

SIM

Incrementa contador de time out, após 5 segundos, limpa o flag "f_tela_principal", para liberar atualização da tela principal.

NÃO

FIM DA INT ERRUPÇÃO

62 Linguagem C para PIC

Trata Botão MENU

Ação já foi executada ?

SIM

NÃO

Decrementa Filtro

SIM

Fim do Filtro ?

NÃO

SIM Contador de Tela < 2

NÃO

Posiciona a seta na linha 0, coluna 0 do LCD

Posiciona a seta na linha 1, coluna 0 do LCD

A

Linguagem C para PIC

63

Trata Botão ENTER

Ação já foi executada ?

SIM

NÃO

Decrementa Filtro

SIM

Fim do Filtro ?

NÃO

Carrega a tela de seleção de tarefa: Controle dos Leds ou Controle do Ventilador

Re-inicia time-out

A

64 Linguagem C para PIC

Linguagem C para PIC

65

Seleção da Tela de Menu Switch Case

SIM Tela 1 do Menu ?

NÃO

Posiciona a seta na linha 0 coluna 0

SIM Tela 2 do Menu

NÃO

Posiciona a seta na linha 1 coluna 0

Return

Beep

Fim do loop do Beep ? (conta beep)

SIM

NÃO

Return

Liga Beep Delay

Desliga Beep Delay

Decrementa conta beep

66 Linguagem C para PIC

Seleção da Tela de Enter Switch Case

SIM Tela 1 do Enter ? Carrega a tela de controle de leds. Carrega contador para tela 3

NÃO

SIM Tela 2 do Enter Carrega a tela de controle do Ventilador Carrega contador para tela 4

NÃO

SIM Tela 3 do Enter Indica estado dos leds On ou Off emite beep.

NÃO

SIM Tela 4 do Enter

NÃO

Indica estado do ventilador On ou Off emite beep

Return

A

Linguagem C para PIC

67

1.41 - Código
/* * * * * * * * * * * * /* * * // // // // // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * Exemplo 6 * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Este exemplo foi elaborado para explicar o funcionamento do módulo de LCD. Foi criada uma rotina para escrever comandos e uma para escrever caracteres, existe também uma rotina de inicialização necessária para a correta configuração do LCD. Os botões S1 e S2 são respectivamente botão Menu e Enter, o botão Menu seleciona a tarefa que desejamos executar (controle de Leds ou do Ventilador), o botão Enter seleciona a tarefa e funciona como controle de liga/desliga para a tarefa selecionada. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ arquivo de definições do pic utilizado deve ser referenciado para que nomes definidos pela Microchip possam ser utilizados, sem a necessidade redigitação. <16f877A.h> // microcontrolador utilizado

/* * * * * // O //os //de

#include

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #define t_filtro 500 // tamanho do filtro

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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)

68 Linguagem C para PIC

#use #use #use #use #byte #byte #byte #byte #byte

fast_io(b) fast_io(c) fast_io(d) fast_io(e) porta portb portc portd porte = = = = = 0x05 0x06 0x07 0x08 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. #bit f_tela_principal = /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit menu flags1.0

* * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programação e do hardware. // Estado do botão menu // 1 -> Liberado // 0 -> Pressionado // Estado do botão enter // 1 -> Liberado // 0 -> Pressionado

= portb.0

#bit

enter = portb.1

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #bit #bit #bit #bit #bit #bit rs = porte.0 enable = porte.1 led1 = portb.2 // led led2 = portb.3 // led ventilador = portc.1 buzzer = porta.5 // // s3 s4 // // via do lcd que sinaliza recepção de dados ou comando enable do lcd controle do ventilador controle do buzzer *

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; portd = caracter; enable = 1 ; delay_us(1); enable = 0; delay_us(40); }

// // // // //

// seleciona o envio de um comando carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable espera mínimo 40 microsegundos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; portd = caracter; enable = 1; delay_us(1); enable = 0; delay_us(40); }

*

// // // // //

// seleciona o envio de um comando carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable espera mínimo 40 microsegundos

Linguagem C para PIC

69

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); delay_ms (2); }

*

// limpa lcd

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); delay_ms(4); comando_lcd(0x30); delay_us(100); comando_lcd(0x30); comando_lcd(0x38); limpa_lcd(); comando_lcd(0x0c); comando_lcd(0x06); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de Bip´s * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void bip(long int tempo, long int periodo) { long int conta_bip; conta_bip = tempo / periodo; while (conta_bip) { buzzer = 1; delay_ms(periodo/2); buzzer = 0; delay_ms(periodo/2); conta_bip--; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 } // define variável local // contabiliza quantas vezes terá // que fazer o loop de bip´s // faça o loop até acabar o conta_bip

*

// envia comando para inicializar display // espera 4 milisengundos // envia comando para inicializar display // espera 100 microsengundos // envia comando para inicializar display // configura LCD, 8 bits, matriz de 7x5, 2 linhas // limpa lcd // display sem cursor // desloca cursor para a direita

// liga o buzzer // conta tempo para o período escolhido // desliga o buzzer // conta tempo para o período excolhido // decrementa o conta_bip

*

70 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Menu * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 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 comando_lcd(0xc2); // posiciona o cursor na linha 1, coluna 2 printf (escreve_lcd, "ctr do vent"); // 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 comando_lcd(0xc4); printf (escreve_lcd, "ON // posiciona o cursor na linha 1, coluna 4 OFF"); // imprime mensagem no lcd *

if (!led1) { comando_lcd(0xc7); escreve_lcd(0x3e); comando_lcd(0xc3); escreve_lcd(' '); } else { comando_lcd(0xc3); escreve_lcd(0x3e); comando_lcd(0xc7); escreve_lcd(' '); } }

// // // //

posiciona o cursor na linha 1, coluna 7 envia simbolo "maior" para o lcd posiciona o cursor na linha 1, coluna 3 envia simbolo "espaço" para o lcd

// // // //

posiciona o cursor na linha 1, coluna 3 envia simbolo "maior" para o lcd posiciona o cursor na linha 1, coluna 7 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 comando_lcd(0xc4); printf (escreve_lcd, "ON // posiciona o cursor na linha 1, coluna 4 OFF"); // imprime mensagem no lcd

if (!ventilador) { comando_lcd(0xc7); escreve_lcd(0x3e); comando_lcd(0xc3); escreve_lcd(' '); } else { comando_lcd(0xc3); escreve_lcd(0x3e); comando_lcd(0xc7); escreve_lcd(' '); } }

// // // //

posiciona o cursor na linha 1, coluna 7 envia simbolo "maior" para o lcd posiciona o cursor na linha 1, coluna 3 envia simbolo "espaço" para o lcd

// // // //

posiciona o cursor na linha 1, coluna 3 envia simbolo "maior" para o lcd posiciona o cursor na linha 1, coluna 7 envia simbolo " " para o lcd

Linguagem C para PIC

71

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleção das telas de Menu * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 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; case 2: tela_ctr_ventilador(); contador_tela = 4; break; *

// retorna da função

// retorna da função

case 3: if (!led1) { led1 = 1; // acende o led bip(50,2); comando_lcd(0xc3);// posiciona o cursor na escreve_lcd(0x3e);// envia simbolo "maior" comando_lcd(0xc7);// posiciona o cursor na escreve_lcd(' ');// envia simbolo "espaço" } else { led1 = 0; // apaga o led comando_lcd(0xc7);// posiciona o cursor na escreve_lcd(0x3e);// envia simbolo "maior" comando_lcd(0xc3);// posiciona o cursor na escreve_lcd(' ');// envia simbolo "espaço" bip(50,2); delay_ms(250); bip(50,2); } break; // retorna da função

linha 1, coluna 3 para o lcd linha 1, coluna 7 para o lcd

linha 1, coluna 7 para o lcd linha 1, coluna 3 para o lcd

72 Linguagem C para PIC

case 4: if (!ventilador) { bip(750,2); ventilador = 1; comando_lcd(0xc3); escreve_lcd(0x3e); comando_lcd(0xc7); escreve_lcd(' '); } else { bip(1000,2); ventilador = 0; comando_lcd(0xc7); escreve_lcd(0x3e); comando_lcd(0xc3); escreve_lcd(' '); } break; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); setup_counters (rtcc_internal, WDT_2304MS); set_tris_a(0b11011111); set_tris_b(0b11110011); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; inicializa_lcd(); tela_principal(); // // // // // // configuração da direção dos pinos de I/O // desliga o ventilador posiciona o cursor na linha 1, coluna 7 envia simbolo "maior" para o lcd posiciona o cursor na linha 1, coluna 3 envia simbolo "espaço" para o lcd // retorna da função

// // // //

// liga o ventilador posiciona o cursor na linha 1, coluna 3 envia simbolo "maior" para o lcd posiciona o cursor na linha 1, coluna 7 envia simbolo "espaço" para o lcd

// // // //

limpa limpa limpa limpa limpa

porta portb portc portd porte

// configura o lcd // imprime a tela principal no LCD

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(); }

Linguagem C para PIC

73

//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * if (!menu) { goto } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * if (!enter) { goto } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filtro = t_filtro; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 time_out = 0; // re-inicia contagem do tempo de } } goto loop; } * * * * * * * * * * * * * * */ // recarga da variável filtro // testa botão 2 trata_enter;// desvia para a rotina de incremento do timer // testa botão 1 trata_menu;// desvia para a rotina de incremento do timer

de tarefa time-out

74 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 256us. // A variável auxiliar temp1 será utilizada para contar 40 interrupções, // totalizando 10ms. O comando switch será executado a cada 10ms. #int_rtcc void trata_int_tmr0() { temp1 ++; if (temp1 == 40) { temp1 = 0; switch(contador) { case 0: temp2 ++; if (temp2 == 50) { temp2 = 0; // já passou 10ms? // sim, zera contador de interrupção // seleciona tarefa // controle do led2 // passou 1 segundo? // sim, zera contador de interrupção

if (led1) // O led1 está ligado { if (!led2) // sim, o led2 está ligado? { led2 = 1; // não, liga o led2 } else { led2 = 0; // sim, desliga o led2 } } // não, então não controla o led2 else { led2 = 0;// não, mantém o led2 desligado } } contador ++; // incrementa contador de tarefa break; // fim de execução de execução da tarefa case 1: // time_out = 10ms * 250 * 2 time_out ++; if (time_out == 250) // já passou 5 segundos? { time_out = 0; // sim, zera time_out contador_tela = 0; // zera contador de tela f_tela_principal = 0; // libera atual.tela principal } contador ++; // incrementa contador de tarefa break; // fim de execução de execução da tarefa default: contador = 0; } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // não, sai da int.

Linguagem C para PIC

75

1.42 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 1. Mude a rotina para que seja controlado o buzzer no lugar do led 2. 2. Crie mais um nível no Menu para controlar o buzzer.

76 Linguagem C para PIC

1.43 - Anotações

Linguagem C para PIC

77

Recursos Avançados: Exemplo 7
1.44 - Recursos do Livro

Conversor Analógico Digital

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, funções do compilador para controle do conversor analógico digital (cap.11-pág 206 do livro Programação em C).

1.45 - Lógica do exemplo
Este exemplo foi elaborado para explicar as funções do CCS para o módulo de conversão analógico digital interno do PIC. É convertido o valor analógico presente no pino RA1 do microcontrolador, sendo que este valor pode ser alterado através do potenciômetro P2 da placa MCLAB2 este valor é ajustado entre 0 e 5V e mostrado no LCD. Neste exemplo foi utilizado variável do tipo float para armazenar o resultado da conversão A/D. Para que possamos visualizar o valor de 0 à 5V no LCD, foi feita uma segunda conversão o valor digital foi convertido para “Volts” realizando uma regra de 3.
Valor máximo da resolução do AD (10 bits) Valor a ser mostrado no display

(5V * ADRES) / 1023 = "n" Volts

Tensão de Referência

Valor de tensão medido

78 Linguagem C para PIC

1.46 - Esquema Elétrico

+5V

P2 10K

+ LM358

4,7K

330R RA1 +5V 1uF

7 8 9 10 11 12 13 14

DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7

VDD 2 VO 3 VSS 1 RS 6 EN 5 R/W
4

10K

RS EN

LCD +5V

RESET

10K MC1
1 2 3 4 5 6 7

+5V
VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

RS EN

8 9 10 11 12 13 14 15

4MHz

16 17 18 23 24

MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5

16F877A

Linguagem C para PIC

79

1.47 - Fluxograma

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

Prepara Tela principal

A

80 Linguagem C para PIC

A

LIMPA WATCHDOG

Inicia e lê o resultado da conversão

Multiplica valor da conversão por 5

Divide resultado da multiplicação por 1023

Envia resultado para o display

Linguagem C para PIC

81

1.48 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * Exemplo 7 * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. /* * * * * // O //os //de * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ arquivo de definições do pic utilizado deve ser referenciado para que nomes definidos pela Microchip possam ser utilizados, sem a necessidade redigitação.

#include <16f877A.h> // microcontrolador utilizado #device adc=10 // configura AD para retornar valor em 10 bits /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 *

82 Linguagem C para PIC

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte #byte #byte #byte #byte porta portb portc portd porte = = = = = 0x05 0x06 0x07 0x08 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programação e 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 #bit enable = porte.1 // via do lcd que sinaliza recepção de dados ou comando // enable do lcd *

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; portd = caracter; enable = 1 ; delay_us(1); enable = 0; delay_us(40); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; portd = caracter; enable = 1; delay_us(1); enable = 0; delay_us(40); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); delay_ms (2); }

// // // //

// seleciona o envio de um comando carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable

// espera mínimo 40 microsegundos

*

// // // //

// seleciona o envio de um comando carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable

// espera mínimo 40 microsegundos

// limpa lcd

Linguagem C para PIC

83

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * void tela_principal() { comando_lcd(0x83); // printf (escreve_lcd, "Voltimetro"); comando_lcd(0xcd); // printf (escreve_lcd, " V"); } * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * */ posiciona o cursor na linha 0, coluna 3 // imprime mensagem no lcd posiciona o cursor na linha 1, coluna 14 // 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 set_tris_a(0b11111111); set_tris_b(0b11111111); set_tris_c(0b11111111); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; inicializa_lcd(); tela_principal(); // // // // // // configuração da direção dos pinos de I/O

limpa limpa limpa limpa limpa

porta portb portc portd porte

// configura o lcd // imprime a tela principal no LCD

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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.

84 Linguagem C para PIC

} } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Linguagem C para PIC

85

1.49 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 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.

86 Linguagem C para PIC

1.50 - Anotações

Linguagem C para PIC

87

Recursos Avançados: Exemplo 8 Interna
1.51 - Recursos do Livro

Controle do PWM e EEPROM

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, funções do compilador para controle do PWM (cap.11.9 pág.218 do livro Programação em C), funções do compilador para operação com EEPROM (cap.11.10 pág.219 do livro Programação em C), diretiva #ROM (cap.10, pág.167 do livro Programação em C) e função de manipulação de registradores make8 e make16 (cap.11, pág.200 e 201 do livro Programação em C).

1.52 - Lógica do exemplo
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 salvo 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(usado como contador) e mostrada no LCD. Através do botão S1, o PWM é incrementado e decrementado pelo botão S2. Realizando a operação nestes botões será visualizado no LCD o incremento e o decremento em porcentagem(%) e a rotação do ventilador em rps (rotações por segundo). O botão S4 salva o valor de ajuste em EEPROM e o botão S3 restaura o valor salvo atualizando o PWM. Para que possamos utilizar o PWM do PIC não podemos esquecer de configurar a freqüência do PWM no Timer2. T = [(PR2 + 1) * 4] * Tosc * Prescaler TMR2 A função set_pwm_duty(valor), determina o período do pulso do PWM, ou seja, o tempo em que a saída do PWM permanecerá em nível lógico 1. Este valor pode chegar a 1023, enquanto o período do PWM pode chegar a 1024, com PR2 igual a 255. Por está razão dependendo da freqüência do PWM não será possível alcançar os 100% de Duty Cyle. DC = (valor / T), 1023 / 1024 = 0,9990 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.

88 Linguagem C para PIC

1.53 - Esquema Elétrico
+5V

7 8 9 10 11 12 13 14

DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7

VDD 2 VO 3 VSS 1 RS 6 EN 5 R/W
4

10K

RS EN

LCD +5V

RESET

10K MC1
1 2 3 4 5 6 7

+5V
VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

RS EN

8 9 10 11 12 13 14 15 16 17 18

4MHz TACOMETRO

23 24

MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5

16F877A

+5V

+5V

+5V

+5V

10K

10K

10K

10K

RB0 S1
+Vcc

RB1 S2

RB2 S3

RB3 S4

1N4148

MINI VENTILADOR

+5V

+5V

4,7K

BC337 150R SIR381583F RPT38PT3F 10K 1K TACOMETRO

1K

BC337

Linguagem C para PIC

89

1.54 - Fluxograma
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

T ela princ ipal

H abilita as interrupç ões A 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 P R ES S .?

S IM

T rata B otão D O W N

N ÃO

N ÃO G rava D ados em E E PR O M ?

SIM

S alva dados em EE PR O M

N ÃO

R estaura D ados da E E PR O M ?

SIM

Lê E EP R O M

N ÃO

A tualiza P wm

90 Linguagem C para PIC

Trata Botão UP

Trata Botão DOWN

Ação já foi executada ?

SIM

Ação já foi executada ?

SIM

NÃO

NÃO

Decrementa Filtro

Decrementa Filtro

Fim do Filtro ?

NÃO

Fim do Filtro ?

NÃO

SIM Decrementa Turbo

SIM Decrementa Turbo

Fim do Turbo ?

Fim do Turbo ?

Re-carrega variavel do Turbo

Re-carrega variavel do Turbo

Incrementa PWM do ventilador Atualiza a tela principal

Decrementa PWM do ventilador Atualiza a tela principal

A

A

Linguagem C para PIC

91

INTERRUPÇÕES

Contador de interrupções é igual a zero ? (Temp1 = 0)

SIM

NÃO

Decrementa contador de interrupções

Carrega variável rotação com o valor do Timer1

Divide variável rotação por 7 (número de palhetas do ventilador) habilita atualização do LCD

FIM DA INTERRUPÇÃO

92 Linguagem C para PIC

1.55 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * Exemplo 8 * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #include <16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #define t_filtro 200 #define turbo_tecla 5 // tamanho do filtro // turbo dos botões

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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

Linguagem C para PIC

93

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use #byte #byte #byte #byte #byte fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e) porta=0x05 portb=0x06 portc=0x07 portd=0x08 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 /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações #bit * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programação e do hardware. // Estado do botão 2 // 1 -> Liberado // 0 -> Pressionado // Estado do botão 3 // 1 -> Liberado // 0 -> Pressionado // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado

botao1 = portb.0

#bit

botao2 = portb.1

#bit

botao3 = portb.2

#bit

botao4 = portb.3

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #bit enable = porte.1 #bit ventilador = portc.1 // via do lcd que sinaliza recepção de dados ou comando // enable do lcd // pino de I/O para controle do ventilador (PWM) *

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; portd = caracter; enable = 1 ; delay_us(1); enable = 0; delay_us(40); }

// // // //

// seleciona o envio de um comando carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable

// espera mínimo 40 microsegundos

94 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; portd = caracter; enable = 1; delay_us(1); enable = 0; delay_us(40); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); delay_ms (2); }

// // // //

// seleciona o envio de um caracter carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable

// espera mínimo 40 microsegundos

// limpa lcd

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); delay_ms(4); comando_lcd(0x30); delay_us(100); comando_lcd(0x30); comando_lcd(0x38); limpa_lcd(); comando_lcd(0x0c); comando_lcd(0x06); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 printf (escreve_lcd,"%" "3Lu%%", duty_cycle1); // envia dados para o display de LCD comando_lcd(0xcb); // posiciona o cursor na linha 1, coluna 11 printf (escreve_lcd,"%" "3Lu", rotacao); // envia dados para o display de LCD }

// envia comando para inicializar display // espera 4 milisengundos // envia comando para inicializar display // espera 100 microsengundos // envia comando para inicializar display // liga o display, sem cursor e sem blink // limpa lcd // display sem cursor // desloca cursor para a direita

Linguagem C para PIC

95

/* * * // //

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Salva Dados na EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ salva dado na eeprom no endereço indicado através da variável "end", o dado a ser salvo é passado para a Função através da variável "dado".

*

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() { setup_adc_ports (no_analogs); // desliga as entradas analógicas setup_counters (rtcc_internal, rtcc_div_64);// tmr0 clock interno, ps: 1:64 setup_timer_1 (t1_external_sync | t1_div_by_1);// tmr1 clock externo, ps: 1:1 setup_timer_2 (t2_div_by_16,255,1);// tmr2 ps=1:16, pr2=255 e postscale: 1:1 setup_ccp2(ccp_pwm); // modo PWM ligado set_pwm2_duty(periodo_pulso); // ajusta duty cycle em 0. set_tris_a(0b11111111); set_tris_b(0b11111111); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; inicializa_lcd(); tela_principal(); enable_interrupts(INT_RTCC); enable_interrupts(GLOBAL); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * loop: while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog if (atualiza_lcd != 0) * * */ // configuração da direção dos pinos de I/O

// // // // //

limpa limpa limpa limpa limpa

porta portb portc portd porte

// configura o lcd // imprime a tela principal no LCD

timer

96 Linguagem C para PIC

{ duty_cycle = periodo_pulso; // carrega valor da rotação medida duty_cycle = (duty_cycle / 1024); // efetua cálculo do duty cycle duty_cycle = (duty_cycle * 100); // converte para porcentagem (%) duty_cycle1 = (long int) duty_cycle; // carrega os 16 bits menos significativos da parte inteira // do resultado da converão tela_principal(); atualiza_lcd = 0; } // imprime a tela principal no LCD // indica LCD atualizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de incremento (UP) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de decremento (down) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao2) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão ler dados da EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao3) { le_dados(1); periodo_pulso = dado; // testa botão 3 // lê byte_low da eeprom // carrega valor lido em variável de 16 bits // testa botão 2 trata_dowm; // desvia para a rotina de decremento do PWM // testa botão 1 trata_up; // desvia para a rotina de incremento do PWM

le_dados(0); // lê byte_high da eeprom periodo_pulso = make16(dado, periodo_pulso); // recompõe o dado de 16 bits atualiza_pwm(); atualiza_lcd = 1; } // Função para atualizar o PWM // habilita atualização do LCD

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão salvar dados na EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao4) // testa botão 4 { end = 0; // endereço do byte_high dado = make8(periodo_pulso,1); // retorna byte_high salva_dados(); // salva byte_high end = 1; // endereço do byte_low dado = make8(periodo_pulso,0); // retorna byte_low salva_dados(); // salva byte_low } filtro = t_filtro; turbo = 1; } // carrega filtro dos botões // fecha while

//* * * * * * * * * * * Incrementa duty cycle do PWM * * * * * * * * * * trata_up: { filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? {

Linguagem C para PIC

97

goto

turbo --; // decrementa o turbo da tecla filtro = t_filtro; if (turbo == 0) // sim, fim do turbo do botão ? { turbo = turbo_tecla; if (periodo_pulso < 1023) // limita incremento do periodo do pulso em 1023 { periodo_pulso ++; atualiza_pwm(); // Função para atualizar o PWM atualiza_lcd = 1; // habilita atualização do LCD } } } } loop;

//* * * * * * * * * * * Decrementa duty cycle do PWM * * * * * * * * * * trata_dowm: { filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? { turbo --; // decrementa o turbo da tecla filtro = t_filtro; if (turbo == 0) // sim, fim do turbo do botão ? { turbo = turbo_tecla; if (periodo_pulso != 0) // limita decremento do periodo do pulso em 0 { periodo_pulso --; atualiza_pwm(); // Função para atualizar o PWM atualiza_lcd = 1; // habilita atualização do LCD } } } } goto loop; } /* * * // // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 ) { rotacao = get_timer1(); set_timer1 (0); rotacao = (rotacao / 7); atualiza_lcd = 1; temp1 = 125; } else { temp1 --; }

// ja passou 1 segundo? // Sim, // le valor do timer 1 // zera timer 1 // divide por 7 (quantidade de palhetas do ventilador) // habilita atualização do LCD // re-inicia temp1 // Não, // decrementa temp1

} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

98 Linguagem C para PIC

1.56 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 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.

Linguagem C para PIC

99

1.57 - Anotações

100 Linguagem C para PIC

Recursos Avançados: Exemplo 9
1.58 - Recursos do Livro

Coletor de Dados

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, funções do compilador para controle de comunicação serial I2C (cap.11.14 pág 240 do livro Programação em C), funções do compilador para controle de comunicação serial RS232 (cap.11.13 pág 230 do livro Programação em C), diretiva de configuração #use i2c e #use RS232 (cap.10, pág.171 e 172 do livro Programação em C).

1.59 - Lógica do exemplo
Este exemplo foi elaborado para explicar as funções de I2C do compilador CCS e comunicação serial com a USART. Neste exemplo iremos coletar dados do A/D 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. Quando for recebido o dado 0x55 o PIC inicia a coleta de dados, ao final da coleta e enviado para o PC o comando 0x0b, para a liberação da transmissão de dados. Após o fim da coleta de dados o PIC aguarda o comando 0xaa, recebendo este dado, ele inicia a transmissão de dados para o PC plotar os dados na tela. Ao final da transmissão ele aguarda novo comando de inicio de coleta de dados.

Linguagem C para PIC

101

1.60 - Esquema Elétrico

+5V

P2 10K

+

4,7K

330R RA1

1uF

+5V

+5V

7 8 9 10 11 12 13 14

RESET 10K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7

VDD 2 VO 3 VSS 1 RS 6 EN 5 R/W
4

10K

RS EN

MC1
MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5 VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

LCD

+5V

+5V

RS EN

1 2 3 4

A0 A1 A2 GND

VCC WP SCL SDA

8 7 6 5

10K

10K

4MHz

17 18 23 24

24C04

16F877A

+5V

1uF
1 3

1uF

1uF

C1+ C1 C2+ C2 +C 2 -C 6
12

4 5 13 14 8 7 15

T1IN T1OUT R1OUT R1IN 11 T2IN T2OUT R2OUT R2IN 10 GND VCC
16 9

1K +5V

3

2

5

1uF

MAX-232

CONECTOR DB9 FEMEA

102 Linguagem C para PIC

1.61 - Fluxograma
MAIN

CONFIGURAÇÕES INICIAIS TRIS, PORTAS, W ATCHDOG, PRESCALER.

Configuração: AD, rs232 e I2C

Inicializa LCD

Tela principal

Habilita as interrupções A Limpa W ATCHDOG

Verifica se chegou comando pela USART B

SIM Inicia coleta de dados ? Coleta Dados

NÃO

Deve transmitir dados para o PC ?

SIM TX Dados para o PC

NÃO

SIM Para a coleta de Dados ?

Cancela coleta de dados Transmite para o PC comando de fim de coleta de dados

NÃO

A

Linguagem C para PIC

103

Recebe comando do PC

Chegou comando do PC ?

NÃO

SIM

SIM

Recebeu o comando de inicio de Coleta de Dados ?

Tarefa = coleta de dados

NÃO

B SIM Recebeu o comando de transmissão de dados para o PC ?

Tarefa = transmite dados para o PC

NÃO

B SIM Recebeu o comando de parar coleta de dados ?

Tarefa = para coleta de dados

NÃO

B

104 Linguagem C para PIC

Coleta Dados

Escreve no LCD: "Coletando Dados"

Lê Dados do AD Salva em EEPROM Serial

NÃO

Fim da Coleta de Dados ?

SIM

Aguarda novo comando do PC

Envia para o PC comando de Fim de Coleta de Dados

Escreve no LCD: "Pronto para TX"

Return

Linguagem C para PIC

105

Transmite dados para o PC

Escreve no LCD: "TX para o PC"

Lê memória EEPROM Serial Transmite para o PC

NÃO

Fim da transmissão de Dados ?

SIM Escreve no LCD: "Fim da Trans..."

Aguarda novo comando do PC delay de 5 segundos

Escreve no LCD: "Press Inicio" delay de 1 segundo

Return

106 Linguagem C para PIC

Linguagem C para PIC

107

Escreve na memória EEPROM Serial

Lê dados da memória EEPROM Serial

Envia Start bit

Envia Start bit

Envia Controle

Envia Controle

Envia endereço low

Envia endereço low

Envia Dado

Envia Start bit

Envia Stop bit

Envia Controle

delay 10ms

Recebe dados da memória salva em variável dado

Return

Envia Stop bit

delay 10ms

Return

108 Linguagem C para PIC

1.62 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 9 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #include <16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis // configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração do Módulo I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use i2c(master,sda=pin_c4, scl=pin_c3, SLOW, RESTART_WDT, FORCE_HW) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração da USART * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use rs232 (baud=9600, xmit = pin_c6, rcv = pin_c7) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define #define ctrl_le ctrl_escr 0b10100001// byte de controle da memória p/ leitura 0b10100000// byte de controle da memória p/ escrita

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constante internas do tipo Enumeração * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum selecao_de_tarefa { aguarda_comando, coleta_de_dados, transmite_para_pc, parar_coleta }tarefa;

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

Linguagem C para PIC

109

* Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. static int flags1 = 0; // flags static int dado = 0; static int end_low = 0; static int tx_pc; static int comando = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #byte #byte #byte #byte porta=0x05 portb=0x06 portc=0x07 portd=0x08 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 /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programação e 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 * * * * * * * * * * * * escr_mem_serial () { i2c_start(); i2c_write(ctrl_escr); i2c_write(end_low); i2c_write(dado); i2c_stop(); delay_ms(10); } /* * * * * * * * * * * * * Função * * * * * * * * * * * * le_mem_serial () { i2c_start(); i2c_write(ctrl_escr); i2c_write(end_low); i2c_start(); i2c_write(ctrl_le); dado = i2c_read(0); i2c_stop(); } * * * * * * * * * * * * * * * * * * * * * * * * * * para escrita na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Condição de início // Envia o byte de controle de leitura // Envia endereço baixo // Escreve dado na E²PROM // Condição de parada // espera a gravação estar completa * * * * * * * * * * * * * * * * * * * * * * * * * * para leitura na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Condição de início // Envia o byte de controle de leitura // Envia endereço baixo // Nova condição de início // Envia o byte de controle de leitura // lê o dado armazenado na E²PROM // Condição de parada

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

110 Linguagem C para PIC

* Função que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; portd = caracter; enable = 1 ; delay_us(1); enable = 0; delay_us(40); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; portd = caracter; enable = 1; delay_us(1); enable = 0; delay_us(40); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); delay_ms (2); }

*

// // // //

// seleciona o envio de um comando carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable

// espera mínimo 40 microsegundos

*

// // // //

// seleciona o envio de um caracter carrega o portd com o caracter gera pulso no enable espera 1 microsegundo desce o pino de enable

// espera mínimo 40 microsegundos

// limpa lcd

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); delay_ms(4); comando_lcd(0x30); delay_us(100); comando_lcd(0x30); comando_lcd(0x38); limpa_lcd(); comando_lcd(0x0c); comando_lcd(0x06); }

// envia comando para inicializar display // espera 4 milisengundos // envia comando para inicializar display // espera 100 microsengundos // envia comando para inicializar display // liga o display, sem cursor e sem blink // limpa lcd // display sem cursor // 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 *

Linguagem C para PIC

111

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ coleta_dados() { comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, "Coletando Dados"); // imprime mensagem no lcd do { dado = read_adc(); // le resuldado do AD escr_mem_serial (); // salva em eeprom end_low += 1; // incrementa endereço, seleciona nova posição delay_ms(10); // delay de 10 ms }while (end_low != 0); // fim da coleta ? tarefa = aguarda_comando; // aguarda comando do PC comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " Pronto para TX "); // imprime mensagem no lcd tx_pc = 11; // indica para o pc fim da coleta de dados printf ("%x\r\n",tx_pc);// envia ao PC o comando de fim da coleta de dados delay_ms(2000); // delay de 2 segundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 tarefa = aguarda_comando; // aguarda comando do PC comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " Fim da Trans..."); // imprime mensagem no lcd delay_ms(3000); // delay de 3 segundos comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " "); // imprime mensagem no lcd delay_ms(1000); // delay de 1 segundo } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 *

112 Linguagem C para PIC

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (RA0_RA1_RA3_analog); setup_adc (adc_clock_div_8); set_adc_channel (1); setup_counters (rtcc_internal, WDT_2304MS); set_tris_a(0b11111111); set_tris_b(0b11111111); set_tris_c(0b10110111); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; inicializa_lcd(); tela_principal(); // configuração da direção dos pinos de I/O

// // // // //

limpa limpa limpa limpa limpa

porta portb portc portd porte

// configura o lcd // imprime a tela principal no LCD

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Linguagem C para PIC

113

1.63 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 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.

114 Linguagem C para PIC

1.64 - Anotações

Linguagem C para PIC

115

Recursos Avançados: Exemplo 10 Funções Matemáticas
1.65 - Recursos do Livro
Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, funções matemáticas do compilador (cap.11.1 pág 175 do livro Programação em C).

1.66 - Lógica do exemplo
A elaboração deste exemplo foi pensando na demonstração das funções matemáticas, nele veremos o microcontrolador realizando o calculo do seno de 0 a 2π, um software para PC foi elaborado para coletar os cálculos realizas e plotar os cálculos na tela do PC. Outras funções podem ser visualizadas, bastando para isso alterar a função matemática de nosso programa.

116 Linguagem C para PIC

1.67 - Esquema Elétrico

+5V

RESET

10K MC1
1 2 3 4 5 6 7

+5V
VDD VSS RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 RC7 RC6
32 31 40 39 38 37 36 35 34 33 30 29 28 27 22 21 20 19 26 25

+5V

RS EN

8 9 10 11 12 13 14 15

4MHz

16 17 18 23 24

MCLR RA0 RA1 RA2 RA3 RA4 RA5 RE0 RE1 RE2 VDD VSS OSC1 OSC2 RC0 RC1 RC2 RC3 RC4 RC5

16F877A

+5V

1uF
1 3

1uF

1uF

C1+ C1 C2+ C2 +C 2 -C 6
12

4 5 13 14 8 7 15

T1IN T1OUT R1OUT R1IN 11 T2IN T2OUT R2OUT R2IN 10 GND VCC 16
9

1K +5V

3

2

5

1uF

MAX-232

CONECTOR DB9 FEMEA

Linguagem C para PIC

117

1.68 - Fluxograma
MAIN

CO NFIG URAÇÕ ES INICIAIS TRIS, PO RTAS, W ATCHDO G , PRESCALER.

Inicializa a variável X=0

NÃO X < (2 * PI)

SIM

LIMPA W ATCHDO G

Y = seno (x)

Envia o valor de X para o PC

Envia o valor de Y para o PC

Incrementa a variável X X = x + 0,01

118 Linguagem C para PIC

1.69 - Código
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 10 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * dos I/O's e opções de configuração para periféricos * * * * * * * * * * * * * * * * * * * * * */ *

/* * * * * * * * * * * * * * * * * Definição * das funções * * * * * * * * * * * * * * * * #include <16f877A.h> #device adc=10

// microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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

Linguagem C para PIC

119

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use #byte #byte #byte #byte #byte fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e) porta=0x05 portb=0x06 portc=0x07 portd=0x08 porte=0x09 * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programação do hardware. * * */ e

/* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alterações

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO //FUTURAS ALTERAÇÕES DO HARDWARE.

* * */ E

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 set_tris_a(0b11111111); set_tris_b(0b11111111); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; // configuração da direção dos pinos de I/O

// // // // //

limpa limpa limpa limpa limpa

porta portb portc portd porte

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

120 Linguagem C para PIC

1.70 1.71 - Exercícios Propostos
Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e soluções, seguindo os exercícios propostos: 1. Altere a função matemática para que o PIC calcule o co-seno. 2. Altere a função matemática para que o PIC calcule o log de um número.

Linguagem C para PIC

121

1.72 - Anotações

122 Linguagem C para PIC

You're Reading a Free Preview

Descarregar
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->