apostila linguagem c para pic

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

Upload: roger-gomes

Post on 05-Jul-2015

810 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Apostila Linguagem C Para PIC

Curso de

Linguagem C

Rinaldo Câmara Gonçalves

Labtools – Mosaico Didactic Division Revisão 2

Page 2: Apostila Linguagem C Para PIC
Page 3: Apostila Linguagem C Para PIC

Linguagem C para PIC 3

Sumário

SUMÁRIO.....................................................................................................................................................................3

RECURSOS BÁSICOS: EXEMPLO 1 BOTÃO E LED............................................................................................5

RECURSOS DO LIVRO ..................................................................................................................................................5

LÓGICA DO EXEMPLO ...................................................................................................................................................5

ESQUEMA ELÉTRICO....................................................................................................................................................6

FLUXOGRAMA..............................................................................................................................................................7

CÓDIGO ......................................................................................................................................................................8

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................10

ANOTAÇÕES..............................................................................................................................................................11

RECURSOS BÁSICOS: EXEMPLO 2 PISCA – PISCA VARIÁVEL .....................................................................13

RECURSOS DO LIVRO ................................................................................................................................................13

LÓGICA DO EXEMPLO .................................................................................................................................................13

ESQUEMA ELÉTRICO..................................................................................................................................................14

FLUXOGRAMA............................................................................................................................................................15

CÓDIGO ....................................................................................................................................................................16

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................18

ANOTAÇÕES..............................................................................................................................................................19

RECURSOS BÁSICOS: EXEMPLO 3 CONTADOR HEXADECIMAL ..................................................................20

RECURSOS DO LIVRO ................................................................................................................................................20

LÓGICA DO EXEMPLO .................................................................................................................................................20

ESQUEMA ELÉTRICO..................................................................................................................................................21

FLUXOGRAMA............................................................................................................................................................22

CÓDIGO ....................................................................................................................................................................25

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................28

ANOTAÇÕES..............................................................................................................................................................29

RECURSOS AVANÇADOS: EXEMPLO 4 MAXIMIZAÇÃO DE PINOS DE I/O...................................................30

RECURSOS DO LIVRO ................................................................................................................................................30

LÓGICA DO EXEMPLO .................................................................................................................................................30

ESQUEMA ELÉTRICO..................................................................................................................................................31

FLUXOGRAMA............................................................................................................................................................32

CÓDIGO ....................................................................................................................................................................36

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................40

ANOTAÇÕES..............................................................................................................................................................41

RECURSOS AVANÇADOS: EXEMPLO 5 VARREDURA DE DISPLAY.............................................................42

RECURSOS DO LIVRO ................................................................................................................................................42

LÓGICA DO EXEMPLO .................................................................................................................................................42

ESQUEMA ELÉTRICO..................................................................................................................................................44

FLUXOGRAMA............................................................................................................................................................45

CÓDIGO ....................................................................................................................................................................50

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................57

ANOTAÇÕES..............................................................................................................................................................58

RECURSOS AVANÇADOS: EXEMPLO 6 CONTROLE DO LCD............................................................................59

RECURSOS DO LIVRO ................................................................................................................................................59

LÓGICA DO EXEMPLO .................................................................................................................................................59

ESQUEMA ELÉTRICO..................................................................................................................................................60

FLUXOGRAMA............................................................................................................................................................61

CÓDIGO ....................................................................................................................................................................68

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................76

ANOTAÇÕES..............................................................................................................................................................77

RECURSOS AVANÇADOS: EXEMPLO 7 CONVERSOR ANALÓGICO DIGITAL..............................................78

RECURSOS DO LIVRO ................................................................................................................................................78

LÓGICA DO EXEMPLO .................................................................................................................................................78

Page 4: Apostila Linguagem C Para PIC

Linguagem C para PIC 4

ESQUEMA ELÉTRICO..................................................................................................................................................79

FLUXOGRAMA............................................................................................................................................................80

CÓDIGO ....................................................................................................................................................................82

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................86

ANOTAÇÕES..............................................................................................................................................................87

RECURSOS AVANÇADOS: EXEMPLO 8 CONTROLE DO PWM E EEPROM INTERNA..................................88

RECURSOS DO LIVRO ................................................................................................................................................88

LÓGICA DO EXEMPLO .................................................................................................................................................88

ESQUEMA ELÉTRICO..................................................................................................................................................89

FLUXOGRAMA............................................................................................................................................................90

CÓDIGO ....................................................................................................................................................................93

EXERCÍCIOS PROPOSTOS ..........................................................................................................................................99

ANOTAÇÕES............................................................................................................................................................100

RECURSOS AVANÇADOS: EXEMPLO 9 COLETOR DE DADOS ....................................................................101

RECURSOS DO LIVRO ..............................................................................................................................................101

LÓGICA DO EXEMPLO ...............................................................................................................................................101

ESQUEMA ELÉTRICO................................................................................................................................................102

FLUXOGRAMA..........................................................................................................................................................103

CÓDIGO ..................................................................................................................................................................109

EXERCÍCIOS PROPOSTOS ........................................................................................................................................114

ANOTAÇÕES............................................................................................................................................................115

RECURSOS AVANÇADOS: EXEMPLO 10 FUNÇÕES MATEMÁTICAS..............................................................116

RECURSOS DO LIVRO ..............................................................................................................................................116

LÓGICA DO EXEMPLO ...............................................................................................................................................116

ESQUEMA ELÉTRICO................................................................................................................................................117

FLUXOGRAMA..........................................................................................................................................................118

CÓDIGO .................................................................................................................................................................119

EXERCÍCIOS PROPOSTOS ........................................................................................................................................121

ANOTAÇÕES............................................................................................................................................................122

Page 5: Apostila Linguagem C Para PIC

Linguagem C para PIC 5

Recursos Básicos: Exemplo 1 Botão e Led 1.1 - Recursos do Livro

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

1.2 - Lógica do exemplo Nosso exemplo será composto de um programa capaz de ler um botão e controlar um led. Com

o botão S1 pressionado o led L2 acende, com o botão S1 liberado o led L2 apaga. Veremos os primeiros comandos para controle de fluxo de um programa e como ler uma entrada

e acionar uma saída, fundamental já que estamos trabalhando com um microcontrolador. Neste exemplo você verá o comando WHILE, (Faça enquanto for verdadeiro) sendo utilizado

para o controle de fluxo de nossa rotina principal, forçando um loop infinito. O comando IF ELSE, (Se verdadeiro {comando}, Se falso {comando}), realiza o teste do

botão e determina o caminho a ser seguido, se acende ou apaga o led. Caso o botão esteja pressionado o teste determina que o led deve acender, caso contrário o led será apagado. Para o teste do botão está sendo utilizado o operando “!” (NOT), para botão pressionado temos nível lógico zero no pino de I/O, neste caso o teste com o comando IF será verdadeiro para botão pressionado e falso para botão liberado.

Page 6: Apostila Linguagem C Para PIC

Linguagem C para PIC 6

1.3 - Esquema Elétrico

+5V

+5V

+5V

+5V

S1

RB0

10K

RB1

330R

RESET10K

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

MC1

4MHz

L2

16F877A

Page 7: Apostila Linguagem C Para PIC

Linguagem C para PIC 7

1.4 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

WATCHDOG, PRESCALER.

LIMPA WATCHDOG

BOTÃO S1PRESS.?

NÃO SIM

APAGA LED L2 ACENDE LED L2

A

A

Page 8: Apostila Linguagem C Para PIC

Linguagem C para PIC 8

1.5 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 1 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este software está preparado para demonstrar o controle dos pinos de I/O // este primeiro programa demonstrará o estado de um botão por meio de um led. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição das variáveis internas do PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. //Este programa não utiliza nenhuma constante de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08 #byte porte = 0x09

Page 9: Apostila Linguagem C Para PIC

Linguagem C para PIC 9

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit botao = portb.0 // Estado do botão // 1 -> Liberado // 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do Hardware. #bit led = portb.1 // Led correspondente ao botão // 1 -> Led ligado // 0 -> Led desligado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () { setup_counters(RTCC_INTERNAL, WDT_2304MS); set_tris_a(0b11111111); // configuração dos pinos de I/O set_tris_b(0b11111101); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111);

porta=0x00; // limpa porta portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0x00; // limpa portd porte=0x00; // limpa porte /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); if(!botao) // testa botão { led = 1; // Se botão = 0, então led = 1 } else led=0; // caso contrário, led = 0 } // FIM DO PROGRAMA }

1.6 -

Page 10: Apostila Linguagem C Para PIC

Linguagem C para PIC 10

1.7 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Utilize as funções do Compilador para controlar o Led, OUTPUT_HIGH e OUTPUT_LOW. 2. Altere a lógica do programa para que o led acenda com o botão liberado e apague com o

botão pressionado. 3. Troque o pino de I/O que controla o botão, por exemplo, utilize o pino RB3. 4. Com o botão pressionado acenda o led 2 e apague o led 3, para o botão liberado apague o

led 2 e acenda o led 3.

Page 11: Apostila Linguagem C Para PIC

Linguagem C para PIC 11

1.8 - Anotações

Page 12: Apostila Linguagem C Para PIC
Page 13: Apostila Linguagem C Para PIC

Linguagem C para PIC 13

Recursos Básicos: Exemplo 2 Pisca – Pisca Variável 1.9 - Recursos do Livro

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

1.10 - Lógica do exemplo A finalidade de nosso exemplo é demonstrar a inversão de portas e a utilização da função de

delay da Linguagem C. Através dos botões S1 e S2, Up e Down é possível ajustar a freqüência de oscilação dos Leds 3

e 4 da placa McLab2. As constantes min e max determinam os limites, máximos e mínimos de ajuste da freqüência de

oscilação. Para a inversão das portas está sendo utilizado o operador lógico “~”, (NOT, complemento de 1),

com este operando estaremos invertendo bit a bit o conteúdo do registrador portb. A função delay_ms gera um atraso de milisegundos usando o ciclo de máquina, ou seja, o

programa fica travado nesta função até o tempo desejado. O camando For (inicialização, teste condicional, incremento) é utilizado para controle do laço

da rotina de delay, definindo a quantidades de vezes que o laço será executado, nesta rotina não utilizaremos a opção de inicialização do comando For, sendo a mesma executada fora do laço.

Page 14: Apostila Linguagem C Para PIC

Linguagem C para PIC 14

1.11 - Esquema Elétrico

+5V

+5V

+5V

+5V

S1

RB0

10K

+5V

S2

RB1

10K

RB2

330R

RB3

330R

RESET10K

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

MC1

4MHz

L3 L4

16F877A

Page 15: Apostila Linguagem C Para PIC

Linguagem C para PIC 15

1.12 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

WATCHDOG, PRESCALER.

INICIALIZA PORTB COM0X0F

DELAY (10MS)

LIMPA WATCHDOG

COMPLEMENTA PORTB

BOTÃO S1PRESS.?

NÃO SIM

INCREMENTA TEMPO

TEMPO = MAX?

NÃO

BOTÃO S2PRESS.?

SIM

A

A

DECREMENTA TEMPO

TEMPO = MIN?

NÃO

SIMNÃO

SIM

LAÇO FOR

SIM

B

BNÃO

ROTINA DE DELAY

CARREGA A VARIÁVELCONTADOR COM O VALOR

DA VARIÁVEL TEMPO

0≠CONTADOR

Page 16: Apostila Linguagem C Para PIC

Linguagem C para PIC 16

1.13 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 2 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este software demonstrará a utilização da função de delay e a inversão de portas //a frequência de oscilação dos leds é controlada pelos botões S1 (UP) e S2 (DOWN). /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição das variáveis internas do PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) // diretiva para o uso da função delay /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int contador = 0 ; int tempo = 9; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. //Este programa não utiliza constantes #define max 255 // Limite de ajuste do tempo #define min 10 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08

Page 17: Apostila Linguagem C Para PIC

Linguagem C para PIC 17

#byte porte = 0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit botao_0 = portb.0 // Estado do botão_0 // 1 -> Liberado // 0 -> Pressionado #bit botao_1 = portb.1 // Estado do botão_1 // 1 -> Liberado

// 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () { setup_counters(rtcc_internal,wdt_2304ms); set_tris_a(0b11111111); set_tris_b(0b11110011); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta = 0x00; portb = 0x0f; // carrega portb com valor inicial portc = 0x00; portd = 0x00; porte = 0x00; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); portb = ~portb; // complemanta o portb if (!botao_0) // O botão_0 foi pressionado? { if (tempo != max) // sim, tempo é diferente de max? { tempo = tempo + 1; // não, incrementa tempo } } // botão_0 liberado, testa botão 1 if (!botao_1) // O botão 1 foi pressionado ? { if (tempo != min) // sim, tempo é diferente de min? { tempo = tempo - 1; // não, decrementa tempo } } // botão_1 liberado contador = tempo; // carrega contador for (;contador!=0; contador--) // contador é diferente de 0? se sim

// decrementa contador e executa o comando delay_ms(10); // comando: delay de 10 milisegundos. } } // FIM DO PROGRAMA

Page 18: Apostila Linguagem C Para PIC

Linguagem C para PIC 18

1.14 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Implemente a inversão de portas para que o led 3 e o led 4 pisquem alternadamente. 2. Utilize a forma reduzida para incrementar e decrementar a variável tempo. 3. Troque a função delay_ms por delay_us e ajuste as constantes para obter o mesmo ajuste de

freqüência. 4. Substitua o comando For pelo comando While.

Page 19: Apostila Linguagem C Para PIC

Linguagem C para PIC 19

1.15 - Anotações

Page 20: Apostila Linguagem C Para PIC

Linguagem C para PIC 20

Recursos Básicos: Exemplo 3 Contador Hexadecimal

1.16 - Recursos do Livro Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos nos

exemplos anteriores e tabela de constante (cap.12.21 pág. 309 do livro Programação em C).

1.17 - Lógica do exemplo Através dos botões S1 e S2 o contador será incrementado ou decrementado, e o seu valor

mostrado no display de sete segmentos ds4. A finalidade de nosso exemplo é demonstrar a implementação de tabelas utilizando a memória

de programa, sendo está tabela uma matriz unidimensional, nossa tabela fará a conversão de BCD para sete segmentos, realizando a função de um circuito decodificador.

Para o devido tratamento dos botões, neste exemplo foi implementada uma rotina de filtro para cada botão evitando o problema de debouncing, além do filtro foi criado um flag, para cada botão, que tem a função de indicar se a tecla está pressionada ou liberada. Desta forma para que o contador seja incrementado ou decrementado o botão deve ser pressionado e depois liberado.

A variável contador será utilizada como indexador da tabela de constante, assim sendo para o contador igual à zero, será retornado o código de sete segmentos para o número zero e assim por diante.

Page 21: Apostila Linguagem C Para PIC

Linguagem C para PIC 21

1.18 - Esquema Elétrico

MC1

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

+5V

+5V

+5V

RESET

DS4abcdefg

Dp

a

c

b

d

e

f g

Dp

RB0 RB1

+5V

10K

+5V

10K

10K

S1 S2

4,7K

BC337

4MHz

220R

220R

PIC16F877PIC16F877

16F877A

Page 22: Apostila Linguagem C Para PIC

Linguagem C para PIC 22

1.19 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

WATCHDOG, PRESCALER.

INICIALIZA PORTB COM0X10

LIMPA WATCHDOG

B

A

Page 23: Apostila Linguagem C Para PIC

Linguagem C para PIC 23

BOTÃO S1PRESS.?

NÃO SIM

O botão já estavapressionado ?

NÃO

NÃO

A

Decrementa o Filtro

SIM

C

SIM

Marca Botão pressionado

SIM

Incrementa o contadorConsulta tabela de conversão e

atualiza o display

NÃO

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

C

?MaxContador ≠

?0≠Filtro

Page 24: Apostila Linguagem C Para PIC

Linguagem C para PIC 24

BOTÃO S2PRESS.?

NÃO SIM

O Botão já estavapressionado ?

NÃO

NÃO

C

Decrementa o Filtro

SIM

B

SIM

Marca Botão pressionado

SIM

Decrementa o contadorConsulta tabela de conversão e

atualiza o display

NÃO

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

B

?0≠Filtro

?MinContador ≠

Page 25: Apostila Linguagem C Para PIC

Linguagem C para PIC 25

1.20 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 3 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Contador hexadecimal que utiliza dois botões para incrementar e decrementar // o valor da variável "contador". O contador está limitado pelas constantes min e max. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 400 // tamanho do filtro #define min 0 // valor mínimo para o contador #define max 15 // valor máximo para o contador /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int contador=min; // inicia contador com mínimo long int filtro0=t_filtro; // inicia filtro do bot1 long int filtro1=t_filtro; // inicia filtro do bot2 int flags=0; // limpa os flags /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. #bit bt_UP_press = flags.0 #bit bt_DOWN_press = flags.1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e)

Page 26: Apostila Linguagem C Para PIC

Linguagem C para PIC 26

#byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08 #byte porte = 0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit botao_UP = portb.0 // Estado do botão UP // 1 -> Liberado // 0 -> Pressionado #bit botao_DOWN = portb.1 // Estado do botão DOWN

// 1 -> Liberado // 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e // futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tabela de Valores * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ byte const tabela[16] = { //PGFEDCBA ; POSIÇÃO RELATIVA AOS SEGMENTOS 0b00111111, // 0H - 0 0b00000110, // 1H - 1 0b01011011, // 2H - 2 0b01001111, // 3H - 3 0b01100110, // 4H - 4 0b01101101, // 5H - 5 0b01111101, // 6H - 6 0b00000111, // 7H - 7 0b01111111, // 8H - 8 0b01101111, // 9H - 9 0b01110111, // AH - A 0b01111100, // BH - B 0b00111001, // CH - C 0b01011110, // DH - D 0b01111001, // EH - E 0b01110001}; // FH - F /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_counters(rtcc_internal, wdt_2304ms); set_tris_a(0b11111111); set_tris_b(0b11101111); set_tris_c(0b11111111); set_tris_d(0b00000000); set_tris_e(0b00000111); porta = 0x00; portb=(0b00010000); // seleciona display ds4 portc = 0x00; portd = (tabela[contador]); // mostra no display valor inicial do contador porte = 0x00; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 27: Apostila Linguagem C Para PIC

Linguagem C para PIC 27

* Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao_UP) // O botão UP está pressionado ? { // sim, if (!(bt_UP_press)) // O botão UP já foi tratato ? { // não. if (filtro0 !=0) // Fim do filtro do botão UP ? { filtro0--; // Não, então decrementa o filtro } else // Sim, Faz a ação do botão { bt_UP_press = 1; // Marca que o botão está pressionado if (contador != max) { contador++; // incrementa o contador portd = (tabela[contador]); // consulta tabela, atualiza // display } } } } else { // botão 0 liberado filtro0 = t_filtro; // inicia o filtro do botão 0 bt_UP_press = 0; // marca que o botão foi liberado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao_DOWN) // testa botão DOWN { // botão DOWN pressionado if (!(bt_DOWN_press)) // o botão DOWN já foi tratato ? { // não if (filtro1 !=0) // Fim do filtro do botão DOWN ? { filtro1--; // não, então decrementa o filtro

} else // SIM. Faz a ação do botão { bt_DOWN_press = 1; // marca que o botão está pressionado if (contador != min) { contador--; // decrementa o contador portd = (tabela[contador]);// consulta tabela, atualiza // display } } } } else { // botão 1 liberado filtro1 = t_filtro; // inicia o filtro do botão 1 bt_DOWN_press = 0; // marca que o botão foi liberado } } }

Page 28: Apostila Linguagem C Para PIC

Linguagem C para PIC 28

1.21 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Modifique o programa para que o contador conte de 1 a 5. 2. Implemente um botão para reset do contador. 3. Altere a tabela para que as posições de A a F da tabela apaguem o display. 4. Mude a contagem do dsp4 para o display dsp3.

Page 29: Apostila Linguagem C Para PIC

Linguagem C para PIC 29

1.22 - Anotações

Page 30: Apostila Linguagem C Para PIC

Linguagem C para PIC 30

Recursos Avançados: Exemplo 4 Maximização de Pinos de I/O 1.23 - Recursos do Livro

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

1.24 - Lógica do exemplo Nosso exemplo será composto de um programa capaz de ler quatro botões e tocar o buzzer com

uma freqüência diferente para cada combinação de botões. Para cada botão existe um led ligado no mesmo pino, que será utilizado para indicar os botões pressionados no momento. Utilizaremos os timers e duas interrupções para controlarmos a freqüência de leitura dos botões e a freqüência do buzzer:

• Timer 0: controlará a freqüência de varredura dos botões;

• Timer 2: controlará a freqüência do som. O som será feito excitando o buzzer com uma onda quadrada de freqüência variável. Variaremos esta freqüência alterando o valor de PR2, que controla o estouro deste timer.

Desta forma, nosso programa principal será um loop infinito sem efeito algum. Somente ficaremos esperando o acontecimento das interrupções.

Para a varredura dos botões ajustaremos a interrupção de TMR0 para aproximadamente 500Hz:

Ciclo de Máq. Prescale Conta TMR0 Auxiliar Período Freqüência 1 µs 8 256 - 2048 µs 488 Hz

Além disso, o sistema possui um filtro, regulado pela constante FILTRO_BOTAO, para evitar o

debounce da tecla. Este filtro garante que a tecla fique pressionada pelo tempo de FILTRO_BOTAO x 2048µs.

Quanto à freqüência do buzzer, esta será controlada por TMR2. Calibramos os valores de pre e postscale para que a freqüência da interrupção do TMR2 varie entre 100Hz e 2kHz, com a variação de PR2 entre 16 e 240:

Ciclo de Máq. Prescale Postscale PR2 Período Freqüência

1 µs 16 1 16 256 µs 3906 Hz 1 µs 16 1 240 3840 µs 260 Hz

Para facilitar a implementação, a cada interrupção inverteremos o estado do pino de

acionamento do buzzer. Desta forma, a freqüência deste será equivalente à metade da freqüência da interrupção do TMR2.

O Livro Conectando o PIC, possui um cápitulo dedicado a este assunto.

Page 31: Apostila Linguagem C Para PIC

Linguagem C para PIC 31

1.25 - Esquema Elétrico

+5V

+5V

+5V

+5V

S1

RB0

10K

10K

330R

+5V

S2

RB1

10K

10K

330R

+5V

S3

RB2

10K

10K

330R

+5V

S4

RB3

10K

10K

330R

RESET10K

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2

VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0

RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

MC1

BUZZER

4MHz

L1 L2 L3 L4

16F877A

Page 32: Apostila Linguagem C Para PIC

Linguagem C para PIC 32

1.26 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

WATCHDOG, PRESCALER.

LIGA AS INTERRUPÇÕES

LIMPA WATCHDOG

Page 33: Apostila Linguagem C Para PIC

Linguagem C para PIC 33

INT DE TMR0?NÃO SIM

SAÍDA DO BUZZERESTÁ LIGADA?

DESLIGA A SAÍDA DOBUZZER

SIMNÃO

INTERRUPÇÕES

Trata TMR0Trata TMR2

TRATA TMR2

LIGA A SAÍDA DO BUZZER

FIM DA INTERRUPÇÃO

Page 34: Apostila Linguagem C Para PIC

Linguagem C para PIC 34

TRATA TMR0

Convetre pinos dos botões ementradas

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

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

Converte pinos dos botões emsaída

Marca flag de botãopressionado

Botão S1 PRESS ?

SIM

NÃO

CHECA BOTÃO S1

Reinicia Filtro

Limpa Flag de botãopressionado (Status Leds)

Fim do Filtro ?

SIM

CHECA BOTÃO S2

NÃO

CHECA BOTÃO S3

CHECA BOTÃO S4

A

Page 35: Apostila Linguagem C Para PIC

Linguagem C para PIC 35

Atualiza leds conforme botõespressionados

Consulta tabela conformeconbinação de botões

pressionados

Algum botão pressionado ?

SIM

NÃO

Inicializa PER com 255

Deliga interrupção de TMR2 Inicializa TMR2

Liga Interrupção de TMR2

A

Desliga a saída do Buzzer

FIM DA INTERRUPÇÃO

AÇÃO DOS BOTÕES

Page 36: Apostila Linguagem C Para PIC

Linguagem C para PIC 36

1.27 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 4 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este software está preparado para ler quatro botões e tocar o buzzer com //duração variavel conforme a tecla pressionada, além de acender o led //indicando a última tecla pressionada. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 20 // tamanho do filtro /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int status_botoes = 0; // armazena o estado lógico dos botões int status_leds = 0; // atualiza leds conforme o botão pressionado int per = 0; // limitador de contagem do Timer2 int filtro1 = t_filtro; // inicia filtro do botao1 int filtro2 = t_filtro; // inicia filtro do botao2 int filtro3 = t_filtro; // inicia filtro do botao3 int filtro4 = t_filtro; // inicia filtro do botao4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08 #byte porte = 0x09

Page 37: Apostila Linguagem C Para PIC

Linguagem C para PIC 37

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit botao1 = status_botoes.0 // Estado do botão 1 // 1 -> Liberado // 0 -> Pressionado #bit botao2 = status_botoes.1 // Estado do botão 2 // 1 -> Liberado // 0 -> Pressionado #bit botao3 = status_botoes.2// Estado do botão 3 // 1 -> Liberado // 0 -> Pressionado #bit botao4 = status_botoes.3 // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #bit botao1_press = status_leds.0 #bit botao2_press = status_leds.1 #bit botao3_press = status_leds.2 #bit botao4_press = status_leds.3 #bit buzzer = porta.5 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tabela de Valores * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ byte const tabela[16] = {255,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // A rotina principal simplesmente limpa o WDT, pois toda a lógica do // programa é tratada dentro das interrupções. void main() { setup_adc_ports (no_analogs); setup_counters(rtcc_internal , rtcc_div_8); setup_timer_2 (t2_div_by_16,per,1); set_tris_a(0b11011111); set_tris_b(0b11110000); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111);

porta=(0b00000000); portb=(0b00000000); portc=(0b00000000); portd=(0b00000000); porte=(0b00000000);

enable_interrupts(GLOBAL); enable_interrupts(INT_RTCC); #priority timer0,timer2 // prioridade para a int de trm0

Page 38: Apostila Linguagem C Para PIC

Linguagem C para PIC 38

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 2048us. // O filtro dos botões tem duração de 40ms (2048us x 20) e são decrementados a cada // interrupção. // Esta interrupção é responsável por converter os pinos dos botões em entrada, salvar // a condição dos botões em variável temporária e converter os pinos em saída // novamente. #int_rtcc void trata_int_tmr0() { set_tris_b(0b00001111); // configura os pinos como entrada para

// testar os botões delay_cycles(4); // aguarda 4 ciclos de máquina para a // estabilização do portb status_botoes = portb; // lê o status dos botoes, salva em variável // temporária set_tris_b(0b00000000); // configura os pinos como saída para // controle dos leds /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) // testa botão 1 { // botão 1 está pressionado ? filtro1--; // Sim, então decrementa o filtro if (filtro1 == 0) // acabou o filtro do botão 1 ? { botao1_press = 1; // marca que o botão está pressionado } } else { // botão 1 liberado filtro1 = t_filtro; // inicia o filtro do botão 1 botao1_press = 0; // marca que o botão foi liberado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao2) // testa botão 2 { // botão 2 está pressionado ? filtro2--; // Sim, então decrementa o filtro if (filtro2 == 0) // fim do filtro do botão 2 ? { botao2_press = 1; // marca que o botão está pressionado } } else { // botão 2 liberado filtro2 = t_filtro; // inicia o filtro do botão 2 botao2_press = 0; // marca que o botão foi liberado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao3) // testa botão 3 { // botão 3 está pressionado ?

Page 39: Apostila Linguagem C Para PIC

Linguagem C para PIC 39

filtro3--; // Sim, então decrementa o filtro if (filtro3 == 0) // fim do filtro do botão 3 ? { botao3_press = 1; // marca que o botão está pressionado } } else { // botão 3 liberado filtro3 = t_filtro; // inicia o filtro do botão 3 botao3_press = 0; // marca que o botão foi liberado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao4) // testa botão 4 { // botão 4 está pressionado ? filtro4--; // Sim, então decrementa o filtro if (filtro4 == 0) // fim do filtro do botão 4 ? { botao4_press = 1; // marca que o botão está pressionado } } else { // botão 4 liberado filtro4 = t_filtro; // inicia o filtro do botão 4 botao4_press = 0; // marca que o botão foi liberado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Atualiza Leds conforme botões pressionados * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ portb = status_leds; // atualiza os leds if (status_leds == 0) { per = 0xff; setup_timer_2 (t2_div_by_16,per,1); disable_interrupts (INT_TIMER2); buzzer = 0; } else { per = (tabela[status_leds]);// consulta tabela e inicializa timer2. setup_timer_2 (t2_div_by_16,per,1); enable_interrupts (INT_TIMER2); // habilita interrupção de timer2. } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Está interrupção só irá ocorrer quando alguma tecla estiver pressionada, // o periodo de ocorrência depende do botão ou da conbinação de botões pressionados, // ela irá inverter o pino de I/O do buzzer a cada interrupção. #int_timer2 void trata_int_tmr2() { if (buzzer != 0) // o buzzer está ligado ? { buzzer = 0; // sim, então desliga } else { buzzer = 1; // não, então liga } }

Page 40: Apostila Linguagem C Para PIC

Linguagem C para PIC 40

1.28 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Utilize as funções disponíveis do Compilador para inverter o estado do buzzer. 2. Modifique o controle dos leds, os botões pares controlam os leds impares e os botões

impares controlam os leds pares, conforme a tabela abaixo. Botão 1 Botão 2 Botão 3 Botão 4 Led 2 Led 1 Led 4 Led3

Page 41: Apostila Linguagem C Para PIC

Linguagem C para PIC 41

1.29 - Anotações

Page 42: Apostila Linguagem C Para PIC

Linguagem C para PIC 42

Recursos Avançados: Exemplo 5 Varredura de Display 1.30 - Recursos do Livro

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

1.31 - Lógica do exemplo O exemplo desenvolvido para esta aula faz muito mais que simplesmente implementar a

varredura dos displays. Trata-se de um contador regressivo de segundos, ou seja, um temporizador capaz de contar até 9.999 segundos.

Para isso, utilizaremos os displays para indicar o valor atual do temporizador. A primeira tecla (S1) não possui nenhuma função. Por outro lado, o led relacionado a ela (L1) será utilizado para indicar o estado do temporizador:

L1 Descrição

Aceso Temporizador em contagem regressiva Apagado Temporizador paralisado

Os demais botões apresentam as funções de controle do temporizador:

Botão Descrição S2 Incrementa o valor inicial em 1 segundo S3 Decrementa o valor inicial em 1 segundo S4 Inicia e paralisa o temporizador

Os botões de incremento e decremento operam de forma rotativa, isto é, comutam

automaticamente entre 0000 e 9999. Outra característica destes botões é que eles executam suas funções repetidamente quando mantidos pressionados e só funcionam quando o temporizador está paralisado. Ao atingir o valor zero (0000) o temporizador é automaticamente paralisado, desligando-se o led indicativo (L1).

Para o sistema de varredura foram criadas 4 variáveis para armazenamento dos dígitos mostrados nos respectivos displays: UNIDADE, DEZENA, CENTENA e MILHAR. Estas variáveis representam o valor atual do temporizador e são incrementadas e decrementadas através dos botões.

Na verdade, os botões alteram diretamente o valor da unidade. A lógica do sistema compara este valor com os limites (0 e 9) para alterar ou não os demais dígitos.

A freqüência de varredura é controlada pela interrupção de Timer0. Ajustamos seus parâmetros para que a comutação entre displays (tempo da interrupção) seja de aproximadamente 4kHz:

Ciclo de Máq. Prescale Conta TMR0 Auxiliar Período Freqüência

1 µs 1 256 - 256 µs 3900 Hz

Page 43: Apostila Linguagem C Para PIC

Linguagem C para PIC 43

A freqüência de varredura será a freqüência de comutação dividida pelo número de displays, que no nosso caso será de aproximadamente 1kHz.

Dentro do tratamento da interrupção de TMR0 é desligado o display atual, carregado o valor do dígito correspondente ao display e ligado o display seguinte.

Quanto à contagem dos segundos, utilizamos a interrupção de Timer1 para esta finalidade. Veja os ajustes dos parâmetros para esta interrupção:

Ciclo de Máq. Prescale Conta TMR1 Auxiliar Período Freqüência

1 µs 8 62500 2 1.000.000 µs 1 Hz Para isso, configuramos o prescale de TMR1 em 1:8 e iniciamos o contador com o valor total

menos o desejado para a contagem (65.536 – 62.500). Desta maneira a interrupção acontecerá a cada 0,5 segundo. Para podermos contar 1 segundo foi criado uma variável auxiliar denominada DIVISOR_TMR1.

Cada vez que o sistema entrar na interrupção de TMR1 e o contador auxiliar (DIVISOR_TMR1) terminar, o tempo é decrementado, começando pela unidade e chegando até a milhar, se for necessário. Quando o tempo termina (0000) tanto o led quanto o TMR1 são desligado.

Neste exemplo está sendo utilizado o tratamento Manual de interrupções, neste modo nós devemos providenciar todo o código necessário para o tratamento da interrupção, tais como: salvar contexto, restaurar contexto, limpar os flags de indicação de interrupção e criar os registradores para as rotinas de salvar e restaurar contexto. A prioridade de tratamento da interrupção depende da seqüência de teste dos flags de int, que também é de responsabilidade do programador.

Para este tipo de tratamento estamos utilizando a diretiva #int global.

Page 44: Apostila Linguagem C Para PIC

Linguagem C para PIC 44

1.32 - Esquema Elétrico

MC1

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

+5V

+5V

+5V

RESET

DS4DS3DS2DS1abcdefg

Dp

Comum 4Comum 3Comum 2Comum 1

a

c

b

d

e

f g

Dp

a

c

b

d

e

f g

Dp

a

c

b

d

e

f g

Dp

a

c

b

d

e

f g

Dp

RB0

RB1 RB2 RB3

+5V

10K330R

+5V

10K

+5V

10K

10K

S2 S3 S4

4,7K 4,7K 4,7K 4,7K

BC337BC337BC337BC337

4MHz

220R

220R

L1

16F877A

Page 45: Apostila Linguagem C Para PIC

Linguagem C para PIC 45

1.33 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

WATCHDOG, PRESCALER.

Liga as interrupções

Limpa WATCHDOG

BOTÃO UP PRESS.?SIM

NÃO

Recarrega Filtro e turbo dasteclas

Configura Timer1

Trata Botão UP

BOTÃO DOWNPRESS.?

SIM

NÃO

Trata Botão Down

BOTÃO Start/StopPRESS.?

SIM

NÃO

Trata Botão Start/Stop

A

Page 46: Apostila Linguagem C Para PIC

Linguagem C para PIC 46

INT DE TMR0?NÃO SIM

Passou 1 segundo ?

SIM

NÃO

INTERRUPÇÕES

Decrementa Timer

Recarrega contador de int.

FIM DA INTERRUPÇÃO

Incrementa ponteiro de seleçãode Display, desliga display domilhar, consulta tabela deconversão para setesegmentos, liga display daunidade

Atualiza Display daUnidade?

Atualiza Display daDezena?

Incrementa ponteiro de seleçãode Display, desliga display daunidade, consulta tabela deconversão para setesegmentos, liga display dadezena

Atualiza Display daCentena?

Incrementa ponteiro de seleçãode Display, desliga display dadezena, consulta tabela deconversão para setesegmentos, liga display dacentena

Atualiza Display domilhar?

Zera ponteiro de seleção deDisplay, desliga display dacentena, consulta tabela deconversão para setesegmentos, liga display domilhar

FIM DA INTERRUPÇÃO

SIM

SIM

SIM

SIM

NÃO

NÃO

NÃO

NÃO

SWITCH CASE

Recarrega Timer1

decrementa contador de int.

Timer Chegou a zero?

Desliga led de indicação detimer operando

Desabilita interrupção deTimer1

NÃO

SIM

Page 47: Apostila Linguagem C Para PIC

Linguagem C para PIC 47

Trata Botão UP

Decrementa Turbo

Timer Ligado ?SIM

Decrementa Filtro

Fim do Filtro ?

SIM

Recarrega temporizador paraTurbo

NÃO

A

NÃO

Fim do Temporizadorpara Turbo do Botão?

Incrementa Timer

NÃO

Trata Botão DOWN

Decrementa Turbo

Timer Ligado ?SIM

Decrementa Filtro

Fim do Filtro ?

SIM

Recarrega temporizador paraTurbo

NÃO

A

NÃO

Fim do Temporizadorpara Turbo do Botão?

Decrementa Timer

NÃO

SIM SIM

Page 48: Apostila Linguagem C Para PIC

Linguagem C para PIC 48

Filtro terminou ?

NÃO

SIM

Acende Led de indicação deTimer ligado

Carrega Timer1

Apaga led de indicação deTimer ligado

Desabilita interrupção deTimer1

Carrega contador deinterrupções

A

Trata botão Start/Stop

Ação já foi executada ?

Timer ligado ?

SIM

NÃO

NÃO

SIM

Timer é igual a zero ?

NÃO

A

SIM

Habilita interrupção de Timer 1

Page 49: Apostila Linguagem C Para PIC

Linguagem C para PIC 49

Dezena = 10 ?

SIM

NÃO

Incrementa Timer

Unidade = 10 ?

centena = 10 ?

SIM

NÃO

NÃO

SIM

Incrementa unidade

Zera unidadeIncrementa dezena

Zera dezenaIncrementa centena

Zera centenaIncrementa milhar

Milhar = 10 ?NÃO

SIM

Zera milhar

Return

Dezena = 0XFF ?

SIM

NÃO

Decrementa Timer

Unidade = 0XFF ?

centena = 0XFF ?

SIM

NÃO

NÃO

SIM

Decrementa unidade

Unidade = 9Decrementa dezena

Dezena = 9Decrementa centena

Centena = 9Decrementa milhar

Milhar = 0XFF ?NÃO

SIM

Milhar = 9

Return

Page 50: Apostila Linguagem C Para PIC

Linguagem C para PIC 50

1.34 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 5 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi preparado para demonstrar o funcionamento do TIMER de // 16 bits do PIC (TMR1), da varredura de displays e do tratamento manual de int. // Consiste num temporizador de segundos. dois botões foram utilizados para // programar o tempo da contagem. Um outro botão foi utilizado para disparar // o contador. O temporizador consegue contar até 9999 segundos, de forma que // os 4 displays de 7 segmentos foram necessários. A contagem é regressiva. // um led indica que o temporizador está operando. Quando o sistema chega // a 0000 (ZERO) o led é desligado automaticamente. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 250 // tamanho do filtro #define turbo_tecla 60 #define delta_timer1 (65536 - 62500) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int display = 0 ; // atualiza os displays int contador = 2; // contador de interrupções de timer1 int filtro = t_filtro; // inicia filtro dos botões int turbo = 1; // inicia turbo das teclas int unidade = 9; // variável unidade do timer de 1 seg int dezena = 9; // variável dezena do timer de 1 seg int centena = 9; // variável centena do timer de 1 seg int milhar = 9; // variável milhar do timer de 1 seg static int W_TEMP; // variáveis para salvar contexto static int STATUS_TEMP; static int FSR_TEMP; static INT PCLATH_TEMP;

Page 51: Apostila Linguagem C Para PIC

Linguagem C para PIC 51

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta=0x05 #byte portb=0x06 #byte portc=0x07 #byte portd=0x08 #byte porte=0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição de SFR's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #bit tmr1if = 0x0c.0 // tmr1if é o bit 0 do sfr pir1 #bit t0if = 0x0b.2 // t0if é o bit 2 do sfr intcon #bit tmr1ie = 0x8c.0 // tmr1ie é o bit 0 do fsr pie1 #byte status = 0x03 // define endereço do reg de status #byte fsr = 0x04 // define endereço do reg de fsr #byte pclath = 0x0a // define endereço do reg de pclath /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit bt_up = portb.1 // Estado do botão up // 1 -> Liberado // 0 -> Pressionado #bit bt_down = portb.2 // Estado do botão down // 1 -> Liberado // 0 -> Pressionado #bit bt_start_stop = portb.3 // Estado do botão start_stop // 1 -> Liberado // 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #bit estado_timer = portb.0 // led de estado do timer // 1 -> timer contando // 0 -> timer parado #bit disp0 = portb.4 // seleção do display unidade (0) #bit disp1 = portb.5 // seleção do display dezena (1) #bit disp2 = portb.6 // seleção do display centena (2) #bit disp3 = portb.7 // seleção do display milhar (3)

Page 52: Apostila Linguagem C Para PIC

Linguagem C para PIC 52

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tabela de Valores * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ byte const converte[11] = { //PGFEDCBA POSIÇÃO RELATIVA AOS SEGMENTOS 0b00111111, // 0H - 0 0b00000110, // 1H - 1 0b01011011, // 2H - 2 0b01001111, // 3H - 3 0b01100110, // 4H - 4 0b01101101, // 5H - 5 0b01111101, // 6H - 6 0b00000111, // 7H - 7 0b01111111, // 8H - 8 0b01101111, // 9H - 9 0b00000000}; // blank /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de decremento do Timer * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ decrementa_timer() { unidade --; if (unidade == 0xff) { unidade = 9; dezena --; } if (dezena == 0xff) { dezena = 9; centena --; } if (centena == 0xff) { centena = 9; milhar --; } if (milhar == 0xff) { milhar = 9; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de incremento do Timer * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ incrementa_timer() { unidade ++; if (unidade == 10) { unidade = 0; dezena ++; } if (dezena == 10) { dezena = 0; centena ++; } if (centena == 10) { centena = 0; milhar ++; } if (milhar == 10) { milhar = 0; } }

Page 53: Apostila Linguagem C Para PIC

Linguagem C para PIC 53

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

Page 54: Apostila Linguagem C Para PIC

Linguagem C para PIC 54

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para salvar contexto * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ salva_contexto() { #asm MOVWF W_TEMP // SALVA REGISTRADOR DE TRABALHO E SWAPF STATUS,W // DE STATUS DURANTE O TRATAMENTO MOVWF STATUS_TEMP // DA INTERRUPÇÃO. MOVF FSR,W MOVWF FSR_TEMP // SALVA REGISTRADOR FSR MOVF PCLATH,W MOVWF PCLATH_TEMP // SALVA REGISTRADOR PCLATH CLRF PCLATH // LIMPA REGISTRADOR PCLATH, SELECIONA PAGINA 0 CLRF STATUS // LIMPA REGISTRADOR STATUS #endasm } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para restaurar contexto * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ restaura_contexto() { #asm MOVF PCLATH_TEMP,W MOVWF PCLATH // RECUPERA REG. PCLATH (PAGINAÇÃO) MOVF FSR_TEMP,W MOVWF FSR // RECUPERA REG. FSR (END. INDIRETO) SWAPF STATUS_TEMP,W MOVWF STATUS // RECUPERA REG. STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W // RECUPERA REG. WORK #endasm } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); setup_counters(rtcc_internal, wdt_2304ms); setup_timer_1 (t1_internal | t1_div_by_8); set_tris_a(0b11111111); set_tris_b(0b00001110); set_tris_c(0b11111111); set_tris_d(0b00000000); set_tris_e(0b00000111); porta=(0b00000000); portb=(0b00000000); portc=(0b00000000); portd=(0b00000000); porte=(0b00000000); enable_interrupts(INT_RTCC ); enable_interrupts(GLOBAL); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ loop: while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer

Page 55: Apostila Linguagem C Para PIC

Linguagem C para PIC 55

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de incremento (UP) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_up) // testa botão up { goto trata_up;// desvia para a rotina de incremento do timer } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de decremento (down) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_down) // testa botão down { goto trata_dowm;// desvia para a rotina de decremento do timer } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de Start / Stop * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!bt_start_stop) // testa botão start_stop { goto trata_start_stop; // desvia para a rotina para ligar ou

// desligar o timer } filtro = t_filtro; turbo = 1; } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * trata_up: if (estado_timer == 0) // o timer está parado? { filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? { turbo --; // decrementa o turbo da tecla if (turbo == 0) // sim, fim do turbo do botão ? { turbo = turbo_tecla; // carrega o turbo incrementa_timer(); // incrementa o timer } } } goto loop; //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * trata_dowm: if (estado_timer == 0) // o timer está parado? { filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? { turbo --; // decrementa o turbo da tecla if (turbo == 0) // sim, fim do turbo do botão ? { turbo = turbo_tecla; // carrega o turbo decrementa_timer(); // decrementa o timer } } } goto loop;

Page 56: Apostila Linguagem C Para PIC

Linguagem C para PIC 56

//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * trata_start_stop: if (filtro != 0) // o timer está parado? {

filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? { if (estado_timer != 0) // sim, o timer está ligado ? { estado_timer = 0; // indica timer parado tmr1ie = 0; // desliga o tratamento de interrupção de timer1 } else { if((unidade!=0)||(dezena!=0)||(centena!=0)||(milhar != 0))

// timer está zerado? { estado_timer = 1;// não, indica que o timer está contando contador = 2; // carrega contador auxiliar set_timer1(delta_timer1); // carrega timer 1 tmr1if = 0; // limpa flag de int tmr1 tmr1ie = 1; // liga o tratamento de interrupção de timer1 } } } } goto loop; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de Tratamento de interrupções * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Todo o tratamento de interrupção é feito manualmente. // As funções salva contexto e restaura contexto foram feitas em assembler // Observe que a prioridade das interrupções é realizada através do comando IF // e a ordem do teste determina a prioridade no tratamento da interrupção. #int_global Void trata_int() { salva_contexto();// salva os registradores antes do tratamento da int if (t0if) // É int de tmr0 ? { trata_tmr0(); // sim, trata tmr0 } else // não, { if (tmr1if) // É int de tmr1 ? { trata_tmr1(); // sim, trata tmr1 } } // não. restaura_contexto(); // restaura contexto e sai da int. }

Page 57: Apostila Linguagem C Para PIC

Linguagem C para PIC 57

1.35 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Mude a rotina para que o temporizador conte de forma crescente e desligue quando chegar a

zero. 2. Altere a rotina de temporização para que o timer seja decrementado a cada 1 minuto. 3. Mude a rotina do timer para que ele funcione como um cronômetro com um botão de start e

um de reset.

Page 58: Apostila Linguagem C Para PIC

Linguagem C para PIC 58

1.36 - Anotações

Page 59: Apostila Linguagem C Para PIC

Linguagem C para PIC 59

Recursos Avançados: Exemplo 6 Controle do LCD 1.37 - Recursos do Livro

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, controle do LCD (cap.12.7.2 pág. 310 do livro Programação em C).

1.38 - Lógica do exemplo Este exemplo foi criado para demonstrar a inicialização de LCD de 2 linhas por 16 caracteres

utilizando 8 vias de dados, e como enviar dados e comandos para o LCD. O exemplo controla o acionamento de leds e do ventilador através de um MENU, tecla S1, de

escolha de opções, onde será possível escolher as opções de ligar ou desligar através da tecla ENTER, tecla S2.

A escolha das telas será controlada pelo comando SWITCH do compilador C. Após o programa ser carregado a seguinte tela será visualizada no display:

S e l e c i o n e T a r e f a

P r e s s M e n u

Quando a tecla S1 é pressionada a mensagem é trocada indicando as opções de controle,

pressionando a tecla menu é possível escolher entre controle de leds e controle do ventilador. O controle selecionado é indicado por uma seta �.

� c t r d o s l e d s

c t r d o v e n t

Uma vez que a tela de controle foi escolhida, pressione a tecla enter para entrar na tela de

controle, de acordo com a tela selecionada poderemos visualizar as seguintes telas:

c t r d o s l e d s

O N > O F F

V e n t i l a d o r

O N > O F F

Na tela de controle, deve se pressionar enter para escolher a opção desejada, ON ou OFF,

quando a tecla for pressionada o símbolo “>” será deslocado para a condição desejada.

Page 60: Apostila Linguagem C Para PIC

Linguagem C para PIC 60

1.39 - Esquema Elétrico

MCLRRA0RA1

RA2

RA4RA5

RA3

RE1

RE0

RE2

VDDVSS

OSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7

RB6

RB4RB3

RB5

RB1

RB2

RB0

RD7RD6

RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

1011121314151617182324

3330292827222120192625

323140393837363534

+5V

+5V

+5V

RESET

LCD

DB0DB1DB2DB3DB4DB5DB6DB7

VDDVOVSS

RSENR/W

2

1

3

4

5

6

7

98

12

14

13

11

10

RSEN

10K

MC1

+5V

10K

RB0 RB1

RB2 RB3

+5V

10K

+5V

10K

S1 S2

RS

EN

4MHz

+Vcc

MIN

I VE

NT

ILA

DO

R

4,7K

1N4148

BC337

330R 330R

16F877A

L3 L4

Page 61: Apostila Linguagem C Para PIC

Linguagem C para PIC 61

1.40 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

W ATCHDOG, PRESCALER.

Limpa W ATCHDOG

Escreve tela principal ?SIM

NÃO

Recarrega Filtro dos Botões

Configura Timer0

Tela principal

BOTÃO MENUPRESS.?SIM

NÃO

Trata Botão Menu

BOTÃO ENTERPRESS.?

SIM

NÃO

Trata Botão ENTER

A

Habilita as interrupções

Tela principal

Inicializa LCD

Page 62: Apostila Linguagem C Para PIC

Linguagem C para PIC 62

Temp1 = 40SIM

INTERRUPÇÕES

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

Controle do Led2

Controle do Time - out datela principal

Incrementa contador de time -out, após 5 segundos, limpa oflag "f_tela_principal", paraliberar atualização da telaprincipal.

FIM DA INTERRUPÇÃO

SIM

SIM

NÃO

NÃO

SW ITCH CASE

Declara Variáveis locais

Incrementa contador deinterrupções

Zera contador de interrupçõesNÃO

Page 63: Apostila Linguagem C Para PIC

Linguagem C para PIC 63

Trata Botão MENU

Ação já foi executada ?

NÃO

Decrementa Filtro

Fim do Filtro ?SIM

Posiciona a seta na linha 0,coluna 0 do LCD

NÃO

A

SIM

Contador de Tela < 2NÃOSIM

Posiciona a seta na linha 1,coluna 0 do LCD

Page 64: Apostila Linguagem C Para PIC

Linguagem C para PIC 64

Trata Botão ENTER

Ação já foi executada ?

NÃO

Decrementa Filtro

Fim do Filtro ?SIM

Carrega a tela de seleção detarefa:Controle dos Leds ou Controledo Ventilador

NÃO

A

SIM

Re-inicia time-out

Page 65: Apostila Linguagem C Para PIC

Linguagem C para PIC 65

Page 66: Apostila Linguagem C Para PIC

Linguagem C para PIC 66

NÃO

SIM

Seleção da Tela de Menu

Tela 1 do Menu ?

Return

Posiciona a seta na linha 0coluna 0

NÃO

SIMTela 2 do Menu

Posiciona a seta na linha 1coluna 0

Switch Case

Beep

Fim do loop do Beep ?(conta beep)

SIM

Liga BeepDelay

NÃO

Desliga BeepDelay

Decrementa conta beep

Return

Page 67: Apostila Linguagem C Para PIC

Linguagem C para PIC 67

NÃO

SIM

Seleção da Tela de Enter

Tela 1 do Enter ?

Carrega a tela de controle deleds.Carrega contador para tela 3

NÃO

SIMTela 2 do Enter

Carrega a tela de controle doVentiladorCarrega contador para tela 4

Switch Case

NÃO

SIMTela 3 do Enter

Return

Indica estado dos leds On ouOff emite beep.

NÃO

SIMTela 4 do Enter

Indica estado do ventilador Onou Off emite beep

A

Page 68: Apostila Linguagem C Para PIC

Linguagem C para PIC 68

1.41 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Básicos de programação * * Exemplo 6 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar o funcionamento do módulo de LCD. // Foi criada uma rotina para escrever comandos e uma para escrever caracteres, // existe também uma rotina de inicialização necessária para a correta configuração // do LCD. Os botões S1 e S2 são respectivamente botão Menu e Enter, o botão Menu // seleciona a tarefa que desejamos executar (controle de Leds ou do Ventilador), // o botão Enter seleciona a tarefa e funciona como controle de liga/desliga // para a tarefa selecionada. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // O arquivo de definições do pic utilizado deve ser referenciado para que //os nomes definidos pela Microchip possam ser utilizados, sem a necessidade //de redigitação. #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 500 // tamanho do filtro /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. long int filtro = t_filtro; // inicia filtro dos botões int flags1 = 0; // registrador de flags int contador_tela = 0; // contador para seleção de tela int time_out = 0; // registrador para contagem de tempo de time-out

int contador,temp1,temp2; // variaveis para a rotina de int de Timer0 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a)

Page 69: Apostila Linguagem C Para PIC

Linguagem C para PIC 69

#use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08 #byte porte = 0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. #bit f_tela_principal = flags1.0 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit menu = portb.0 // Estado do botão menu // 1 -> Liberado // 0 -> Pressionado #bit enter = portb.1 // Estado do botão enter // 1 -> Liberado // 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #bit rs = porte.0 // via do lcd que sinaliza recepção de dados ou comando #bit enable = porte.1 // enable do lcd #bit led1 = portb.2 // led s3 #bit led2 = portb.3 // led s4 #bit ventilador = portc.1 // controle do ventilador #bit buzzer = porta.5 // controle do buzzer /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1 ; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos }

Page 70: Apostila Linguagem C Para PIC

Linguagem C para PIC 70

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); // limpa lcd delay_ms (2); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); // envia comando para inicializar display delay_ms(4); // espera 4 milisengundos 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); // configura LCD, 8 bits, matriz de 7x5, 2 linhas limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de Bip´s * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void bip(long int tempo, long int periodo) { long int conta_bip; // define variável local conta_bip = tempo / periodo; // contabiliza quantas vezes terá // que fazer o loop de bip´s while (conta_bip) // faça o loop até acabar o conta_bip { buzzer = 1; // liga o buzzer delay_ms(periodo/2); // conta tempo para o período escolhido buzzer = 0; // desliga o buzzer delay_ms(periodo/2); // conta tempo para o período excolhido conta_bip--; // decrementa o 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 }

Page 71: Apostila Linguagem C Para PIC

Linguagem C para PIC 71

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Menu * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_menu() { limpa_lcd(); comando_lcd(0x82); // posiciona o cursor na linha 0, coluna 2 printf (escreve_lcd, "ctr dos leds"); // imprime mensagem no lcd comando_lcd(0xc2); // posiciona o cursor na linha 1, coluna 2 printf (escreve_lcd, "ctr do vent"); // imprime mensagem no lcd } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleção de tela após pressionar a tecla enter * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_ctr_led() { limpa_lcd(); comando_lcd(0x82); // posiciona o cursor na linha 0, coluna 2 printf (escreve_lcd, "ctr dos leds"); // imprime mensagem no lcd comando_lcd(0xc4); // posiciona o cursor na linha 1, coluna 4 printf (escreve_lcd, "ON OFF"); // imprime mensagem no lcd if (!led1) { comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7 escreve_lcd(0x3e); // envia simbolo "maior" para o lcd comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 escreve_lcd(' '); // envia simbolo "espaço" para o lcd } else { comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 escreve_lcd(0x3e); // envia simbolo "maior" para o lcd comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7 escreve_lcd(' '); // envia simbolo "espaço" para o lcd } } void tela_ctr_ventilador() { limpa_lcd(); comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 3 printf (escreve_lcd, "Ventilador"); // imprime mensagem no lcd comando_lcd(0xc4); // posiciona o cursor na linha 1, coluna 4 printf (escreve_lcd, "ON OFF"); // imprime mensagem no lcd if (!ventilador) { comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7 escreve_lcd(0x3e); // envia simbolo "maior" para o lcd comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 escreve_lcd(' '); // envia simbolo "espaço" para o lcd } else { comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 escreve_lcd(0x3e); // envia simbolo "maior" para o lcd comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7 escreve_lcd(' '); // envia simbolo " " para o lcd } }

Page 72: Apostila Linguagem C Para PIC

Linguagem C para PIC 72

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleção das telas de Menu * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void sel_tela_menu() { switch(contador_tela) { case 1: tela_menu(); comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0 escreve_lcd(0x7e); // envia simbolo "seta" para o lcd break; // retorna case 2: tela_menu(); comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 escreve_lcd(0x7e); // envia simbolo "seta" para o lcd break; // retorna da função } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Seleção das telas após pressionar Enter * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void sel_tela_enter() { switch(contador_tela) { case 1: tela_ctr_led(); contador_tela = 3; break; // retorna da função case 2: tela_ctr_ventilador(); contador_tela = 4; break; // retorna da função case 3: if (!led1) { led1 = 1; // acende o led bip(50,2); comando_lcd(0xc3);// posiciona o cursor na linha 1, coluna 3 escreve_lcd(0x3e);// envia simbolo "maior" para o lcd comando_lcd(0xc7);// posiciona o cursor na linha 1, coluna 7 escreve_lcd(' ');// envia simbolo "espaço" para o lcd } else { led1 = 0; // apaga o led comando_lcd(0xc7);// posiciona o cursor na linha 1, coluna 7 escreve_lcd(0x3e);// envia simbolo "maior" para o lcd comando_lcd(0xc3);// posiciona o cursor na linha 1, coluna 3 escreve_lcd(' ');// envia simbolo "espaço" para o lcd bip(50,2); delay_ms(250); bip(50,2); } break; // retorna da função

Page 73: Apostila Linguagem C Para PIC

Linguagem C para PIC 73

case 4: if (!ventilador) { bip(750,2); ventilador = 1; // liga o ventilador comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 escreve_lcd(0x3e); // envia simbolo "maior" para o lcd comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7 escreve_lcd(' '); // envia simbolo "espaço" para o lcd } else { bip(1000,2); ventilador = 0; // desliga o ventilador comando_lcd(0xc7); // posiciona o cursor na linha 1, coluna 7 escreve_lcd(0x3e); // envia simbolo "maior" para o lcd comando_lcd(0xc3); // posiciona o cursor na linha 1, coluna 3 escreve_lcd(' '); // envia simbolo "espaço" para o lcd } break; // retorna da função } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); setup_counters (rtcc_internal, WDT_2304MS); set_tris_a(0b11011111); // configuração da direção dos pinos de I/O set_tris_b(0b11110011); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; // limpa porta portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0x00; // limpa portd porte=0x00; // limpa porte inicializa_lcd(); // configura o lcd tela_principal(); // imprime a tela principal no LCD enable_interrupts(INT_RTCC); enable_interrupts(GLOBAL); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ loop: while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Verifica se algum botão foi pressionado * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!f_tela_principal) { tela_principal(); }

Page 74: Apostila Linguagem C Para PIC

Linguagem C para PIC 74

//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * if (!menu) // testa botão 1 { goto trata_menu;// desvia para a rotina de incremento do timer } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * if (!enter) // testa botão 2 { goto trata_enter;// desvia para a rotina de incremento do timer } //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filtro = t_filtro; // recarga da variável filtro } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão S1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ trata_menu: //ligar time - out if (filtro != 0) // Ação já foi executada? { filtro --; // não, decrementa o filtro if (filtro == 0) // fim do filtro do botão? { // sim, executa tarefa if (contador_tela < 2) // De selecionar a próxima tarefa? { contador_tela ++;// sim, incrementa contador de seleção de tarefa sel_tela_menu(); // seleciona a tela de menu time_out = 0; // re-inicia contagem do tempo de time-out } else // não, { contador_tela = 1;// Volta para a primeira tela do menu sel_tela_menu(); // carrega a tela de menu time_out = 0; // re-inicia contagem do tempo de time-out } } } goto loop; // sim, volta para o loop principal /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão S2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ trata_enter: if (filtro != 0) // Ação já foi executada? { filtro --; // não, decrementa o filtro if (filtro == 0) // fim do filtro do botão? { sel_tela_enter(); // sim, carrega a tela de seleção de tarefa time_out = 0; // re-inicia contagem do tempo de time-out } } goto loop; }

Page 75: Apostila Linguagem C Para PIC

Linguagem C para PIC 75

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 256us. // A variável auxiliar temp1 será utilizada para contar 40 interrupções, // totalizando 10ms. O comando switch será executado a cada 10ms. #int_rtcc void trata_int_tmr0() { temp1 ++; if (temp1 == 40) // já passou 10ms? { temp1 = 0; // sim, zera contador de interrupção switch(contador) // seleciona tarefa { case 0: // controle do led2 temp2 ++; if (temp2 == 50) // passou 1 segundo? { temp2 = 0; // sim, zera contador de interrupção if (led1) // O led1 está ligado { if (!led2) // sim, o led2 está ligado? { led2 = 1; // não, liga o led2 } else { led2 = 0; // sim, desliga o led2 } } // não, então não controla o led2 else { led2 = 0;// não, mantém o led2 desligado } } contador ++; // incrementa contador de tarefa break; // fim de execução de execução da tarefa case 1: // time_out = 10ms * 250 * 2 time_out ++; if (time_out == 250) // já passou 5 segundos? { time_out = 0; // sim, zera time_out contador_tela = 0; // zera contador de tela f_tela_principal = 0; // libera atual.tela principal } contador ++; // incrementa contador de tarefa break; // fim de execução de execução da tarefa default: contador = 0; } } // não, sai da int. } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 76: Apostila Linguagem C Para PIC

Linguagem C para PIC 76

1.42 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Mude a rotina para que seja controlado o buzzer no lugar do led 2. 2. Crie mais um nível no Menu para controlar o buzzer.

Page 77: Apostila Linguagem C Para PIC

Linguagem C para PIC 77

1.43 - Anotações

Page 78: Apostila Linguagem C Para PIC

Linguagem C para PIC 78

Recursos Avançados: Exemplo 7 Conversor Analógico Digital 1.44 - Recursos do Livro

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

1.45 - Lógica do exemplo Este exemplo foi elaborado para explicar as funções do CCS para o módulo de conversão

analógico digital interno do PIC. É convertido o valor analógico presente no pino RA1 do microcontrolador, sendo que este valor pode ser alterado através do potenciômetro P2 da placa MCLAB2 este valor é ajustado entre 0 e 5V e mostrado no LCD.

Neste exemplo foi utilizado variável do tipo float para armazenar o resultado da conversão A/D. Para que possamos visualizar o valor de 0 à 5V no LCD, foi feita uma segunda conversão o valor

digital foi convertido para “Volts” realizando uma regra de 3.

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

Valor máximo daresolução do AD (10 bits)

Tensão de Referência Valor de tensão medido

Valor a ser mostrado nodisplay

Page 79: Apostila Linguagem C Para PIC

Linguagem C para PIC 79

1.46 - Esquema Elétrico

+

-

+5V

RA1

LM358

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2

VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0

RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

+5V

+5V

+5V

RESET

LCD

DB0DB1DB2DB3DB4DB5DB6DB7

VDDVOVSS

RSENR/W

2

1

3

4

5

6

7

98

12

14

13

1110

EN

RS

RSEN

10K

MC1

+5V

10K

P2

4MHz

4,7K 330R

1uF

10K

16F877A

Page 80: Apostila Linguagem C Para PIC

Linguagem C para PIC 80

1.47 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

WATCHDOG, PRESCALER.

Configura AD:RA0,RA1 e RA3 como entradas analógicas.adc = 10 bitsTensão de Refêrencia interna (VDD e VSS)Frequencia de conversão = fosc / 32Selecionado Canal 1Módulo ligado

A

Inicializa LCD

Prepara Tela principal

Page 81: Apostila Linguagem C Para PIC

Linguagem C para PIC 81

Envia resultado para o display

A

LIMPA WATCHDOG

Inicia e lê o resultado daconversão

Multiplica valor da conversãopor 5

Divide resultado damultiplicação por 1023

Page 82: Apostila Linguagem C Para PIC

Linguagem C para PIC 82

1.48 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 7 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar o funcionamento do módulo de // conversão analógico digital interno do PIC. É convertido o valor analógico // presente no pino RA2 do microcontrolador, sendo que este valor pode ser // alterado através do potenciômetro P2 da placa MCLAB2. O valor da conversão // A/D é ajustado numa escala de 0 à 5V e mostrado no LCD. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // O arquivo de definições do pic utilizado deve ser referenciado para que //os nomes definidos pela Microchip possam ser utilizados, sem a necessidade //de redigitação. #include <16f877A.h> // microcontrolador utilizado #device adc=10 // configura AD para retornar valor em 10 bits /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. float conversao = 0; // armazena o resultado da conversão AD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's *

Page 83: Apostila Linguagem C Para PIC

Linguagem C para PIC 83

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08 #byte porte = 0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit rs = porte.0 // via do lcd que sinaliza recepção de dados ou comando #bit enable = porte.1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1 ; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); // limpa lcd delay_ms (2); }

Page 84: Apostila Linguagem C Para PIC

Linguagem C para PIC 84

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); // envia comando para inicializar display delay_ms(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display delay_us(100); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal() { comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 3 printf (escreve_lcd, "Voltimetro"); // imprime mensagem no lcd comando_lcd(0xcd); // posiciona o cursor na linha 1, coluna 14 printf (escreve_lcd, " V"); // imprime mensagem no lcd } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (RA0_RA1_RA3_analog); setup_adc (adc_clock_div_32); setup_counters (rtcc_internal, WDT_2304MS); set_adc_channel (1); // seleciona o canal 1 do AD set_tris_a(0b11111111); // configuração da direção dos pinos de I/O set_tris_b(0b11111111); set_tris_c(0b11111111); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; // limpa porta portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0x00; // limpa portd porte=0x00; // limpa porte inicializa_lcd(); // configura o lcd tela_principal(); // imprime a tela principal no LCD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ loop: while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer conversao = read_adc(); // inicia conversão AD conversao = (conversao * 5); // faz regra de 3 para converter o valor, conversao = (conversao / 1023); // das unidades de AD em Volts. comando_lcd(0xC2); // posiciona o cursor na linha 1, coluna 2 printf (escreve_lcd,"%1.9f", conversao);// envia dados para o display de LCD // 1 número inteiro e 9 casas decimais.

Page 85: Apostila Linguagem C Para PIC

Linguagem C para PIC 85

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

Page 86: Apostila Linguagem C Para PIC

Linguagem C para PIC 86

1.49 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Mude a configuração do A/D para que ele retorne apenas os 8 bits mais significativos. 2. Altere a função de escrita no LCD para que ela imprima apenas 3 casas depois da virgula. 3. Mude a configuração do A/D para que ele realize as conversões com a Fosc/8.

Page 87: Apostila Linguagem C Para PIC

Linguagem C para PIC 87

1.50 - Anotações

Page 88: Apostila Linguagem C Para PIC

Linguagem C para PIC 88

Recursos Avançados: Exemplo 8 Controle do PWM e EEPROM Interna

1.51 - Recursos do Livro Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no

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

1.52 - Lógica do exemplo Este exemplo foi elaborado para explicar o funcionamento do módulo de PWM e da escrita da

EEPROM interna do microcontrolador. Um ventilador terá a sua velocidade controlada através do PWM, o valor ajustado poderá ser salvo na memória EEPROM e restaurado através dos botões.

A velocidade do ventilador é medida em rotações por segundo, através do timer1(usado como contador) e mostrada no LCD.

Através do botão S1, o PWM é incrementado e decrementado pelo botão S2. Realizando a operação nestes botões será visualizado no LCD o incremento e o decremento em porcentagem(%) e a rotação do ventilador em rps (rotações por segundo).

O botão S4 salva o valor de ajuste em EEPROM e o botão S3 restaura o valor salvo atualizando o PWM.

Para que possamos utilizar o PWM do PIC não podemos esquecer de configurar a freqüência do PWM no Timer2.

T = [(PR2 + 1) * 4] * Tosc * Prescaler TMR2

A função set_pwm_duty(valor), determina o período do pulso do PWM, ou seja, o tempo em

que a saída do PWM permanecerá em nível lógico 1. Este valor pode chegar a 1023, enquanto o período do PWM pode chegar a 1024, com PR2 igual a 255.

Por está razão dependendo da freqüência do PWM não será possível alcançar os 100% de Duty Cyle.

DC = (valor / T), 1023 / 1024 = 0,9990

Então antes de utilizar o PWM, estude o funcionamento do Módulo CCP para um melhor

aproveitamento. Este conhecimento pode ser adquirido através do livro Conectando o PIC.

Page 89: Apostila Linguagem C Para PIC

Linguagem C para PIC 89

1.53 - Esquema Elétrico

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2

VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0

RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

+5V

+5V

+5V

RESET

LCD

DB0DB1DB2DB3DB4DB5DB6DB7

VDDVOVSS

RSENR/W

2

1

3

4

5

6

7

98

12

1413

1110

RSEN

10K

MC1

+5V

10K

RB0 RB1

+5V

10K

+5V

10K

S1 S2

RS

EN

4MHz

+Vcc

MIN

I VE

NT

ILA

DO

R

4,7K

1N4148

BC337

+5V

150R 10K

+5V

1K

TACOMETRORPT38PT3F

BC337

1KSIR381583F

RB2 RB3

+5V

10K

+5V

10K

S3 S4

TACOMETRO

16F877A

Page 90: Apostila Linguagem C Para PIC

Linguagem C para PIC 90

1.54 - Fluxograma

MAIN

C ONFIGU RAÇ ÕES INICIAISTRIS, PO RTAS,

W ATCHDO G , PRESCALER.

Limpa W ATCH DOG

Escreve tela princ ipal ?SIM

NÃO

Configura T imer0

Tela principal

BO TÃO UP PRESS.?SIM

NÃO

Trata Botão UP

BO TÃO D OW NPRESS.?

SIM

N ÃO

Trata Botão DO W N

Habilita as interrupções

Tela princ ipal

Inic ializa LCD

Grava Dados emEEPRO M ?

SIM

NÃO

Salva dados em EEPR OM

Restaura Dados daEEPRO M ?

SIM

NÃO

Lê EEPRO M

Atualiza Pwm

NÃO

A

Page 91: Apostila Linguagem C Para PIC

Linguagem C para PIC 91

Trata Botão UP

Ação já foi executada ?

NÃO

Decrementa Filtro

Fim do Filtro ?

SIM

Incrementa PWM doventiladorAtualiza a tela principal

NÃO

A

SIM

Trata Botão DOWN

Decrementa Turbo

Fim do Turbo ?

Re-carrega variavel do Turbo

Decrementa PWM doventiladorAtualiza a tela principal

Ação já foi executada ?

NÃO

Decrementa Filtro

Fim do Filtro ?

SIM

NÃO

A

SIM

Decrementa Turbo

Fim do Turbo ?

Re-carrega variavel do Turbo

Page 92: Apostila Linguagem C Para PIC

Linguagem C para PIC 92

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

SIM

INTERRUPÇÕES

FIM DA INTERRUPÇÃO

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

NÃO

Decrementa contador deinterrupções

Divide variável rotação por 7(número de palhetas do

ventilador) habilita atualizaçãodo LCD

Page 93: Apostila Linguagem C Para PIC

Linguagem C para PIC 93

1.55 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 8 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar o funcionamento do módulo de // PWM e da escrita da EEPROM interna do microcontrolador. Um ventilador terá // a sua velocidade controlada através do PWM, o valor ajustado poderá ser // salva na memória EEPROM e restaurado através dos botões. // A velocidade do ventilador é medida em rotações por segundo, através do // timer1 e mostrada no lcd. #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicializa EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #rom 0x2100 = {0x03,0xe8} // carrega eeprom com valor inicial, inicia PWM com 97% /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 200 // tamanho do filtro #define turbo_tecla 5 // turbo dos botões /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. float duty_cycle = 0; // armazena o resultado da conversão AD long int duty_cycle1 = 0; // armazena o resultado da conversão AD long int periodo_pulso = 0; // long int rotacao = 0; // rps do ventilador int end = 0; // variável para endereçamento da eeprom int flags1 = 0; // flags int filtro = t_filtro; // inicia filtro dos botões int temp1 = 125; // variável aux para int de tmr0 int turbo = 1; // inicia turbo das teclas int dado; // variável de dados para eeprom

Page 94: Apostila Linguagem C Para PIC

Linguagem C para PIC 94

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta=0x05 #byte portb=0x06 #byte portc=0x07 #byte portd=0x08 #byte porte=0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. #bit atualiza_lcd = flags1.0 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit botao1 = portb.0 // Estado do botão 2 // 1 -> Liberado // 0 -> Pressionado #bit botao2 = portb.1 // Estado do botão 3 // 1 -> Liberado // 0 -> Pressionado #bit botao3 = portb.2 // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado #bit botao4 = portb.3 // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit rs = porte.0 // via do lcd que sinaliza recepção de dados ou comando #bit enable = porte.1 // enable do lcd #bit ventilador = portc.1 // pino de I/O para controle do ventilador (PWM) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1 ; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos }

Page 95: Apostila Linguagem C Para PIC

Linguagem C para PIC 95

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; // seleciona o envio de um caracter portd = caracter; // carrega o portd com o caracter enable = 1; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); // limpa lcd delay_ms (2); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); // envia comando para inicializar display delay_ms(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display delay_us(100); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para imprimir a Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal() { 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 }

Page 96: Apostila Linguagem C Para PIC

Linguagem C para PIC 96

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Salva Dados na EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // salva dado na eeprom no endereço indicado através da variável "end", // o dado a ser salvo é passado para a Função através da variável "dado". void salva_dados() { write_eeprom (end,dado); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Lê Dados na EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // lê o dado na eeprom no endereço indicado através da variável "end", // o dado lido é carregado na variável "dado". le_dados(end) { dado = read_eeprom (end); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Atualiza PWM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void atualiza_pwm() { set_pwm2_duty(periodo_pulso); // atualiza duty cicle do PWM } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); // desliga as entradas analógicas setup_counters (rtcc_internal, rtcc_div_64);// tmr0 clock interno, ps: 1:64 setup_timer_1 (t1_external_sync | t1_div_by_1);// tmr1 clock externo, ps: 1:1 setup_timer_2 (t2_div_by_16,255,1);// tmr2 ps=1:16, pr2=255 e postscale: 1:1 setup_ccp2(ccp_pwm); // modo PWM ligado set_pwm2_duty(periodo_pulso); // ajusta duty cycle em 0. set_tris_a(0b11111111); // configuração da direção dos pinos de I/O set_tris_b(0b11111111); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); porta=0x00; // limpa porta portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0x00; // limpa portd porte=0x00; // limpa porte inicializa_lcd(); // configura o lcd tela_principal(); // 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 if (atualiza_lcd != 0)

Page 97: Apostila Linguagem C Para PIC

Linguagem C para PIC 97

{ duty_cycle = periodo_pulso; // carrega valor da rotação medida duty_cycle = (duty_cycle / 1024); // efetua cálculo do duty cycle duty_cycle = (duty_cycle * 100); // converte para porcentagem (%) duty_cycle1 = (long int) duty_cycle; // carrega os 16 bits menos significativos da parte inteira

// do resultado da converão tela_principal(); // imprime a tela principal no LCD atualiza_lcd = 0; // indica LCD atualizado } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de incremento (UP) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) // testa botão 1 { goto trata_up; // desvia para a rotina de incremento do PWM } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão de decremento (down) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao2) // testa botão 2 { goto trata_dowm; // desvia para a rotina de decremento do PWM } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão ler dados da EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao3) // testa botão 3 { le_dados(1); // lê byte_low da eeprom periodo_pulso = dado; // carrega valor lido em variável de 16 bits le_dados(0); // lê byte_high da eeprom periodo_pulso = make16(dado, periodo_pulso); // recompõe o dado de 16 bits

atualiza_pwm(); // Função para atualizar o PWM atualiza_lcd = 1; // habilita atualização do LCD

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

Page 98: Apostila Linguagem C Para PIC

Linguagem C para PIC 98

turbo --; // decrementa o turbo da tecla filtro = t_filtro; if (turbo == 0) // sim, fim do turbo do botão ? { turbo = turbo_tecla;

if (periodo_pulso < 1023) // limita incremento do periodo do pulso em 1023 {

periodo_pulso ++; atualiza_pwm(); // Função para atualizar o PWM atualiza_lcd = 1; // habilita atualização do LCD } } } } goto loop; //* * * * * * * * * * * Decrementa duty cycle do PWM * * * * * * * * * * trata_dowm: { filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? { turbo --; // decrementa o turbo da tecla filtro = t_filtro; if (turbo == 0) // sim, fim do turbo do botão ?

{ turbo = turbo_tecla; if (periodo_pulso != 0)

// limita decremento do periodo do pulso em 0 { periodo_pulso --; atualiza_pwm(); // Função para atualizar o PWM atualiza_lcd = 1; // habilita atualização do LCD } } } } goto loop; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 8ms. // A variável auxiliar temp1 será utilizada para contar 125 interrupções, // totalizando 1 segundo. Quando isto ocorrer, a variável rotação será carregada // com o valor de rotações por segundo do ventilador. #int_rtcc void trata_int_tmr0(void) { set_rtcc(256-125); if (temp1 == 0 ) // ja passou 1 segundo? { // Sim, rotacao = get_timer1(); // le valor do timer 1 set_timer1 (0); // zera timer 1 rotacao = (rotacao / 7);

// divide por 7 (quantidade de palhetas do ventilador) atualiza_lcd = 1; // habilita atualização do LCD temp1 = 125; // re-inicia temp1 } else // Não, { temp1 --; // decrementa temp1 } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 99: Apostila Linguagem C Para PIC

Linguagem C para PIC 99

1.56 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Mude a freqüência do PWM para que possamos ajustar o Duty cycle de 0 a 100%. 2. Ative os dois PWM`s um para o ventilador e outro para a resistência.

Page 100: Apostila Linguagem C Para PIC

Linguagem C para PIC 100

1.57 - Anotações

Page 101: Apostila Linguagem C Para PIC

Linguagem C para PIC 101

Recursos Avançados: Exemplo 9 Coletor de Dados 1.58 - Recursos do Livro

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

1.59 - Lógica do exemplo Este exemplo foi elaborado para explicar as funções de I2C do compilador CCS e comunicação

serial com a USART. Neste exemplo iremos coletar dados do A/D e armazenar estes dados na EEPROM externa (24c04), estes dados serão enviados ao PC para a visualização dos mesmos.

O PC controlará as funções do coletor de dados. Quando for recebido o dado 0x55 o PIC inicia a coleta de dados, ao final da coleta e enviado

para o PC o comando 0x0b, para a liberação da transmissão de dados. Após o fim da coleta de dados o PIC aguarda o comando 0xaa, recebendo este dado, ele inicia a

transmissão de dados para o PC plotar os dados na tela. Ao final da transmissão ele aguarda novo comando de inicio de coleta de dados.

Page 102: Apostila Linguagem C Para PIC

Linguagem C para PIC 102

1.60 - Esquema Elétrico

24C04

A0A1

12

A2GND

34 SDA

SCL56

WPVCC

7

810K

+5V

4MHz

+5V

+5V

+5V

RESET10K

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2

VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0

RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

MC1

10K

LCD

DB0DB1DB2DB3DB4DB5DB6DB7

VDDVOVSS

RSENR/W

2

1

3

4

5

6

7

98

12

14

13

1110

EN

RS

+5V

10K

RSEN

+

-

+5V

RA1

P2

4,7K 330R

1uF

10K

MAX-232

+ C- C

VCC

T1OUTR1IN

T2OUTR2IN

26

16

10

9

11

12

C2+C2 -

T1INR1OUT

T2INR2OUT

45

7

8

1413

GND15

C1+C1 -

13

+5V

1K

3 2

CONECTORDB9 FEMEA

1uF

1uF

1uF

1uF5

+5V

16F877A

Page 103: Apostila Linguagem C Para PIC

Linguagem C para PIC 103

1.61 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

W ATCHDOG, PRESCALER.

Limpa W ATCHDOG

Configuração: AD, rs232 e I2C

Verifica se chegou comandopela USART

Inicia coleta de dados ?

SIM

NÃO

Coleta Dados

SIMTX Dados para o PC

Habilita as interrupções

Tela principal

Inicializa LCD

NÃO

A

Deve transmitir dadospara o PC ?

SIM

NÃO

Para a coleta de Dados ?Cancela coleta de dados

Transmite para o PC comandode fim de coleta de dados

A

B

Page 104: Apostila Linguagem C Para PIC

Linguagem C para PIC 104

Recebe comando do PC

Chegou comando do PC ?

SIM

SIM

Tarefa = para coleta de dados

B

NÃO

Recebeu o comando deinicio de Coleta de Dados

?

Tarefa = coleta de dados

SIM

Recebeu o comando detransmissão de dados

para o PC ?

Tarefa = transmite dados para oPC

Recebeu o comando deparar coleta de dados ?

SIM

NÃO

NÃO

NÃO

B

B

Page 105: Apostila Linguagem C Para PIC

Linguagem C para PIC 105

Fim da Coleta de Dados ?

SIM

Coleta Dados

Lê Dados do ADSalva em EEPROM Serial

NÃO

Aguarda novo comando do PC

Escreve no LCD:"Coletando Dados"

Envia para o PC comando deFim de Coleta de Dados

Escreve no LCD:"Pronto para TX"

Return

Page 106: Apostila Linguagem C Para PIC

Linguagem C para PIC 106

Fim da transmissão deDados ?

SIM

Transmite dados para o PC

Lê memória EEPROM SerialTransmite para o PC

NÃO

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

Escreve no LCD:"TX para o PC"

Aguarda novo comando do PCdelay de 5 segundos

Escreve no LCD:"Press Inicio"

delay de 1 segundo

Return

Page 107: Apostila Linguagem C Para PIC

Linguagem C para PIC 107

Page 108: Apostila Linguagem C Para PIC

Linguagem C para PIC 108

delay 10ms

Escreve na memória EEPROM Serial

Return

Envia Start bit

Envia Controle

Envia endereço low

Envia Dado

Envia Stop bit

delay 10ms

Lê dados da memória EEPROM Serial

Return

Envia Start bit

Envia Controle

Envia endereço low

Envia Start bit

Envia Controle

Recebe dados da memóriasalva em variável dado

Envia Stop bit

Page 109: Apostila Linguagem C Para PIC

Linguagem C para PIC 109

1.62 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 9 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar as funcões de I2C do compilador // CCS. Neste exemplo iremos coletar dados do AD e armazenar estes dados na // EEPROM externa (24c04), estes dados serão enviados ao PC para a // visualização dos mesmos. O PC controlará as funções do coletor de dados. #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração do Módulo I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use i2c(master,sda=pin_c4, scl=pin_c3, SLOW, RESTART_WDT, FORCE_HW) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração da USART * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use rs232 (baud=9600, xmit = pin_c6, rcv = pin_c7) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define ctrl_le 0b10100001// byte de controle da memória p/ leitura #define ctrl_escr 0b10100000// byte de controle da memória p/ escrita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constante internas do tipo Enumeração * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum selecao_de_tarefa { aguarda_comando, coleta_de_dados, transmite_para_pc, parar_coleta }tarefa; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 110: Apostila Linguagem C Para PIC

Linguagem C para PIC 110

* Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. static int flags1 = 0; // flags static int dado = 0; static int end_low = 0; static int tx_pc; static int comando = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta=0x05 #byte portb=0x06 #byte portc=0x07 #byte portd=0x08 #byte porte=0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. #bit atualiza_lcd = flags1.0 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit rs = porte.0 // via do lcd que sinaliza recepção de dados ou comando #bit enable = porte.1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para escrita na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ escr_mem_serial () { i2c_start(); // Condição de início i2c_write(ctrl_escr); // Envia o byte de controle de leitura i2c_write(end_low); // Envia endereço baixo i2c_write(dado); // Escreve dado na E²PROM i2c_stop(); // Condição de parada delay_ms(10); // espera a gravação estar completa } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para leitura na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ le_mem_serial () { i2c_start(); // Condição de início i2c_write(ctrl_escr); // Envia o byte de controle de leitura i2c_write(end_low); // Envia endereço baixo i2c_start(); // Nova condição de início i2c_write(ctrl_le); // Envia o byte de controle de leitura dado = i2c_read(0); // lê o dado armazenado na E²PROM i2c_stop(); // Condição de parada } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 111: Apostila Linguagem C Para PIC

Linguagem C para PIC 111

* Função que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1 ; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; // seleciona o envio de um caracter portd = caracter; // carrega o portd com o caracter enable = 1; // gera pulso no enable delay_us(1); // espera 1 microsegundo enable = 0; // desce o pino de enable delay_us(40); // espera mínimo 40 microsegundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); // limpa lcd delay_ms (2); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); // envia comando para inicializar display delay_ms(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display delay_us(100); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para imprimir a Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal() {

limpa_lcd() comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0 printf (escreve_lcd, "Coletor de dados"); // imprime mensagem no lcd } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina para coleta de dados *

Page 112: Apostila Linguagem C Para PIC

Linguagem C para PIC 112

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ coleta_dados() { comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, "Coletando Dados"); // imprime mensagem no lcd do { dado = read_adc(); // le resuldado do AD escr_mem_serial (); // salva em eeprom end_low += 1; // incrementa endereço, seleciona nova posição delay_ms(10); // delay de 10 ms }while (end_low != 0); // fim da coleta ? tarefa = aguarda_comando; // aguarda comando do PC comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " Pronto para TX "); // imprime mensagem no lcd tx_pc = 11; // indica para o pc fim da coleta de dados printf ("%x\r\n",tx_pc);// envia ao PC o comando de fim da coleta de dados delay_ms(2000); // delay de 2 segundos } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina para transmitir dados para o PC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ tx_dados_pc() { comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " TX para o PC "); // imprime mensagem no lcd do { le_mem_serial (); // le dados da eeprom printf ("%x\r\n",dado); // envia ao PC o valor da eeprom externa end_low +=1; // incrementa endereço, seleciona nova posição delay_ms(100); // delay de 100 ms }while (end_low != 0); // fim da transmissão de dados tarefa = aguarda_comando; // aguarda comando do PC comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " Fim da Trans..."); // imprime mensagem no lcd delay_ms(3000); // delay de 3 segundos comando_lcd(0xc0); // posiciona o cursor na linha 1, coluna 0 printf (escreve_lcd, " "); // imprime mensagem no lcd delay_ms(1000); // delay de 1 segundo } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento de recepção serial * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void recebe_comando() { if (kbhit()) { comando = getc(); if (comando == 0x55) // recebeu o camando de coleta de dados ? { tarefa = coleta_de_dados; // sim, libera coleta de dados } if (comando == 0xaa) // recebeu o camando de transmissão de dados ? { tarefa = transmite_para_pc; // sim, transmite dados para o PC } if (comando == 0x7f) // recebeu o camando para cancelar coleta de dados ? { tarefa = parar_coleta; // sim, cancela coleta de dados } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic *

Page 113: Apostila Linguagem C Para PIC

Linguagem C para PIC 113

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 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); // configuração da direção dos pinos de I/O set_tris_b(0b11111111); set_tris_c(0b10110111); set_tris_d(0b00000000); set_tris_e(0b00000100);

porta=0x00; // limpa porta

portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0x00; // limpa portd porte=0x00; // limpa porte inicializa_lcd(); // configura o lcd tela_principal(); // imprime a tela principal no LCD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ loop: while(true) // rotina principal { RESTART_WDT(); // incia o watch-dog timer recebe_comando(); if (tarefa == coleta_de_dados) // inicia coleta de dados ? { end_low = 0; // sim, carrega endereço inicial coleta_dados(); // executa função de coleta de dados } if (tarefa == transmite_para_pc)// inicia transmissão de dados para o PC ? { end_low = 0; // sim, carrega endereço inicial tx_dados_pc(); // executa função de transmissão de dados } if (tarefa == parar_coleta) // cancela coleta de dados ? { end_low = 0; // sim, carrega endereço inicial tarefa = aguarda_comando; // espera envio de comando do PC tx_pc = 11; // fim da coleta de dados tx_dados_pc(); // envia comando para o PC } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 114: Apostila Linguagem C Para PIC

Linguagem C para PIC 114

1.63 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Mude a rotina de coleta de dados para que seja armazenado na EEPROM um valor de 0 à

5V e não um valor de 0 a 255. Implemente a regra de três necessária. 2. Altere a configuração do A/D para que ele retorne os 10 bits do resultado da conversão e

salve este dado na EEPROM.

Page 115: Apostila Linguagem C Para PIC

Linguagem C para PIC 115

1.64 - Anotações

Page 116: Apostila Linguagem C Para PIC

Linguagem C para PIC 116

Recursos Avançados: Exemplo 10 Funções Matemáticas 1.65 - Recursos do Livro

Para o bom entendimento deste exemplo são necessários os conhecimentos adquiridos no exemplo 1 e mais, funções matemáticas do compilador (cap.11.1 pág 175 do livro Programação em C).

1.66 - Lógica do exemplo A elaboração deste exemplo foi pensando na demonstração das funções matemáticas, nele

veremos o microcontrolador realizando o calculo do seno de 0 a 2π, um software para PC foi elaborado para coletar os cálculos realizas e plotar os cálculos na tela do PC. Outras funções podem ser visualizadas, bastando para isso alterar a função matemática de nosso programa.

Page 117: Apostila Linguagem C Para PIC

Linguagem C para PIC 117

1.67 - Esquema Elétrico

MAX-232

+ C- C

VCC

T1OUTR1IN

T2OUTR2IN

26

16

10

9

11

12

C2+C2 -

T1INR1OUT

T2INR2OUT

45

7

8

1413

GND15

C1+C1 -

13

+5V

1K

3 2

CONECTORDB9 FEMEA

1uF

1uF

1uF

1uF

MCLRRA0RA1RA2

RA4RA5

RA3

RE1RE0

RE2VDDVSSOSC1OSC2

RC1RC2

RC0

RC4RC3

RC5

VDDVSSRB7RB6

RB4RB3

RB5

RB1RB2

RB0RD7RD6RD5RD4

RD2RD1

RD3

RC7RD0

RC6

1

2

4

3

5

6

7

8

9

10

11

12

13

14

15

16

17

18

23

24

33

30

29

28

27

22

21

20

19

26

25

32

31

40

39

38

37

36

35

34

+5V

+5V

+5V

RESET

RSEN

10K

MC1

5

4MHz

+5V

16F877A

Page 118: Apostila Linguagem C Para PIC

Linguagem C para PIC 118

1.68 - Fluxograma

MAIN

CONFIGURAÇÕES INICIAISTRIS, PORTAS,

W ATCHDOG, PRESCALER.

Inicializa a variávelX = 0

X < (2 * PI)

LIMPA W ATCHDOG

Y = seno (x)

Envia o valor de X para o PC

Envia o valor de Y para o PC

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

NÃO

SIM

Page 119: Apostila Linguagem C Para PIC

Linguagem C para PIC 119

1.69 - Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 10 * * * * CENTRO DE CAPACITAÇÃO - LABTOOLS * * * * TEL: (0XX11) 4992-8775 SITE: www.labtools.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este software foi desenvolvido para mostrar a implementação de funções // matemáticas, como exemplo estamos calculando o seno e enviando para o // PC os valores de "x" e "y" para serem plotados. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição dos I/O's e opções de configuração * * das funções para periféricos * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado #device adc=10 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Carrega bibliteca Matemática * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <math.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração da Usart * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. float y; float x; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário

Page 120: Apostila Linguagem C Para PIC

Linguagem C para PIC 120

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta=0x05 #byte portb=0x06 #byte portc=0x07 #byte portd=0x08 #byte porte=0x09 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() { setup_adc_ports (no_analogs); // desliga as entradas analógicas setup_counters (rtcc_internal, wdt_2304ms);// tmr0 clock interno, ps: 1:64 set_tris_a(0b11111111); // configuração da direção dos pinos de I/O set_tris_b(0b11111111); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta=0x00; // limpa porta portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0x00; // limpa portd porte=0x00; // limpa porte /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { x=0; while(x < 2*PI) { restart_wdt(); // limpa wdt y = sin (x); // calculo da função printf ("X=%1.3f",x); // envia ao PC o valor de x printf (" "); printf ("Y=%1.3f\r\n",y); // envia ao PC o valor de y x = x + 0.01; // incrementa x } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 121: Apostila Linguagem C Para PIC

Linguagem C para PIC 121

1.70 -

1.71 - Exercícios Propostos Agora que o exemplo já foi estudado e esclarecido, aproveite para gerar novos problemas e

soluções, seguindo os exercícios propostos: 1. Altere a função matemática para que o PIC calcule o co-seno. 2. Altere a função matemática para que o PIC calcule o log de um número.

Page 122: Apostila Linguagem C Para PIC

Linguagem C para PIC 122

1.72 - Anotações