Curso de
Linguagem C
Rinaldo Câmara Gonçalves
Labtools – Mosaico Didactic Division Revisão 2
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
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
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.
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
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
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
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 -
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.
Linguagem C para PIC 11
1.8 - Anotações
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.
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
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
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
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
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.
Linguagem C para PIC 19
1.15 - Anotações
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.
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
Linguagem C para PIC 22
1.19 - Fluxograma
MAIN
CONFIGURAÇÕES INICIAISTRIS, PORTAS,
WATCHDOG, PRESCALER.
INICIALIZA PORTB COM0X10
LIMPA WATCHDOG
B
A
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
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 ≠
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)
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; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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 } } }
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.
Linguagem C para PIC 29
1.22 - Anotações
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.
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
Linguagem C para PIC 32
1.26 - Fluxograma
MAIN
CONFIGURAÇÕES INICIAISTRIS, PORTAS,
WATCHDOG, PRESCALER.
LIGA AS INTERRUPÇÕES
LIMPA WATCHDOG
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
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
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
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
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
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 ?
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 } }
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
Linguagem C para PIC 41
1.29 - Anotações
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
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.
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
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
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
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
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
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
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;
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)
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; } }
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 } }
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
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;
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. }
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.
Linguagem C para PIC 58
1.36 - Anotações
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.
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
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
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
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
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
Linguagem C para PIC 65
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
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
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)
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 }
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 }
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 } }
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
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(); }
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; }
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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.
Linguagem C para PIC 77
1.43 - Anotações
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
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
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
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
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 *
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); }
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.
Linguagem C para PIC 85
} } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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.
Linguagem C para PIC 87
1.50 - Anotações
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.
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
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
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
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
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
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 }
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 }
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)
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? {
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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.
Linguagem C para PIC 100
1.57 - Anotações
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.
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
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
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
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
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
Linguagem C para PIC 107
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
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; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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 } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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 *
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 *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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.
Linguagem C para PIC 115
1.64 - Anotações
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.
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
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
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
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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.
Linguagem C para PIC 122
1.72 - Anotações
Top Related