Você está na página 1de 122

Linguagem C

Roteiros de Experiencias

PIC 16F877A
COMPILADOR CCSC

Sumrio
SUMRIO .....................................................................................................................................................................3 RECURSOS BSICOS: EXEMPLO 1 BOTO E LED ............................................................................................5 RECURSOS DO LIVRO ..................................................................................................................................................5 LGICA DO EXEMPLO ...................................................................................................................................................5 ESQUEMA ELTRICO....................................................................................................................................................6 FLUXOGRAMA ..............................................................................................................................................................7 CDIGO ......................................................................................................................................................................8 EXERCCIOS PROPOSTOS ..........................................................................................................................................10 ANOTAES ..............................................................................................................................................................11 RECURSOS BSICOS: EXEMPLO 2 PISCA PISCA VARIVEL .....................................................................13 RECURSOS DO LIVRO ................................................................................................................................................13 LGICA DO EXEMPLO .................................................................................................................................................13 ESQUEMA ELTRICO..................................................................................................................................................14 FLUXOGRAMA ............................................................................................................................................................15 CDIGO ....................................................................................................................................................................16 EXERCCIOS PROPOSTOS ..........................................................................................................................................18 ANOTAES ..............................................................................................................................................................19 RECURSOS BSICOS: EXEMPLO 3 CONTADOR HEXADECIMAL ..................................................................20 RECURSOS DO LIVRO ................................................................................................................................................20 LGICA DO EXEMPLO .................................................................................................................................................20 ESQUEMA ELTRICO..................................................................................................................................................21 FLUXOGRAMA ............................................................................................................................................................22 CDIGO ....................................................................................................................................................................25 EXERCCIOS PROPOSTOS ..........................................................................................................................................28 ANOTAES ..............................................................................................................................................................29 RECURSOS AVANADOS: EXEMPLO 4 MAXIMIZAO DE PINOS DE I/O...................................................30 RECURSOS DO LIVRO ................................................................................................................................................30 LGICA DO EXEMPLO .................................................................................................................................................30 ESQUEMA ELTRICO..................................................................................................................................................31 FLUXOGRAMA ............................................................................................................................................................32 CDIGO ....................................................................................................................................................................36 EXERCCIOS PROPOSTOS ..........................................................................................................................................40 ANOTAES ..............................................................................................................................................................41 RECURSOS AVANADOS: EXEMPLO 5 VARREDURA DE DISPLAY .............................................................42 RECURSOS DO LIVRO ................................................................................................................................................42 LGICA DO EXEMPLO .................................................................................................................................................42 ESQUEMA ELTRICO..................................................................................................................................................44 FLUXOGRAMA ............................................................................................................................................................45 CDIGO ....................................................................................................................................................................50 EXERCCIOS PROPOSTOS ..........................................................................................................................................57 ANOTAES ..............................................................................................................................................................58 RECURSOS AVANADOS: EXEMPLO 6 CONTROLE DO LCD ............................................................................59 RECURSOS DO LIVRO ................................................................................................................................................59 LGICA DO EXEMPLO .................................................................................................................................................59 ESQUEMA ELTRICO..................................................................................................................................................60 FLUXOGRAMA ............................................................................................................................................................61 CDIGO ....................................................................................................................................................................68 EXERCCIOS PROPOSTOS ..........................................................................................................................................76 ANOTAES ..............................................................................................................................................................77 RECURSOS AVANADOS: EXEMPLO 7 CONVERSOR ANALGICO DIGITAL..............................................78 RECURSOS DO LIVRO ................................................................................................................................................78 LGICA DO EXEMPLO .................................................................................................................................................78 Linguagem C para PIC 3

ESQUEMA ELTRICO..................................................................................................................................................79 FLUXOGRAMA ............................................................................................................................................................80 CDIGO ....................................................................................................................................................................82 EXERCCIOS PROPOSTOS ..........................................................................................................................................86 ANOTAES ..............................................................................................................................................................87 RECURSOS AVANADOS: EXEMPLO 8 CONTROLE DO PWM E EEPROM INTERNA ..................................88 RECURSOS DO LIVRO ................................................................................................................................................88 LGICA DO EXEMPLO .................................................................................................................................................88 ESQUEMA ELTRICO..................................................................................................................................................89 FLUXOGRAMA ............................................................................................................................................................90 CDIGO ....................................................................................................................................................................93 EXERCCIOS PROPOSTOS ..........................................................................................................................................99 ANOTAES ............................................................................................................................................................100 RECURSOS AVANADOS: EXEMPLO 9 COLETOR DE DADOS ....................................................................101 RECURSOS DO LIVRO ..............................................................................................................................................101 LGICA DO EXEMPLO ...............................................................................................................................................101 ESQUEMA ELTRICO................................................................................................................................................102 FLUXOGRAMA ..........................................................................................................................................................103 CDIGO ..................................................................................................................................................................109 EXERCCIOS PROPOSTOS ........................................................................................................................................114 ANOTAES ............................................................................................................................................................115 RECURSOS AVANADOS: EXEMPLO 10 FUNES MATEMTICAS..............................................................116 RECURSOS DO LIVRO ..............................................................................................................................................116 LGICA DO EXEMPLO ...............................................................................................................................................116 ESQUEMA ELTRICO................................................................................................................................................117 FLUXOGRAMA ..........................................................................................................................................................118 CDIGO .................................................................................................................................................................119 EXERCCIOS PROPOSTOS ........................................................................................................................................121 ANOTAES ............................................................................................................................................................122

Linguagem C para PIC

Recursos Bsicos: Exemplo 1


1.1 - Recursos do Livro

Boto e Led

Para o bom entendimento deste nosso primeiro exemplo so necessrios os conhecimentos de programao em linguagem C, comandos de controle de Fluxo (cap.7 do livro Programao em C), declarao de variveis, constantes e tipos de dados (cap.5 do livro Programao em C), diretivas de configurao dos pinos de I/O (cap.10-pg.170, cap.11.5; 11.6-pg.202; 11.7 e cap.12.2-pg. 250 do livro Programao em C).

1.2 - Lgica do exemplo


Nosso exemplo ser composto de um programa capaz de ler um boto e controlar um led. Com o boto S1 pressionado o led L2 acende, com o boto 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 sada, fundamental j que estamos trabalhando com um microcontrolador. Neste exemplo voc ver o comando WHILE, (Faa enquanto for verdadeiro) sendo utilizado para o controle de fluxo de nossa rotina principal, forando um loop infinito. O comando IF ELSE, (Se verdadeiro {comando}, Se falso {comando}), realiza o teste do boto e determina o caminho a ser seguido, se acende ou apaga o led. Caso o boto esteja pressionado o teste determina que o led deve acender, caso contrrio o led ser apagado. Para o teste do boto est sendo utilizado o operando ! (NOT), para boto pressionado temos nvel lgico zero no pino de I/O, neste caso o teste com o comando IF ser verdadeiro para boto pressionado e falso para boto liberado.

Linguagem C para PIC

1.3 - Esquema Eltrico

+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

Linguagem C para PIC

1.4 - Fluxograma

MAIN

CONFIGURAES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

A LIMPA WATCHDOG

NO

BOTO S1 PRESS.?

SIM

APAGA LED L2

ACENDE LED L2

Linguagem C para PIC

1.5 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Bsicos de programao * * Exemplo 1 * * * * CENTRO DE CAPACITAO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * Este software est preparado para demonstrar o controle este primeiro programa demonstrar o estado de um boto * * * * * * * * * * * * * * * * */ dos pinos de I/O por meio de um led.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio das variveis internas do PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. //Este programa no utiliza nenhuma varivel de usurio /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. //Este programa no utiliza nenhuma constante de usurio /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. //Este programa no utiliza nenhum flag de usurio /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes #bit

* * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programao do hardware. // Estado do boto // 1 -> Liberado // 0 -> Pressionado

* * */ e

botao = portb.0

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // As sadas devem ser associadas a nomes para facilitar a programao //futuras alteraes do Hardware. #bit led = portb.1 // Led correspondente ao boto // 1 -> Led ligado // 0 -> Led desligado

* * */ e

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes 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; // // // // // // configurao 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 boto // Se boto = 0, ento led = 1 // caso contrrio, led = 0 // FIM DO PROGRAMA

1.6 -

Linguagem C para PIC

1.7 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Utilize as funes do Compilador para controlar o Led, OUTPUT_HIGH e OUTPUT_LOW. 2. Altere a lgica do programa para que o led acenda com o boto liberado e apague com o boto pressionado. 3. Troque o pino de I/O que controla o boto, por exemplo, utilize o pino RB3. 4. Com o boto pressionado acenda o led 2 e apague o led 3, para o boto liberado apague o led 2 e acenda o led 3.

10 Linguagem C para PIC

1.8 - Anotaes

Linguagem C para PIC

11

Recursos Bsicos: Exemplo 2


1.9 - Recursos do Livro

Pisca Pisca Varivel

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos no exemplo 1 e mais, funes do compilador para controle de atraso (cap.11.4 pg. 195 do livro Programao em C), Operadores para criao de expresses lgicas e aritmticas (cap.6 do livro Programao em C), diretivas de configurao para uso de funo de atraso (cap.10, pg.169 do livro Programao em C).

1.10 - Lgica do exemplo


A finalidade de nosso exemplo demonstrar a inverso de portas e a utilizao da funo de delay da Linguagem C. Atravs dos botes S1 e S2, Up e Down possvel ajustar a freqncia de oscilao dos Leds 3 e 4 da placa McLab2. As constantes min e max determinam os limites, mximos e mnimos de ajuste da freqncia de oscilao. Para a inverso das portas est sendo utilizado o operador lgico ~, (NOT, complemento de 1), com este operando estaremos invertendo bit a bit o contedo do registrador portb. A funo delay_ms gera um atraso de milisegundos usando o ciclo de mquina, ou seja, o programa fica travado nesta funo at o tempo desejado. O camando For (inicializao, teste condicional, incremento) utilizado para controle do lao da rotina de delay, definindo a quantidades de vezes que o lao ser executado, nesta rotina no utilizaremos a opo de inicializao do comando For, sendo a mesma executada fora do lao.

Linguagem C para PIC

13

1.11 - Esquema Eltrico

+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

CONFIGURAES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

NO

BOTO S1 PRESS.?

SIM

INICIALIZA PORTB COM 0X0F B LIMPA WATCHDOG

SIM

TEMPO = MAX?

NO

INCREMENTA TEMPO COMPLEMENTA PORTB

A NO BOTO S2 PRESS.? SIM

SIM

TEMPO = MIN?

NO

DECREMENTA TEMPO

CARREGA A VARIVEL CONTADOR COM O VALOR DA VARIVEL TEMPO

ROTINA DE DELAY LAO FOR

NO

CONTADOR 0

SIM DELAY (10MS)

Linguagem C para PIC

15

1.13 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Bsicos de programao * * Exemplo 2 * * * * CENTRO DE CAPACITAO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Este software demonstrar a utilizao da funo de delay e //a frequncia de oscilao dos leds controlada pelos botes * * * * * * * * * * * * */ a inverso de portas S1 (UP) e S2 (DOWN).

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio das variveis internas do PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configurao dos fusveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definies para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) // diretiva para o uso da funo delay /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. int contador = 0 ; int tempo = 9; /* * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * //A definio de constantes facilita a programao //Este programa no utiliza constantes #define max 255 // Limite de ajuste do #define min 10 * * * * * * * * * * * * * * * * * * * * * * * * */ e a manuteno. tempo

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. //Este programa no utiliza nenhum flag de usurio. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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 alteraes #bit botao_0 #bit botao_1

* * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programao do hardware. = portb.0 // Estado do boto_0 // 1 -> Liberado // 0 -> Pressionado = portb.1 // Estado do boto_1 // 1 -> Liberado // 0 -> Pressionado

* * */ e

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // As sadas devem ser associadas a nomes para facilitar a programao //futuras alteraes do hardware.

* * */ e

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes 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 boto_0 foi pressionado? sim, tempo diferente de max? no, incrementa tempo boto_0 liberado, testa boto 1

if (!botao_1) // O boto 1 foi pressionado ? { if (tempo != min) // sim, tempo diferente de min? { tempo = tempo - 1; // no, decrementa tempo } } // boto_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 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Implemente a inverso de portas para que o led 3 e o led 4 pisquem alternadamente. 2. Utilize a forma reduzida para incrementar e decrementar a varivel tempo. 3. Troque a funo delay_ms por delay_us e ajuste as constantes para obter o mesmo ajuste de freqncia. 4. Substitua o comando For pelo comando While.

18 Linguagem C para PIC

1.15 - Anotaes

Linguagem C para PIC

19

Recursos Bsicos: Exemplo 3


1.16 - Recursos do Livro

Contador Hexadecimal

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos nos exemplos anteriores e tabela de constante (cap.12.21 pg. 309 do livro Programao em C).

1.17 - Lgica do exemplo


Atravs dos botes 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 implementao de tabelas utilizando a memria de programa, sendo est tabela uma matriz unidimensional, nossa tabela far a converso de BCD para sete segmentos, realizando a funo de um circuito decodificador. Para o devido tratamento dos botes, neste exemplo foi implementada uma rotina de filtro para cada boto evitando o problema de debouncing, alm do filtro foi criado um flag, para cada boto, que tem a funo de indicar se a tecla est pressionada ou liberada. Desta forma para que o contador seja incrementado ou decrementado o boto deve ser pressionado e depois liberado. A varivel contador ser utilizada como indexador da tabela de constante, assim sendo para o contador igual zero, ser retornado o cdigo de sete segmentos para o nmero zero e assim por diante.

20 Linguagem C para PIC

1.18 - Esquema Eltrico

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

CONFIGURAES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

INICIALIZA PORTB COM 0X10 B LIMPA WATCHDOG

22 Linguagem C para PIC

NO

BOTO S1 PRESS.?

SIM

Re-carrrega o Filtro do Boto Marca boto liberado

O boto j estava pressionado ?

SIM

NO

NO

Filtro 0 ?

Marca Boto pressionado

SIM

Decrementa o Filtro NO

Contador Max ?

SIM Incrementa o contador Consulta tabela de converso e atualiza o display

Linguagem C para PIC

23

NO

BOTO S2 PRESS.?

SIM

Re-carrrega o Filtro do Boto Marca boto liberado

O Boto j estava pressionado ?

SIM

NO

NO

Filtro 0 ?

Marca Boto pressionado

SIM

Decrementa o Filtro NO

Contador Min ?

SIM Decrementa o contador Consulta tabela de converso e atualiza o display

24 Linguagem C para PIC

1.20 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Bsicos de programao * Exemplo 3 * * CENTRO DE CAPACITAO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * // // * * * * * * * * */

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Contador hexadecimal que utiliza dois botes para incrementar e decrementar o valor da varivel "contador". O contador est limitado pelas constantes min e max.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIO DAS VARIVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configurao dos fusveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definies para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. #define t_filtro 400 #define min 0 #define max 15 // tamanho do filtro // valor mnimo para o contador // valor mximo para o contador

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. int contador=min; // long int filtro0=t_filtro; // long int filtro1=t_filtro; // int flags=0; // inicia contador com mnimo inicia filtro do bot1 inicia filtro do bot2 limpa os flags

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. #bit bt_UP_press = flags.0 #bit bt_DOWN_press = flags.1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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 programao do hardware. // Estado do boto UP // 1 -> Liberado // 0 -> Pressionado * * */ e

/* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes #bit

botao_UP = portb.0

#bit

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

/* * * // //

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * As sadas devem ser associadas a nomes para facilitar a programao futuras alteraes do hardware.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tabela de Valores * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ byte const tabela[16] = { //PGFEDCBA ; POSIO 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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes 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 Boto 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao_UP) // O boto UP est pressionado ? { // sim, if (!(bt_UP_press)) // O boto UP j foi tratato ? { // no. if (filtro0 !=0) // Fim do filtro do boto UP ? { filtro0--; // No, ento decrementa o filtro } else // Sim, Faz a ao do boto { bt_UP_press = 1; // Marca que o boto est pressionado if (contador != max) { contador++; // incrementa o contador portd = (tabela[contador]); // consulta tabela, atualiza // display } } } } else { // boto 0 liberado filtro0 = t_filtro; // inicia o filtro do boto 0 bt_UP_press = 0; // marca que o boto foi liberado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao_DOWN) // testa boto DOWN { // boto DOWN pressionado if (!(bt_DOWN_press)) // o boto DOWN j foi tratato ? { // no if (filtro1 !=0) // Fim do filtro do boto DOWN ? { filtro1--; // no, ento decrementa o filtro } else // SIM. Faz a ao do boto { bt_DOWN_press = 1; // marca que o boto est pressionado if (contador != min) { contador--; // decrementa o contador portd = (tabela[contador]);// consulta tabela, atualiza // display } } } } else { // boto 1 liberado filtro1 = t_filtro; // inicia o filtro do boto 1 bt_DOWN_press = 0; // marca que o boto foi liberado } } }

Linguagem C para PIC

27

1.21 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. 2. 3. 4. Modifique o programa para que o contador conte de 1 a 5. Implemente um boto para reset do contador. Altere a tabela para que as posies 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 - Anotaes

Linguagem C para PIC

29

Recursos Avanados: Exemplo 4


1.23 - Recursos do Livro

Maximizao de Pinos de I/O

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos nos exemplos anteriores e mais, funes do compilador para controle de interrupo, tratamento automtico (cap.12 pg.254 do livro Programao em C), controle do processador (cap.11 pg.223 do livro Programao em C), manipulao de Timers (cap.11.8 pg.211 do livro Programao em C), diretivas de configurao para uso de interrupes, #int_xxx e #priority (cap.10, pg.161 e pg.166 do livro Programao em C).

1.24 - Lgica do exemplo


Nosso exemplo ser composto de um programa capaz de ler quatro botes e tocar o buzzer com uma freqncia diferente para cada combinao de botes. Para cada boto existe um led ligado no mesmo pino, que ser utilizado para indicar os botes pressionados no momento. Utilizaremos os timers e duas interrupes para controlarmos a freqncia de leitura dos botes e a freqncia do buzzer: Timer 0: controlar a freqncia de varredura dos botes; Timer 2: controlar a freqncia do som. O som ser feito excitando o buzzer com uma onda quadrada de freqncia varivel. Variaremos esta freqncia 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 interrupes. Para a varredura dos botes ajustaremos a interrupo de TMR0 para aproximadamente 500Hz: Ciclo de Mq. 1 s Prescale 8 Conta TMR0 256 Auxiliar Perodo 2048 s Freqncia 488 Hz

Alm 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 2048s. Quanto freqncia do buzzer, esta ser controlada por TMR2. Calibramos os valores de pre e postscale para que a freqncia da interrupo do TMR2 varie entre 100Hz e 2kHz, com a variao de PR2 entre 16 e 240: Ciclo de Mq. 1 s 1 s Prescale 16 16 Postscale 1 1 PR2 16 240 Perodo 256 s 3840 s Freqncia 3906 Hz 260 Hz

Para facilitar a implementao, a cada interrupo inverteremos o estado do pino de acionamento do buzzer. Desta forma, a freqncia deste ser equivalente metade da freqncia da interrupo do TMR2. O Livro Conectando o PIC, possui um cpitulo dedicado a este assunto.

30 Linguagem C para PIC

1.25 - Esquema Eltrico

+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

CONFIGURAES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

LIGA AS INTERRUPES

LIMPA WATCHDOG

32 Linguagem C para PIC

INTERRUPES

NO

INT DE TMR0?

SIM

Trata TMR2

Trata TMR0

TRATA TMR2

NO

SADA DO BUZZER EST LIGADA?

SIM

LIGA A SADA DO BUZZER

DESLIGA A SADA DO BUZZER

FIM DA INTERRUPO

Linguagem C para PIC

33

TRATA TMR0

Convetre pinos dos botes em entradas

Delay de 4 ciclos de mquina para estabilizao do port

L todos os botes e guarda em varivel temporria (STATUS_BOTES)

Converte pinos dos botes em sada

CHECA BOTO S1 NO

Reinicia Filtro

Boto S1 PRESS ?

Limpa Flag de boto pressionado (Status Leds)

SIM

Fim do Filtro ?

NO

SIM Marca flag de boto pressionado

CHECA BOTO S2

CHECA BOTO S3

CHECA BOTO S4

34 Linguagem C para PIC

AO DOS BOTES

Atualiza leds conforme botes pressionados

NO

Algum boto pressionado ?

SIM

Inicializa PER com 255

Consulta tabela conforme conbinao de botes pressionados

Deliga interrupo de TMR2

Inicializa TMR2

Desliga a sada do Buzzer

Liga Interrupo de TMR2

FIM DA INTERRUPO

Linguagem C para PIC

35

1.27 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Bsicos de programao * Exemplo 4 * * CENTRO DE CAPACITAO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Este software est preparado para ler quatro botes e //durao variavel conforme a tecla pressionada, alm de //indicando a ltima tecla pressionada. * * * * * * * * */

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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIO DAS VARIVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. #define t_filtro 20 // tamanho do filtro

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis 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 lgico dos botes // atualiza leds conforme o boto pressionado // limitador de contagem do Timer2 // // // // inicia inicia inicia inicia filtro filtro filtro filtro do do do do botao1 botao2 botao3 botao4

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes #bit * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programao do hardware. * * */ e

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

#bit

#bit

#bit

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // AS SADAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAO //FUTURAS ALTERAES 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}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurao do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // A rotina principal simplesmente limpa o WDT, pois toda a lgica do // programa tratada dentro das interrupes. 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 interrupo de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Esta interrupo ocorrer a cada 2048us. O filtro dos botes tem durao de 40ms (2048us x 20) e so decrementados a cada interrupo. Esta interrupo responsvel por converter os pinos dos botes em entrada, salvar a condio dos botes em varivel temporria e converter os pinos em sada 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 botes // aguarda 4 ciclos de mquina para a // estabilizao do portb // l o status dos botoes, salva em varivel // temporria // configura os pinos como sada para // controle dos leds

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) { filtro1--; if (filtro1 == 0) { botao1_press = 1; } } else { filtro1 = t_filtro; botao1_press = 0; } // // // // testa boto 1 boto 1 est pressionado ? Sim, ento decrementa o filtro acabou o filtro do boto 1 ?

// marca que o boto est pressionado

// boto 1 liberado // inicia o filtro do boto 1 // marca que o boto foi liberado

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

// marca que o boto est pressionado

// boto 2 liberado // inicia o filtro do boto 2 // marca que o boto foi liberado * * * * * * * * * * * * * * * * Boto 3 * * * * * * * * * * * * * * * * */ // testa boto 3 // boto 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, ento decrementa o filtro // fim do filtro do boto 3 ? // marca que o boto est pressionado

// boto 3 liberado // inicia o filtro do boto 3 // marca que o boto foi liberado * * * * * * * * * * * * * * * * Boto 4 * * * * * * * * * * * * * * * * */ // testa boto 4 // boto 4 est pressionado ? // Sim, ento decrementa o filtro // fim do filtro do boto 4 ? // marca que o boto est pressionado

// boto 4 liberado // inicia o filtro do boto 4 // marca que o boto foi liberado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Atualiza Leds conforme botes 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 interrupo de timer2. } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupo de TMR2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Est interrupo s ir ocorrer quando alguma tecla estiver pressionada, // o periodo de ocorrncia depende do boto ou da conbinao de botes pressionados, // ela ir inverter o pino de I/O do buzzer a cada interrupo. #int_timer2 void trata_int_tmr2() { if (buzzer != 0) // o buzzer est ligado ? { buzzer = 0; // sim, ento desliga } else { buzzer = 1; // no, ento liga } }

Linguagem C para PIC

39

1.28 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Utilize as funes disponveis do Compilador para inverter o estado do buzzer. 2. Modifique o controle dos leds, os botes pares controlam os leds impares e os botes impares controlam os leds pares, conforme a tabela abaixo. Boto 1 Boto 2 Boto 3 Boto 4 Led 2 Led 1 Led 4 Led3

40 Linguagem C para PIC

1.29 - Anotaes

Linguagem C para PIC

41

Recursos Avanados: Exemplo 5


1.30 - Recursos do Livro

Varredura de Display

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos nos exemplos anteriores e mais, funes do compilador para controle de interrupo, tratamento manual (cap.12 pg.254 do livro Programao em C), controle do processador (cap.11 pg.223 do livro Programao em C), manipulao de Timers (cap.11.8 pg.211 do livro Programao em C), introduo de cdigo em assembly no programa em C (cap.10, pg.151 do livro Programao em C),retorno de valores em funes assembly (cap.9, pg.147 do livro Programao em C), diretivas de configurao para uso de interrupes, #int_global e #priority (cap.10, pg.162 e pg.166 do livro Programao em C).

1.31 - Lgica 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) no possui nenhuma funo. Por outro lado, o led relacionado a ela (L1) ser utilizado para indicar o estado do temporizador: L1 Aceso Apagado Descrio Temporizador em contagem regressiva Temporizador paralisado

Os demais botes apresentam as funes de controle do temporizador: Boto S2 S3 S4 Descrio Incrementa o valor inicial em 1 segundo Decrementa o valor inicial em 1 segundo Inicia e paralisa o temporizador

Os botes de incremento e decremento operam de forma rotativa, isto , comutam automaticamente entre 0000 e 9999. Outra caracterstica destes botes que eles executam suas funes 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 variveis para armazenamento dos dgitos mostrados nos respectivos displays: UNIDADE, DEZENA, CENTENA e MILHAR. Estas variveis representam o valor atual do temporizador e so incrementadas e decrementadas atravs dos botes. Na verdade, os botes alteram diretamente o valor da unidade. A lgica do sistema compara este valor com os limites (0 e 9) para alterar ou no os demais dgitos. A freqncia de varredura controlada pela interrupo de Timer0. Ajustamos seus parmetros para que a comutao entre displays (tempo da interrupo) seja de aproximadamente 4kHz: Ciclo de Mq. 1 s
42 Linguagem C para PIC

Prescale 1

Conta TMR0 256

Auxiliar -

Perodo 256 s

Freqncia 3900 Hz

A freqncia de varredura ser a freqncia de comutao dividida pelo nmero de displays, que no nosso caso ser de aproximadamente 1kHz. Dentro do tratamento da interrupo de TMR0 desligado o display atual, carregado o valor do dgito correspondente ao display e ligado o display seguinte. Quanto contagem dos segundos, utilizamos a interrupo de Timer1 para esta finalidade. Veja os ajustes dos parmetros para esta interrupo: Ciclo de Mq. 1 s Prescale 8 Conta TMR1 62500 Auxiliar 2 Perodo 1.000.000 s Freqncia 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 interrupo acontecer a cada 0,5 segundo. Para podermos contar 1 segundo foi criado uma varivel auxiliar denominada DIVISOR_TMR1. Cada vez que o sistema entrar na interrupo de TMR1 e o contador auxiliar (DIVISOR_TMR1) terminar, o tempo decrementado, comeando pela unidade e chegando at a milhar, se for necessrio. Quando o tempo termina (0000) tanto o led quanto o TMR1 so desligado. Neste exemplo est sendo utilizado o tratamento Manual de interrupes, neste modo ns devemos providenciar todo o cdigo necessrio para o tratamento da interrupo, tais como: salvar contexto, restaurar contexto, limpar os flags de indicao de interrupo e criar os registradores para as rotinas de salvar e restaurar contexto. A prioridade de tratamento da interrupo depende da seqncia de teste dos flags de int, que tambm de responsabilidade do programador. Para este tipo de tratamento estamos utilizando a diretiva #int global.

Linguagem C para PIC

43

1.32 - Esquema Eltrico


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

CONFIGURAES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

Configura Timer1

Liga as interrupes A Limpa WATCHDOG

BOTO UP PRESS.?

SIM

Trata Boto UP

NO

BOTO DOWN PRESS.?

SIM

Trata Boto Down

NO

BOTO Start/Stop PRESS.?

SIM

Trata Boto Start/Stop

NO

Recarrega Filtro e turbo das teclas

Linguagem C para PIC

45

INTERRUPES

NO

INT DE TMR0?

SIM

SWITCH CASE Recarrega Timer1 Incrementa ponteiro de seleo de Display, desliga display do milhar, consulta tabela de converso para sete segmentos, liga display da unidade

Atualiza Display da Unidade? decrementa contador de int. NO

SIM

Passou 1 segundo ?

NO

Atualiza Display da Dezena?

SIM

Incrementa ponteiro de seleo de Display, desliga display da unidade, consulta tabela de converso para sete segmentos, liga display da dezena

SIM

NO

Recarrega contador de int. Atualiza Display da Centena? SIM

Incrementa ponteiro de seleo de Display, desliga display da dezena, consulta tabela de converso para sete segmentos, liga display da centena

Decrementa Timer

NO

Timer Chegou a zero?

NO

Atualiza Display do milhar?

SIM

Zera ponteiro de seleo de Display, desliga display da centena, consulta tabela de converso para sete segmentos, liga display do milhar

NO SIM

Desliga led de indicao de timer operando FIM DA INTERRUPO

Desabilita interrupo de Timer1

FIM DA INTERRUPO

46 Linguagem C para PIC

Trata Boto UP

Trata Boto DOWN

Timer Ligado ?

SIM

Timer Ligado ?

SIM

NO

NO

Decrementa Filtro

Decrementa Filtro

NO Fim do Filtro ? Fim do Filtro ?

NO

SIM

SIM

Decrementa Turbo

Decrementa Turbo

Fim do Temporizador para Turbo do Boto?

NO

Fim do Temporizador para Turbo do Boto?

NO

SIM

SIM

Recarrega temporizador para Turbo

Recarrega temporizador para Turbo

Incrementa Timer

Decrementa Timer

Linguagem C para PIC

47

Trata boto Start/Stop

SIM Ao j foi executada ?

NO

NO Filtro terminou ?

SIM

NO Timer ligado ?

SIM SIM Timer igual a zero ? Apaga led de indicao de Timer ligado

NO Desabilita interrupo de Timer1

Acende Led de indicao de Timer ligado

Carrega Timer1

Carrega contador de interrupes

Habilita interrupo de Timer 1

48 Linguagem C para PIC

Incrementa Timer

Decrementa Timer

Incrementa unidade

Decrementa unidade

NO Unidade = 10 ? Unidade = 0XFF ?

NO

SIM

SIM

Zera unidade Incrementa dezena

Unidade = 9 Decrementa dezena

NO Dezena = 10 ? Dezena = 0XFF ?

NO

SIM

SIM

Zera dezena Incrementa centena

Dezena = 9 Decrementa centena

NO centena = 10 ? centena = 0XFF ?

NO

SIM

SIM

Zera centena Incrementa milhar

Centena = 9 Decrementa milhar

NO Milhar = 10 ? Milhar = 0XFF ?

NO

SIM Zera milhar

SIM Milhar = 9

Return

Return

Linguagem C para PIC

49

1.34 - Cdigo
/* * * * * * * * * * * * /* * * // // // // // // // // /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Bsicos de programao * Exemplo 5 * * CENTRO DE CAPACITAO - LABTOOLS * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio 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 botes foram utilizados para programar o tempo da contagem. Um outro boto foi utilizado para disparar o contador. O temporizador consegue contar at 9999 segundos, de forma que os 4 displays de 7 segmentos foram necessrios. A contagem regressiva. um led indica que o temporizador est operando. Quando o sistema chega a 0000 (ZERO) o led desligado automaticamente. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIO DAS VARIVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ <16f877A.h> // microcontrolador utilizado

#include

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definies para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. #define t_filtro 250 // tamanho do filtro #define turbo_tecla 60 #define delta_timer1 (65536 - 62500) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis 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 interrupes de timer1 // inicia filtro dos botes // inicia turbo das teclas // varivel unidade do timer de 1 seg // varivel dezena do timer de 1 seg // varivel centena do timer de 1 seg // varivel milhar do timer de 1 seg // variveis para salvar contexto

static static static static

50 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * Definio de SFR's * * * * * * * * * * * * * * * * * * * * * * * * * * #bit tmr1if = 0x0c.0 // tmr1if #bit t0if = 0x0b.2 // t0if o #bit tmr1ie = 0x8c.0 // tmr1ie #byte status = 0x03 // define endereo #byte fsr = 0x04 // define endereo #byte pclath = 0x0a // define endereo

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes #bit * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * ser associadas a nomes para facilitar a programao do hardware. // Estado do boto up // 1 -> Liberado // 0 -> Pressionado // Estado do boto down // 1 -> Liberado // 0 -> Pressionado * * */ e

bt_up = portb.1

#bit

bt_down

= portb.2

#bit

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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // AS SADAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAO //FUTURAS ALTERAES DO HARDWARE. #bit estado_timer = portb.0 // led de estado do timer // 1 -> timer contando // 0 -> timer parado // seleo do display unidade (0) // seleo do display dezena // seleo do display centena (2) // seleo 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}; /* * * * * * * * * * * * * * Funo * * * * * * * * * * * * * 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; } } /* * * * * * * * * * * * * * Funo * * * * * * * * * * * * * 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; } }

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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo de tratamento de interrupo de Timer1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupo ocorrer a cada 0,5 segundos, a rotina de tratamento executada a // cada 2 interrupes (contador). #inline trata_tmr1() { set_timer1(delta_timer1); // carraga timer1 tmr1if = 0; // limpa flag de interrupo contador --; // decrementa contador de interrupes 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 interrupo de timer1 } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupo de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupo ocorrer a cada 256us. #inline trata_tmr0() { t0if = 0; switch(display) // incio da varredura dos displays { case 0: display++; // incrementa a varivel 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 varivel de varredura desliga o display 0 // atualiza o portd liga o display 1 sai incrementa a varivel de varredura desliga o display 1 // atualiza o portd liga o display 2 sai inicia a varivel de varredura desliga o display 2 // atualiza o portd liga o display 3 sai

Linguagem C para PIC

53

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 INTERRUPO. 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 } /* * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 (PAGINAO) FSR (END. INDIRETO) STATUS WORK

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurao 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 Boto de incremento (UP) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_up) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto de decremento (down) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_down) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto de Start / Stop * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_start_stop) // testa boto 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 boto? { turbo --; // decrementa o turbo da tecla if (turbo == 0) // sim, fim do turbo do boto ? { 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 boto? { turbo --; // decrementa o turbo da tecla if (turbo == 0) // sim, fim do turbo do boto ? { turbo = turbo_tecla; // carrega o turbo decrementa_timer(); // decrementa o timer } } } goto loop; // testa boto down trata_dowm;// desvia para a rotina de decremento do timer // testa boto 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 boto? { if (estado_timer != 0) // sim, o timer est ligado ? { estado_timer = 0; // indica timer parado tmr1ie = 0; // desliga o tratamento de interrupo de timer1 } else { if((unidade!=0)||(dezena!=0)||(centena!=0)||(milhar != 0)) // timer est zerado? { estado_timer = 1;// no, 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 interrupo de timer1 } } } } goto loop; } /* * * // // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo de Tratamento de interrupes * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Todo o tratamento de interrupo feito manualmente. As funes salva contexto e restaura contexto foram feitas em assembler Observe que a prioridade das interrupes realizada atravs do comando IF e a ordem do teste determina a prioridade no tratamento da interrupo.

#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

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

restaura_contexto(); }

56 Linguagem C para PIC

1.35 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Mude a rotina para que o temporizador conte de forma crescente e desligue quando chegar a zero. 2. Altere a rotina de temporizao para que o timer seja decrementado a cada 1 minuto. 3. Mude a rotina do timer para que ele funcione como um cronmetro com um boto de start e um de reset.

Linguagem C para PIC

57

1.36 - Anotaes

58 Linguagem C para PIC

Recursos Avanados: Exemplo 6 Controle do LCD


1.37 - Recursos do Livro
Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos no exemplo 1 e mais, controle do LCD (cap.12.7.2 pg. 310 do livro Programao em C).

1.38 - Lgica do exemplo


Este exemplo foi criado para demonstrar a inicializao 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 atravs de um MENU, tecla S1, de escolha de opes, onde ser possvel escolher as opes de ligar ou desligar atravs da tecla ENTER, tecla S2. A escolha das telas ser controlada pelo comando SWITCH do compilador C. Aps 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 opes de controle, pressionando a tecla menu possvel 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 opo desejada, ON ou OFF, quando a tecla for pressionada o smbolo > ser deslocado para a condio desejada.

Linguagem C para PIC

59

1.39 - Esquema Eltrico


+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 1 OSC2 5 1 RC0 6 RC1 1 7 RC2 1 8 2 RC3 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

CONFIGURAES INICIAIS TRIS, PORTAS, W ATCHDOG, PRESCALER.

Configura Timer0

Inicializa LCD

Tela principal

Habilita as interrupes A Limpa W ATCHDOG

Escreve tela principal ?

SIM

Tela principal

NO

BOTO MENUPRESS.?

SIM

Trata Boto Menu

NO

BOTO ENTER PRESS.?

SIM

Trata Boto ENTER

NO

Recarrega Filtro dos Botes

Linguagem C para PIC

61

INT ERRUP ES

Declara Variveis locais

Incrementa contador de interrupes

Temp1 = 40

SIM

NO

Zera contador de interrupes 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 no: Apaga o led 2.

NO

Controle do T ime - out da tela principal

SIM

Incrementa contador de time out, aps 5 segundos, limpa o flag "f_tela_principal", para liberar atualizao da tela principal.

NO

FIM DA INT ERRUPO

62 Linguagem C para PIC

Trata Boto MENU

Ao j foi executada ?

SIM

NO

Decrementa Filtro

SIM

Fim do Filtro ?

NO

SIM Contador de Tela < 2

NO

Posiciona a seta na linha 0, coluna 0 do LCD

Posiciona a seta na linha 1, coluna 0 do LCD

Linguagem C para PIC

63

Trata Boto ENTER

Ao j foi executada ?

SIM

NO

Decrementa Filtro

SIM

Fim do Filtro ?

NO

Carrega a tela de seleo de tarefa: Controle dos Leds ou Controle do Ventilador

Re-inicia time-out

64 Linguagem C para PIC

Linguagem C para PIC

65

Seleo da Tela de Menu Switch Case

SIM Tela 1 do Menu ?

NO

Posiciona a seta na linha 0 coluna 0

SIM Tela 2 do Menu

NO

Posiciona a seta na linha 1 coluna 0

Return

Beep

Fim do loop do Beep ? (conta beep)

SIM

NO

Return

Liga Beep Delay

Desliga Beep Delay

Decrementa conta beep

66 Linguagem C para PIC

Seleo da Tela de Enter Switch Case

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

NO

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

NO

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

NO

SIM Tela 4 do Enter

NO

Indica estado do ventilador On ou Off emite beep

Return

Linguagem C para PIC

67

1.41 - Cdigo
/* * * * * * * * * * * * /* * * // // // // // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Bsicos de programao * Exemplo 6 * * CENTRO DE CAPACITAO - LABTOOLS * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Este exemplo foi elaborado para explicar o funcionamento do mdulo de LCD. Foi criada uma rotina para escrever comandos e uma para escrever caracteres, existe tambm uma rotina de inicializao necessria para a correta configurao do LCD. Os botes S1 e S2 so respectivamente boto Menu e Enter, o boto Menu seleciona a tarefa que desejamos executar (controle de Leds ou do Ventilador), o boto Enter seleciona a tarefa e funciona como controle de liga/desliga para a tarefa selecionada. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIO DAS VARIVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ arquivo de definies do pic utilizado deve ser referenciado para que nomes definidos pela Microchip possam ser utilizados, sem a necessidade redigitao. <16f877A.h> // microcontrolador utilizado

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

#include

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definies para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. #define t_filtro 500 // tamanho do filtro

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. long int filtro = t_filtro; // inicia filtro dos botes int flags1 = 0; // registrador de flags int contador_tela = 0; // contador para seleo 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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. #bit f_tela_principal = /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes #bit menu flags1.0

* * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programao e do hardware. // Estado do boto menu // 1 -> Liberado // 0 -> Pressionado // Estado do boto enter // 1 -> Liberado // 0 -> Pressionado

= portb.0

#bit

enter = portb.1

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SADAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAO E //FUTURAS ALTERAES 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 recepo 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 mnimo 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 mnimo 40 microsegundos

Linguagem C para PIC

69

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

// limpa lcd

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicializao 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); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo de Bips * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 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 varivel local // contabiliza quantas vezes ter // que fazer o loop de bips // faa 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 perodo escolhido // desliga o buzzer // conta tempo para o perodo 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 } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleo de tela aps 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 "espao" 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 "espao" 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 "espao" 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleo 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 funo } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleo das telas aps 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 funo

// retorna da funo

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 "espao" } 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 "espao" bip(50,2); delay_ms(250); bip(50,2); } break; // retorna da funo

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; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes 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(); // // // // // // configurao da direo 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 "espao" para o lcd // retorna da funo

// // // //

// 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 "espao" 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 boto foi pressionado * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!f_tela_principal) { tela_principal(); }

Linguagem C para PIC

73

//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * if (!menu) { goto } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * if (!enter) { goto } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filtro = t_filtro; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto S1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ trata_menu: //ligar time - out if (filtro != 0) // Ao j foi executada? { filtro --; // no, decrementa o filtro if (filtro == 0) // fim do filtro do boto? { // sim, executa tarefa if (contador_tela < 2) // De selecionar a prxima tarefa? { contador_tela ++;// sim, incrementa contador de seleo de tarefa sel_tela_menu(); // seleciona a tela de menu time_out = 0; // re-inicia contagem do tempo de time-out } else // no, { 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 Boto S2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * trata_enter: if (filtro != 0) // Ao j foi executada? { filtro --; // no, decrementa o filtro if (filtro == 0) // fim do filtro do boto? { sel_tela_enter(); // sim, carrega a tela de seleo time_out = 0; // re-inicia contagem do tempo de } } goto loop; } * * * * * * * * * * * * * * */ // recarga da varivel filtro // testa boto 2 trata_enter;// desvia para a rotina de incremento do timer // testa boto 1 trata_menu;// desvia para a rotina de incremento do timer

de tarefa time-out

74 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupo de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupo ocorrer a cada 256us. // A varivel auxiliar temp1 ser utilizada para contar 40 interrupes, // 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 interrupo // seleciona tarefa // controle do led2 // passou 1 segundo? // sim, zera contador de interrupo

if (led1) // O led1 est ligado { if (!led2) // sim, o led2 est ligado? { led2 = 1; // no, liga o led2 } else { led2 = 0; // sim, desliga o led2 } } // no, ento no controla o led2 else { led2 = 0;// no, mantm o led2 desligado } } contador ++; // incrementa contador de tarefa break; // fim de execuo de execuo 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 execuo de execuo da tarefa default: contador = 0; } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // no, sai da int.

Linguagem C para PIC

75

1.42 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Mude a rotina para que seja controlado o buzzer no lugar do led 2. 2. Crie mais um nvel no Menu para controlar o buzzer.

76 Linguagem C para PIC

1.43 - Anotaes

Linguagem C para PIC

77

Recursos Avanados: Exemplo 7


1.44 - Recursos do Livro

Conversor Analgico Digital

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos no exemplo 1 e mais, funes do compilador para controle do conversor analgico digital (cap.11-pg 206 do livro Programao em C).

1.45 - Lgica do exemplo


Este exemplo foi elaborado para explicar as funes do CCS para o mdulo de converso analgico digital interno do PIC. convertido o valor analgico presente no pino RA1 do microcontrolador, sendo que este valor pode ser alterado atravs do potencimetro P2 da placa MCLAB2 este valor ajustado entre 0 e 5V e mostrado no LCD. Neste exemplo foi utilizado varivel do tipo float para armazenar o resultado da converso A/D. Para que possamos visualizar o valor de 0 5V no LCD, foi feita uma segunda converso o valor digital foi convertido para Volts realizando uma regra de 3.
Valor mximo da resoluo do AD (10 bits) Valor a ser mostrado no display

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

Tenso de Referncia

Valor de tenso medido

78 Linguagem C para PIC

1.46 - Esquema Eltrico

+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

CONFIGURAES INICIAIS TRIS, PORTAS, WATCHDOG, PRESCALER.

Configura AD: RA0,RA1 e RA3 como entradas analgicas. adc = 10 bits Tenso de Refrencia interna (VDD e VSS) Frequencia de converso = fosc / 32 Selecionado Canal 1 Mdulo ligado

Inicializa LCD

Prepara Tela principal

80 Linguagem C para PIC

LIMPA WATCHDOG

Inicia e l o resultado da converso

Multiplica valor da converso por 5

Divide resultado da multiplicao por 1023

Envia resultado para o display

Linguagem C para PIC

81

1.48 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Avanados de programao * Exemplo 7 * * CENTRO DE CAPACITAO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar o funcionamento do mdulo de // converso analgico digital interno do PIC. convertido o valor analgico // presente no pino RA2 do microcontrolador, sendo que este valor pode ser // alterado atravs do potencimetro P2 da placa MCLAB2. O valor da converso // A/D ajustado numa escala de 0 5V e mostrado no LCD. /* * * * * // O //os //de * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIO DAS VARIVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ arquivo de definies do pic utilizado deve ser referenciado para que nomes definidos pela Microchip possam ser utilizados, sem a necessidade redigitao.

#include <16f877A.h> // microcontrolador utilizado #device adc=10 // configura AD para retornar valor em 10 bits /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definies para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. float conversao = 0; // armazena o resultado da converso AD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programao e do hardware.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As sadas devem ser associadas a nomes para facilitar a programao e //futuras alteraes do hardware. #bit rs = porte.0 #bit enable = porte.1 // via do lcd que sinaliza recepo 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); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 mnimo 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 mnimo 40 microsegundos

// limpa lcd

Linguagem C para PIC

83

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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes 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(); // // // // // // configurao da direo 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 converso 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 nmero inteiro e 9 casas decimais.

84 Linguagem C para PIC

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

Linguagem C para PIC

85

1.49 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Mude a configurao do A/D para que ele retorne apenas os 8 bits mais significativos. 2. Altere a funo de escrita no LCD para que ela imprima apenas 3 casas depois da virgula. 3. Mude a configurao do A/D para que ele realize as converses com a Fosc/8.

86 Linguagem C para PIC

1.50 - Anotaes

Linguagem C para PIC

87

Recursos Avanados: Exemplo 8 Interna


1.51 - Recursos do Livro

Controle do PWM e EEPROM

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos no exemplo 1 e mais, funes do compilador para controle do PWM (cap.11.9 pg.218 do livro Programao em C), funes do compilador para operao com EEPROM (cap.11.10 pg.219 do livro Programao em C), diretiva #ROM (cap.10, pg.167 do livro Programao em C) e funo de manipulao de registradores make8 e make16 (cap.11, pg.200 e 201 do livro Programao em C).

1.52 - Lgica do exemplo


Este exemplo foi elaborado para explicar o funcionamento do mdulo de PWM e da escrita da EEPROM interna do microcontrolador. Um ventilador ter a sua velocidade controlada atravs do PWM, o valor ajustado poder ser salvo na memria EEPROM e restaurado atravs dos botes. A velocidade do ventilador medida em rotaes por segundo, atravs do timer1(usado como contador) e mostrada no LCD. Atravs do boto S1, o PWM incrementado e decrementado pelo boto S2. Realizando a operao nestes botes ser visualizado no LCD o incremento e o decremento em porcentagem(%) e a rotao do ventilador em rps (rotaes por segundo). O boto S4 salva o valor de ajuste em EEPROM e o boto S3 restaura o valor salvo atualizando o PWM. Para que possamos utilizar o PWM do PIC no podemos esquecer de configurar a freqncia do PWM no Timer2. T = [(PR2 + 1) * 4] * Tosc * Prescaler TMR2 A funo set_pwm_duty(valor), determina o perodo do pulso do PWM, ou seja, o tempo em que a sada do PWM permanecer em nvel lgico 1. Este valor pode chegar a 1023, enquanto o perodo do PWM pode chegar a 1024, com PR2 igual a 255. Por est razo dependendo da freqncia do PWM no ser possvel alcanar os 100% de Duty Cyle. DC = (valor / T), 1023 / 1024 = 0,9990 Ento antes de utilizar o PWM, estude o funcionamento do Mdulo CCP para um melhor aproveitamento. Este conhecimento pode ser adquirido atravs do livro Conectando o PIC.

88 Linguagem C para PIC

1.53 - Esquema Eltrico


+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

NO

S IM B O T O U P P R ES S.? T rata B oto U P

N O

BO T O D O W N P R ES S .?

S IM

T rata B oto 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 Boto UP

Trata Boto DOWN

Ao j foi executada ?

SIM

Ao j foi executada ?

SIM

NO

NO

Decrementa Filtro

Decrementa Filtro

Fim do Filtro ?

NO

Fim do Filtro ?

NO

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

Linguagem C para PIC

91

INTERRUPES

Contador de interrupes igual a zero ? (Temp1 = 0)

SIM

NO

Decrementa contador de interrupes

Carrega varivel rotao com o valor do Timer1

Divide varivel rotao por 7 (nmero de palhetas do ventilador) habilita atualizao do LCD

FIM DA INTERRUPO

92 Linguagem C para PIC

1.55 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Avanados de programao * Exemplo 8 * * CENTRO DE CAPACITAO - LABTOOLS * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar o funcionamento do mdulo de // PWM e da escrita da EEPROM interna do microcontrolador. Um ventilador ter // a sua velocidade controlada atravs do PWM, o valor ajustado poder ser // salva na memria EEPROM e restaurado atravs dos botes. // A velocidade do ventilador medida em rotaes por segundo, atravs do // timer1 e mostrada no lcd. #include <16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio 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 definio de constantes facilita a programao e a manuteno. #define t_filtro 200 #define turbo_tecla 5 // tamanho do filtro // turbo dos botes

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. float duty_cycle = 0; // armazena o resultado da converso AD long int duty_cycle1 = 0; // armazena o resultado da converso AD long int periodo_pulso = 0; // long int rotacao = 0; // rps do ventilador int end = 0; // varivel para endereamento da eeprom int flags1 = 0; // flags int filtro = t_filtro; // inicia filtro dos botes int temp1 = 125; // varivel aux para int de tmr0 int turbo = 1; // inicia turbo das teclas int dado; // varivel de dados para eeprom

Linguagem C para PIC

93

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. #bit atualiza_lcd = flags1.0 /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes #bit * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programao e do hardware. // Estado do boto 2 // 1 -> Liberado // 0 -> Pressionado // Estado do boto 3 // 1 -> Liberado // 0 -> Pressionado // Estado do boto 4 // 1 -> Liberado // 0 -> Pressionado // Estado do boto 4 // 1 -> Liberado // 0 -> Pressionado

botao1 = portb.0

#bit

botao2 = portb.1

#bit

botao3 = portb.2

#bit

botao4 = portb.3

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As sadas devem ser associadas a nomes para facilitar a programao e //futuras alteraes do hardware. #bit rs = porte.0 #bit enable = porte.1 #bit ventilador = portc.1 // via do lcd que sinaliza recepo de dados ou comando // enable do lcd // pino de I/O para controle do ventilador (PWM) *

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 mnimo 40 microsegundos

94 Linguagem C para PIC

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 mnimo 40 microsegundos

// limpa lcd

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo de inicializao 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); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 endereo indicado atravs da varivel "end", o dado a ser salvo passado para a Funo atravs da varivel "dado".

void salva_dados() { write_eeprom (end,dado); } /* * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * L Dados na EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ l o dado na eeprom no endereo indicado atravs da varivel "end", o dado lido carregado na varivel "dado".

le_dados(end) { dado = read_eeprom (end); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Atualiza PWM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void atualiza_pwm() { set_pwm2_duty(periodo_pulso); }

// atualiza duty cicle do PWM

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); // desliga as entradas analgicas 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) * * */ // configurao da direo 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 rotao medida duty_cycle = (duty_cycle / 1024); // efetua clculo 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 convero tela_principal(); atualiza_lcd = 0; } // imprime a tela principal no LCD // indica LCD atualizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto de incremento (UP) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto de decremento (down) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao2) { goto } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto ler dados da EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao3) { le_dados(1); periodo_pulso = dado; // testa boto 3 // l byte_low da eeprom // carrega valor lido em varivel de 16 bits // testa boto 2 trata_dowm; // desvia para a rotina de decremento do PWM // testa boto 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); // recompe o dado de 16 bits atualiza_pwm(); atualiza_lcd = 1; } // Funo para atualizar o PWM // habilita atualizao do LCD

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Boto salvar dados na EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao4) // testa boto 4 { end = 0; // endereo do byte_high dado = make8(periodo_pulso,1); // retorna byte_high salva_dados(); // salva byte_high end = 1; // endereo do byte_low dado = make8(periodo_pulso,0); // retorna byte_low salva_dados(); // salva byte_low } filtro = t_filtro; turbo = 1; } // carrega filtro dos botes // fecha while

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

Linguagem C para PIC

97

goto

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

//* * * * * * * * * * * Decrementa duty cycle do PWM * * * * * * * * * * trata_dowm: { filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do boto? { turbo --; // decrementa o turbo da tecla filtro = t_filtro; if (turbo == 0) // sim, fim do turbo do boto ? { turbo = turbo_tecla; if (periodo_pulso != 0) // limita decremento do periodo do pulso em 0 { periodo_pulso --; atualiza_pwm(); // Funo para atualizar o PWM atualiza_lcd = 1; // habilita atualizao do LCD } } } } goto loop; } /* * * // // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupo de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Esta interrupo ocorrer a cada 8ms. A varivel auxiliar temp1 ser utilizada para contar 125 interrupes, totalizando 1 segundo. Quando isto ocorrer, a varivel rotao ser carregada com o valor de rotaes 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 atualizao do LCD // re-inicia temp1 // No, // decrementa temp1

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

98 Linguagem C para PIC

1.56 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Mude a freqncia 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 resistncia.

Linguagem C para PIC

99

1.57 - Anotaes

100 Linguagem C para PIC

Recursos Avanados: Exemplo 9


1.58 - Recursos do Livro

Coletor de Dados

Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos no exemplo 1 e mais, funes do compilador para controle de comunicao serial I2C (cap.11.14 pg 240 do livro Programao em C), funes do compilador para controle de comunicao serial RS232 (cap.11.13 pg 230 do livro Programao em C), diretiva de configurao #use i2c e #use RS232 (cap.10, pg.171 e 172 do livro Programao em C).

1.59 - Lgica do exemplo


Este exemplo foi elaborado para explicar as funes de I2C do compilador CCS e comunicao serial com a USART. Neste exemplo iremos coletar dados do A/D e armazenar estes dados na EEPROM externa (24c04), estes dados sero enviados ao PC para a visualizao dos mesmos. O PC controlar as funes 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 liberao da transmisso de dados. Aps o fim da coleta de dados o PIC aguarda o comando 0xaa, recebendo este dado, ele inicia a transmisso de dados para o PC plotar os dados na tela. Ao final da transmisso ele aguarda novo comando de inicio de coleta de dados.

Linguagem C para PIC

101

1.60 - Esquema Eltrico

+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

1uF

MAX-232

CONECTOR DB9 FEMEA

102 Linguagem C para PIC

1.61 - Fluxograma
MAIN

CONFIGURAES INICIAIS TRIS, PORTAS, W ATCHDOG, PRESCALER.

Configurao: AD, rs232 e I2C

Inicializa LCD

Tela principal

Habilita as interrupes A Limpa W ATCHDOG

Verifica se chegou comando pela USART B

SIM Inicia coleta de dados ? Coleta Dados

NO

Deve transmitir dados para o PC ?

SIM TX Dados para o PC

NO

SIM Para a coleta de Dados ?

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

NO

Linguagem C para PIC

103

Recebe comando do PC

Chegou comando do PC ?

NO

SIM

SIM

Recebeu o comando de inicio de Coleta de Dados ?

Tarefa = coleta de dados

NO

B SIM Recebeu o comando de transmisso de dados para o PC ?

Tarefa = transmite dados para o PC

NO

B SIM Recebeu o comando de parar coleta de dados ?

Tarefa = para coleta de dados

NO

104 Linguagem C para PIC

Coleta Dados

Escreve no LCD: "Coletando Dados"

L Dados do AD Salva em EEPROM Serial

NO

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 memria EEPROM Serial Transmite para o PC

NO

Fim da transmisso 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 memria EEPROM Serial

L dados da memria EEPROM Serial

Envia Start bit

Envia Start bit

Envia Controle

Envia Controle

Envia endereo low

Envia endereo low

Envia Dado

Envia Start bit

Envia Stop bit

Envia Controle

delay 10ms

Recebe dados da memria salva em varivel dado

Return

Envia Stop bit

delay 10ms

Return

108 Linguagem C para PIC

1.62 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Avanados de programao * * Exemplo 9 * * * * CENTRO DE CAPACITAO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar as funces de I2C do compilador // CCS. Neste exemplo iremos coletar dados do AD e armazenar estes dados na // EEPROM externa (24c04), estes dados sero enviados ao PC para a // visualizao dos mesmos. O PC controlar as funes do coletor de dados. #include <16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusveis // configurao dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurao do Mdulo I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use i2c(master,sda=pin_c4, scl=pin_c3, SLOW, RESTART_WDT, FORCE_HW) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurao da USART * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use rs232 (baud=9600, xmit = pin_c6, rcv = pin_c7) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. #define #define ctrl_le ctrl_escr 0b10100001// byte de controle da memria p/ leitura 0b10100000// byte de controle da memria p/ escrita

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constante internas do tipo Enumerao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum selecao_de_tarefa { aguarda_comando, coleta_de_dados, transmite_para_pc, parar_coleta }tarefa;

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

Linguagem C para PIC

109

* Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis 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; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. #bit atualiza_lcd = flags1.0 /* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ser associadas a nomes para facilitar a programao e do hardware.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As sadas devem ser associadas a nomes para facilitar a programao e //futuras alteraes do hardware. #bit rs = porte.0 // via do lcd que sinaliza recepo de dados ou comando #bit enable = porte.1 // enable do lcd /* * * * * * * * * * * * * Funo * * * * * * * * * * * * escr_mem_serial () { i2c_start(); i2c_write(ctrl_escr); i2c_write(end_low); i2c_write(dado); i2c_stop(); delay_ms(10); } /* * * * * * * * * * * * * Funo * * * * * * * * * * * * 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 * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Condio de incio // Envia o byte de controle de leitura // Envia endereo baixo // Escreve dado na EPROM // Condio de parada // espera a gravao estar completa * * * * * * * * * * * * * * * * * * * * * * * * * * para leitura na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Condio de incio // Envia o byte de controle de leitura // Envia endereo baixo // Nova condio de incio // Envia o byte de controle de leitura // l o dado armazenado na EPROM // Condio de parada

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

110 Linguagem C para PIC

* Funo 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); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 mnimo 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 mnimo 40 microsegundos

// limpa lcd

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo de inicializao 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

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Funo 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 endereo, seleciona nova posio 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 endereo, seleciona nova posio delay_ms(100); // delay de 100 ms }while (end_low != 0); // fim da transmisso 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 recepo 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 transmisso 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 } } }

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes 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(); // configurao da direo 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 endereo inicial coleta_dados(); // executa funo de coleta de dados } if (tarefa == transmite_para_pc)// inicia transmisso de dados para o PC ? { end_low = 0; // sim, carrega endereo inicial tx_dados_pc(); // executa funo de transmisso de dados } if (tarefa == parar_coleta) // cancela coleta de dados ? { end_low = 0; // sim, carrega endereo 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 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Mude a rotina de coleta de dados para que seja armazenado na EEPROM um valor de 0 5V e no um valor de 0 a 255. Implemente a regra de trs necessria. 2. Altere a configurao do A/D para que ele retorne os 10 bits do resultado da converso e salve este dado na EEPROM.

114 Linguagem C para PIC

1.64 - Anotaes

Linguagem C para PIC

115

Recursos Avanados: Exemplo 10 Funes Matemticas


1.65 - Recursos do Livro
Para o bom entendimento deste exemplo so necessrios os conhecimentos adquiridos no exemplo 1 e mais, funes matemticas do compilador (cap.11.1 pg 175 do livro Programao em C).

1.66 - Lgica do exemplo


A elaborao deste exemplo foi pensando na demonstrao das funes matemticas, nele veremos o microcontrolador realizando o calculo do seno de 0 a 2, um software para PC foi elaborado para coletar os clculos realizas e plotar os clculos na tela do PC. Outras funes podem ser visualizadas, bastando para isso alterar a funo matemtica de nosso programa.

116 Linguagem C para PIC

1.67 - Esquema Eltrico

+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

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 varivel X=0

NO 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 varivel X X = x + 0,01

118 Linguagem C para PIC

1.69 - Cdigo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programao em C - Recursos Avanados de programao * * Exemplo 10 * * * * CENTRO DE CAPACITAO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: cursos@labtools.com.br * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * // // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrio geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Este software foi desenvolvido para mostrar a implementao de funes matemticas, 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 opes de configurao para perifricos * * * * * * * * * * * * * * * * * * * * * */ *

/* * * * * * * * * * * * * * * * * Definio * das funes * * * * * * * * * * * * * * * * #include <16f877A.h> #device adc=10

// microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Carrega bibliteca Matemtica * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <math.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes para gravao * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configurao dos fusveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definies para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurao da Usart * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao das variveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco esto definidas as variveis globais do programa. float y; float x; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de constantes facilita a programao e a manuteno. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declarao dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definio de flags ajuda na programao e economiza memria RAM. //Este programa no utiliza nenhum flag de usurio

Linguagem C para PIC

119

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definio e inicializao 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 programao do hardware. * * */ e

/* * * * * * * * * * * * * * * * * * * * * // As entradas devem //futuras alteraes

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // AS SADAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAO //FUTURAS ALTERAES DO HARDWARE.

* * */ E

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuraes do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); // desliga as entradas analgicas 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; // configurao da direo 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 funo 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 - Exerccios Propostos


Agora que o exemplo j foi estudado e esclarecido, aproveite para gerar novos problemas e solues, seguindo os exerccios propostos: 1. Altere a funo matemtica para que o PIC calcule o co-seno. 2. Altere a funo matemtica para que o PIC calcule o log de um nmero.

Linguagem C para PIC

121

1.72 - Anotaes

122 Linguagem C para PIC

Você também pode gostar