Prévia do material em texto
0
1
MICROCONTROLADORES
Os microcontroladores são dispositivos de tamanho reduzido que
possuem uma interface programável para controle de máquinas e
equipamentos eletro-eletrônicos. Esses dispositivos possuem em um único
circuito integrado, diversos componentes de um sistema computacional
simplificado. Sendo assim, um microcontrolador é um pequeno
microcomputador integrado em um único chip. Trata-se de um componente
versátil por ser programável, viabilizando o seu empregado em diversas
situações. A maior parte do custo desse componente não está vinculada ao
material com que o mesmo é fabricado, mas sim, ao projeto,
desenvolvimento e produção dos circuitos internos que garantem a
funcionalidade a ele atribuída. Diversas empresas como a Intel, Microchip,
Atmel, Motorola, Philips, entre outras importantes fabricantes investem
milhões de dólares em pesquisas e desenvolvimento de microcontroladores
cada vez mais eficientes, mais velozes, com maior capacidade, mais
recursos de conectividade e controle, tudo isso com um menor consumo de
energia elétrica.
Apesar do alto investimento financeiro na sua produção, o
microcontrolador é considerado, na maioria das vezes, uma alternativa com
um excelente custo benefício. Isso porque se trata de um componente
versátil, permitindo uma grande diversidade de aplicações, portanto, há
uma grande quantidade de microcontroladores desenvolvidos que podem
ser úteis para um mesmo projeto, assim há diluição de grande parte do
investimento de desenvolvimento, tornando o componente bastante atrativo
em termos de custo.
LINGUAGEM DE PROGRAMAÇÃO C
Trata-se de uma linguagem de programação com um nível mais alto
que a linguagem Assembly, e mais baixo que as demais linguagens ,
portanto, a linguagem C é considerada uma linguagem de nível
intermediário e é bastante poderosa e versátil. Criada por Dennis Ritchie da
Bell Labs em 1972, é conhecida pelo seu equilíbrio entre estruturação e
eficiência, suprimindo as deficiências da linguagem Assembly e mantendo o
baixo consumo de memória.
Um fator que difere a linguagem C (assim como todas as outras
linguagens) em relação à Assembly, é que a primeira é compilada. Desta
forma, o programa fonte gerado pelo programador é processado por um
outro programa, conhecido como COMPILADOR, que irá gerar o programa
em linguagem binária.
Na maioria dos compiladores, o processo é realizado em duas etapas,
2
sendo isso transparente ao usuário. Na primeira etapa, existe a leitura do
programa fonte, a verificação dos símbolos (nomes usados no programa), e
da sintaxe dos comandos, verificando se há algum erro sintático. Em
paralelo a isso, através da análise do significado de cada estrutura da
linguagem, é produzido um programa em linguagem intermediária (em
alguns casos o código intermediário é em Assembly). Na segunda etapa, o
compilador executa a tradução do código intermediário para a linguagem de
destino, neste caso, em um arquivo HEX com as instruções de máquina do
microcontrolador (Figura 2).
Figura 1 - Diagrama de programação em linguagem C
Fonte: Centro Tercnológico de Mecatrônica SENAI.
Uma das vantagens da linguagem C em relação ao Assembly está no
fato de se poder criar situações mais complexas do que as suportadas por
uma única instrução da linguagem de máquina do harware alvo. Por
exemplo, se o programador assembly necessita realizar uma multiplicação,
ele deverá criar um trecho que execute somas sucessivas. Em C, o
programador já possui a opção de utilizar o operador multiplicação e o
compilador fica responsável pela tradução dessa operação, tornando-a
mais adequada possível.
Uma desvantagem da linguagem C em relação a linguagem Assembly
está no consumo de memória. O compilador nem sempre consegue realizar
as otimizações de código possíveis, com isso, há um acréscimo de
instruções no código binário (arquivo HEX) gerado, o que acarreta em um
aumento no consumo de memória de programa. Mas, há a possibilidade do
programador realizar otimizações ao programa depois de gerá-lo em C e
com isso reduzir o consumo de memória a um valor bem próximo ao que
seria utilizado se o mesmo fosse escrito em Assembly, com a vantagem da
economia de tempo.
A linguagem C permite ao programador, escrever seu programa de
forma estruturada, otimizando a programação devido à organização e
possibilitando o reaproveitamento de trechos já escritos.
3
1 – PINOS INPUT/OUTPUT DIGITAIS
1.1 – INTRODUÇÃO
Os pinos de entrada e saída ou input/output (I/O) permitem a interação do
microcontrolador com o circuito ou dispositivo conectado a ele, realizando a
entrada ou a saída de dados. Os pinos de entrada recebem dados que
podem ser processados pelo microcontrolador, já os pinos de saída enviam
dados que podem ativar ou desativar circuitos ou dispositivos que estejam
conectados a ele. Existem pinos que trabalham como entrada e saída de
dados.
1.2 – DIFERENÇA ENTRE SINAIS ANALÓGICOS E SINAIS DIGITAIS
Um sinal que pode ter infinitos valores de amplitude em um intervalo
finito, é chamado sinal analógico. Abaixo segue um exemplo:
Já um sinal digital é aquele que pode assumir finitos valores de
amplitude em um intervalo finito. Nós trabalharemos com sinais que vão
possuir apenas dois valores de amplitude, como no exemplo a seguir:
4
1.3 – SINTAXE
1.3.1 Trisx: Configurações das portas como entrada ou saída
Ex: Trisa=1; //Definindo porta como entrada.
Trisb=0; //Definindo portb como saída.
Trisc.rc0=1; //Definindo a porta rc0 como entrada.
1.3.2 Portx: Definindo o nível lógico das portas digitais
Ex: Portb=255; //Definindo portb como nível lógico alto.
Porta=0; //Definindo porta como nível lógico baixo.
Portc.rc3=1; //Definindo o nível lógico da porta rc3 como alto.
1.3.3 define: Utilizado antes do Void main, rotula variáveis para
facilitar seu uso ou modificação ao longo de um programa de maior
complexidade
Ex: #define Verde portb.rb0; //”Verde” se torna um rótulo
//para a variável “portb.rb0”.
//Temos que “Verde=1” é igual
// à “portb.rb0=1”.
5
1.4 – PORTA
O porta possui as funções de entrada, saída e muitas outras funções
multiplexadas nos seus pinos. Segue uma tabela que contém todas as
funções listadas, retirada do datasheet dos modelos de microcontroladores
que utilizaremos no curso.
A tabela abaixo lista todos registradores ligados ao porta.
6
1.5 – PORTB
Da mesma forma que o porta, o portb possui muitas funções
multiplexadas em seus pinos, que estão na tabela abaixo.
7
A tabela abaixo lista todos registradores ligados ao portb.
8
1.6 – PORTC
O portc possui muitas funções, assim como o porta e o portb, que
estão listadas na tabela abaixo:
A tabela abaixo lista todos registradores ligados ao portc.
9
1.7 – PORTD
Assim como os anteriores, o portd possui diversas funções
multiplexadas em seus pinos, que estão contidas na tabela abaixo:
A tabela abaixo lista os registradores ligados ao portd.
10
1.8 – PORTE
Da mesma forma que os demais, o porte possui várias funções nos
seus pinos. Na tabela abaixo estão lista todas elas.
A tabela abaixo lista os registradores ligados ao porte.
11
1.9 – SENSORES DIGITAIS
Os sensores digitais podem assumir apenas dois estágios de tensão
em seu sinal de saída no decorrer do tempo,também são chamados de
nível lógico, que são interpretados como zero ou um. Naturalmente não
existem grandezas físicas que possuam esses valores, porém, é assim que o
sensor se comunica com o sistema de controle, geralmente após passar por
um circuito eletrônico de comparação. Qualquer tipo de sensor pode ser
usado como um sensor digital. Segue abaixo uma tabela com a descrição de
alguns sensores digitais.
Sensor Descrição Onde é encontrado Imagens
Chaves digitais
São os sensores mais
comuns, são encontrados
de diversas formas, é
acionado
mecanicamente, funciona
como dispositivo de
entrada de dados
É comumente
encontrado em
qualquer equipamento
eletrônico.
Chave
magnética
"reed switch"
É uma chave digital
acionada por campo
magnético.
É muito comum em
sistemas de alarme
Par óptico ou
sensor
infravermelho
É formado por um LED
infravermelho e um
fototransistor
É encontrado em
controles remotos (TV,
DVD, etc.) ou em
teclados e mouses sem
fio. É responsável por
transmissão de dados.
Sensor
Ultrassônico
Um oscilador emite uma
onda ultrassônica, esta é
refletida por obstáculos
físicos e é captada pelo
sensor. A resposta desse
sensor é um sinal digital.
É utilizado para medir
distâncias e detecção
de objetos. É muito
presente na indústria,
também em
automóveis.
12
1.10 – EXEMPLOS
1.10.1 - Faça um programa para piscar um LED de 1 em 1s, o mesmo está
conectado ao portb.RB0 do PIC.
Resposta:
void main(){ //função principal
trisb=0; //Definido o portb como saída
portb=0; //Definindo o estado lógico inicial do portb como baixo (0V)
while(1){ //Laço repetitivo
portb.rb0=1; //Ascende o LED
delay_ms(1000); //Damos um Delay de 1000ms = 1s
portb.rb0=0; //Desliga o LED
delay_ms(1000); //Damos mais um Delay de 1000ms = 1s
}
}
1.10.2 - Faça um programa para ascender um LED quando for apertado um
botão, que dará entrada de sinal na porta RA0. O LED está conectado a
porta RB0 do PIC.
Resposta:
void main{ //função principal
trisa.RA0=1; //definindo a porta RA0 como entrada
trisb.RB0=0; //definindo a porta RB0 como saída
portb=0; //Definindo o estado lógico inicial do portb como baixo (0V)
while(1){ //Laço repetitivo
if(porta.RA0=1){ //Se o botão estiver apertado
portb.RB0=1; //Ascender o LED
}else{ //Se o botão não estiver apertado
portb.RB0=0; //Desliga o LED
}
}
}
13
1.11 – EXERCÍCIOS
1 – Utilizando o Circuito eletrônico abaixo, programe o PORTB para que
acenda somente o Led D8 e o Led D4, os demais leds deverão ficar
apagados.
2 – Com base no circuito do exercício anterior, programe o PORTB para que
acenda todos os leds.
3 – Programe o PORTA para que acenda todos os Leds.
4 – Utilizando o circuito da imagem abaixo, programe o PORTA para que os
Leds ímpares (1,3,5 e 7) pisquem de 1 em 1s enquanto o botão 1 está
sendo apertado, e quando o botão estiver desapertado manter os Leds
pares (2,4 e 6) acesos.
5 – Faça um programa para controlar as luzes de um semáforo, utilize o
circuito abaixo e os padrões de cores da tabela.
Semáforo
1
Semáforo
2
14
6 – Abaixo segue uma tabela que descreve a lógica de uma placa de
potência que aciona um motor de corrente contínua.
Estado lógico das entradas
Entrada 1 Entrada 2 Resposta do motor
0 0 Motor parado
0 1 Gira sentido horário
1 0 Gira sentido anti-horário
1 1 Motor parado
Esse motor está ligado a uma esteira rolante industrial que transporta peças
em um processo. Cada peça necessita ficar parada por um período de 5
segundos, e depois a esteira é acionada para transportar a peça para uma
próxima etapa. Programe e simule o acionamento deste motor para realizar
a tarefa descrita. O esquemático da placa de potência encontra-se abaixo:
15
2 – DISPLAY LCD ALFANUMÉRICO
2.1 – INTRODUÇÃO
O display alfanumérico é um dispositivo capaz de converter sinais
digitais recebidos em seus pinos de entrada em uma diversidade de
caracteres exibidos em uma tela de LCD.
Esse dispositivo possui uma memoria chamada DDRAM onde são
gravados os caracteres que estão em exibição no display. Os caracteres
devem ser escritos um por vez e a posição do curso do display representa a
posição da DDRAM na qual o dado estará sendo escrito.
A maioria das DDRAM de LCDs possui um total de 80 bytes, ou seja,
é capaz de armazenar até 80 caracteres, porém, esse numero é limitado
pelo numero de casas que o display é capaz de exibir.
Exemplo: Um Display LCD 16x2 possui uma tela capaz de mostrar 16
colunas e 2 linhas, ou seja exibe um total de 32 caracteres gravados na
DDRAM.
Coluna 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16
Linha 1 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
Linha 2 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E
Endereço da DDRAM correspondente.
16
2.2 – DESCRIÇÃO DOS PINOS DO LCD
Pino Função
VSS Alimentação do display. (GND)
VDD Alimentação do display. (5V)
VE
Pino responsável pelo controle do contraste do display,
este pino geralmente é ligado a um potenciômetro para
permitir o ajuste manual do contraste.
A Alimentação do backlight. (5V)
K Alimentação do backlight. (GND)
E – Enable
Este pino é responsável por iniciar a leitura dos sinais na
entrada dos pinos de dados do LCD.
R/W – Read/Write
Este pino configura o alterna o display entre o modo de
escrita da memória DDRAM.
R/W=0: Escrita de DDRAM.
R/W=1: Leitura da DDRAM.
RS
O pino RS é responsável notifica o display qual é o tipo de
dado que chegou em seus pinos de dados. Os dados
podem ser um caractere a ser escrito ou um comando a
ser executado como, por exemplo, deslocar o cursor ou
limpar a tela.
RS= 0: Executar comando.
RS=1: Escrever caractere.
D7-D0 :Pinos de dados.
Esses pinos são os 8 bits de dados recebidos pelo
display. O display LCD pode ser configurado para
trabalhar tanto utilizando esses 8 pinos de dados quanto
utilizando apenas 4 deles..
Os dados enviados a um display alfanumérico por um
microcontolador, na grande maioria das vezes por meio de 4 bits, pois isso
permite que sejam usados 4 pinos de I/O a menos, liberando estes para
serem utilizados em outras aplicações.
17
2.3 – UTILIZAÇÃO NO MIKROC
O software MikroC Pro, conta com um biblioteca integrada destinada
a escrever em Displays LCD.
Para se trabalhar com um display usando o MikroC devemos seguir os
seguintes passos:
1. Setar os bits.
2. Inicializar o display.
3. Escrever ou enviar comandos.
2.3.1 – Setar os bits:
Essa etapa consiste em informar a compilador as conexões
eletrônicas do circuito, ou seja, associar cada pino do microcontrolador ao
pino do display que será conectado.
A associação é feita através do comando setbit. É necessário também
associar também o registrador de definição de direção do pino ao pino do
display (TRIS).
Exemplo:
Conexões eletrônicas do circuito
18
// Lcd pinout settings
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D4 at RD4_bit;
// Pin direction
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD4_bit;Associação dos registradores para o circuito eletrônico acima.
2.3.2 – Inicializar o display
Para inicializar o display LCD basta adicionar o comando Lcd_Init()
da biblioteca de LCD a ao início do código.
2.3.3 – Escrever e enviar comandos para o display
Temos 3 comandos que podem ser utilizados para escrever no display
LCD, cada um deste com uma função:
Comando Descrição Exemplo
Lcd_Out(X, Y, Texto )
Comando utilizado para escrever em
uma determinada coordenada do
display.
Lcd_Out(2,1,”TROIA”)
Lcd_Out_cp(Texto)
Este comando escreve na posição
em que o curso do display estiver
parado.
Lcd_Out_cp(“TROIA)
Lcd_Out_ch(Caractere)
Comando utilizado para escrever um
único caractere no display.
Lcd_Out_ch(‘%’)
O envio de comandos ao display se da por meio da função:
Lcd_Cmd(Comando);
Como parâmetro esta função deve enviar o código hexadecimal do
comando segundo o determinado no datasheet do Display. O MikroC conta
com algumas constantes associadas aos hexadecimais dos comandos mais
utilizados, o que permite o envio de um texto como parâmetro.
19
Segue abaixo a tabela com as constantes de comando:
Comando Efeito
_LCD_FIRST_ROW Move o cursor para a 1ª linha.
_LCD_SECOND_ROW Move o cursor para a 2ª linha.
_LCD_THIRD_ROW Move o cursor para a 3ª linha.
_LCD_FOURTH_ROW Move o cursor para a 4ª linha.
_LCD_CLEAR Limpa o display
_LCD_RETURN_HOME Retorna o curso a posição incial.
_LCD_CURSOR_OFF Desativa o cursor.
_LCD_UNDERLINE_ON Ativa cursor linha
_LCD_BLINK_CURSOR_ON Ativa cursor bloco
_LCD_MOVE_CURSOR_LEFT Move o cursor para a esquerda
_LCD_MOVE_CURSOR_RIGHT Move o cursor para direita
_LCD_TURN_ON Liga o display.
_LCD_TURN_OFF Desliga o display.
_LCD_SHIFT_LEFT Move o texto do display para a esquerda.
_LCD_SHIFT_RIGHT Move o texto do display para a direita
Os comandos Lcd_ Out e Lcd_Out_cp do MikroC, são destinados a
escrever na tela vetores de caracteres (Strings), logo se for enviado um
número como parâmetro destas funções, o número não será impresso.
Para se escrever números nos display deve-se então convertê-los
para variáveis do tipo String. Para se realizar essa conversão é necessário
utilizar os comandos da biblioteca Conversions.
Comando Conversão
InttoStr Inteiro para String
FloattoStr Float para String
DoubletoStr Double para String
20
2.4 – EXEMPLOS
Limpar o display: Lcd_Cmd(_LCD_CLEAR);
Desligar o cursor: Lcd_Cmd(_LCD_CURSOR_OFF);
2.4.1 – Desativando o cursor, escrevendo e limpando o LCD
O exemplo abaixo irá desligar o cursor, mostrar um texto por 1 segundo e
em seguida limpar o LCD.
// Lcd pinout settings
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D4 at RD4_bit;
// Pin direction
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD4_bit;
void main() {
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
while(1){
Lcd_Out(1,1,"Equipe TROIA");
Delay_ms(1000);
Lcd_cmd(_LCD_CLEAR);
Delay_ms(1000);}}
21
2.4.2 – Escrevendo número no LCD
// Lcd pinout settings
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D4 at RD4_bit;
// Pin direction
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD4_bit;
void main() {
int i;
char texto[7];
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
while(1){
i++;
intToStr(i,texto); //Converte inteiro em String
Lcd_Out(1,1,texto);
Delay_ms(100);
Lcd_cmd(_LCD_CLEAR);
}
}
22
2.5 – EXERCÍCIOS
1 – Escreva uma sequência de pelo menos dois textos que se alternem no
Display, utilizando o circuito abaixo:
2 – Inclua variáveis numéricas no programa do exercício anterior e faça a
impressão delas.
3 – Faça um programa que conte o número de vezes que um botão ligado a
uma entrada digital do microcontrolador é pressionado.
23
3 – CONVERSOR ANALÓGICO DIGITAL
3.1 – INTRODUÇÃO
O conversor A/D é um dispositivo eletrônico capaz de gerar uma
representação digital binária a partir de uma grandeza analógica.
Normalmente os sinais interpretados são valores de tensão. Os
microcontroladores com os quais estamos trabalhando possuem
conversores analógico digitais de 10bits, a resposta que obtemos com a
conversão é um número que varia entre 0 e 1023. Estes números estão
relacionados com as tensões de referência que estamos usando.
3.1.1 – Onde usamos
Quando queremos medir grandezas físicas como temperatura,
luminosidade, deformação, ruídos, entre outras, utilizamos sensores. Esses
componentes são dispositivos eletroeletrônicos que transformam uma
grandeza física em um sinal elétrico que está relacionado a uma ou mais
propriedades do material que ele é feito. Existem diversos tipos de
sensores, entre eles os fotodiodos (conversão elétrico/luminosa), os
microfones (conversão elétrico/sonora) e os termistores (conversão
elétrico/térmica). Para o microcontrolador interpretar os dados dos
sensores, este necessita converter o sinal elétrico analógico em um sinal
digital, para isso é usado o conversor A/D. O valor de referência da tensão
que queremos medir deve ser conectado nos pinos de referência do PIC
(𝑉𝑟𝑒𝑓+ 𝑒 𝑉𝑟𝑒𝑓−). Se não for ligado nenhuma tensão neles, o microcontrolador
irá usar o valor de tensão dos pinos de alimentação, ou seja 0 à 5V.
3.1.2 – Exemplo prático
Queremos monitorar uma tensão que varia de 0 à 5V utilizando um
microcontrolador. Se utilizarmos o conversor analógico de 10bits, a
resposta do deste será um número entre 0 à 1023, que corresponde aos
valores de tensão. O número 1023 condiz a 5V e o 0 corresponde ao
0V,portanto para qualquer valor entre 0 e 1023 conseguimos chegar ao
equivalente da tensão com uma simples regra de três.
24
3.2 – REGISTRADORES
3.2.1 - ADCON1
Bits de configuração da tensão de referência e a seleção das portas
analógicas e digitais que serão utilizadas:
Bits 7 e 6: Não implementados, definir como 0;
Bit5 VCFG1: Configuração da tensão de referência;
1 = 𝑉𝑟𝑒𝑓 − (𝑉𝑟𝑒𝑓−)
0 = 𝑉𝑠𝑠
Bit 4 VCFG0: Configuração da tensão de referência:
1 = 𝑉𝑟𝑒𝑓 + (𝑉𝑟𝑒𝑓+)
0 = 𝑉𝐷𝐷
Bits 3-0 PCFG3-PCFG0: Seleção das portas analógicas e digitais, abaixo
segue uma tabela de como deve ser definidos os bits:
25
3.2.2 – ANSEL
Seleciona quais portas serão utilizadas como analógicas e quais serão
digitais, tudo isso através das definições dos bits desse registrador.
Bits 7-0 ANS7-ANS0:
1 = Porta analógica
0 = Porta digital
Este registrador está presente apenas em alguns modelos de PIC.
3.2.3 – ADC_init()
Inicializa e faz as configurações básicas para o conversor A/D.
3.2.4 – ADC_read(Canal_AD)
Esse é o comando que se utiliza para fazer a conversão A/D.
Exemplo de utilização:
Variável = ADC_Read(0);
Essa linha de comando realiza a conversão do valor da tensão que
está sendo aplicada no pino AN0 e o atribui a uma variável qualquer.
26
3.3 – SENSORES ANALÓGICOS
Sensores analógicos são aqueles que sua resposta é um sinal
analógico, ou seja, mesmo limitados por um intervalofinito, podem assumir
infinitos valores de amplitude. Em um sensor analógico “ideal”, com a
mudança de alguma determinada condição, haverá mudança na mesma
proporção alguma de suas propriedades físicas, como resistividade ou
tensão. Nos sensores “reais”, elementos como condições climáticas podem
acarretar em erros de medida. A maioria dos sensores é analógica, já que a
maioria das grandezas que necessitamos medir é analógica. A temperatura,
por exemplo, pode assumir infinitos valores entre dois valores fixados.
Segue abaixo uma tabela com alguns sensores analógicos comumente
utilizados.
Sensor Descrição Onde é encontrado Imagens
LDR (Light
Dependent
Resistor)
É um sensor resistivo, que
varia a sua resistência de
acordo com a intensidade
de luz que está exposto.
É utilizado na iluminação
pública, em câmeras
fotográficas, entre outros.
Termistor
É também um sensor
resistivo, no qual varia a sua
resistência de acordo com a
temperatura que é
submetido.
É utilizado em diversas
aplicações, exemplo ar
condicionado,
automóveis, aviões, entre
outros.
Sensor de peso,
pressão ou
esforço
É um sensor resistivo,
quanto maior a força
exercida sobre ele, menor
será a resistência entre
seus terminais.
Muito utilizado na
indústria, controle de
entrada de matéria prima
e saída do produto final.
Potenciômetro
O potenciômetro é um
componente largamente
utilizado, mas pode ser
usado como sensor de
posição.
Só muito encontrados em
robôs e equipamentos
industriais.
Microfone
É um componente captador
do som, o converte em
sinais elétricos.
É utilizado em aparelhos
telefônicos e aparelhos de
gravação à sensores.
Sensor de
vibração
Converte vibrações em
sinais elétricos.
É utilizado na verificação
do funcionamento de
motores, máquinas,
centrífugas, entre outros.
Acelerômetro
São dispositivos destinados
a medir a aceleração sofrida
por um corpo.
O uso mais comum desse
sensor é em outomóveis,
no acionamento de air-
bags. Também é
encontrado em celulares.
27
3.4 – EXEMPLOS
3.4.1 – Faça um programa para ler a tensão na porta NA0, que varia de 0 à
5V.
Resposta:
int Leitura; //Declaração da variável global inteira
float V; //Declaração da variável global não inteira
Void main(){ // Função principal
TRISA=1; //Define porta como entrada
ADCON1=0b00001110; //Configura apenas AN0 como entrada
analógica
ADC_init(); //Inicializa e configura o conversor A/D
While(1){ //Laço repetitivo
Leitura=ADC_read(0); //Realiza a conversão e atribui à variável leitura
V=Leitura*0.0048875855327468; //Conversão do valor da leitura para
volts
}
}
Obs: A conversão do valor da leitura para volts é realizada com uma simples
regra de três. O conversor irá retornar um valor que varia de 0 à 1023. O
número 1023 condiz a 5V e o 0 corresponde ao 0V. Assim chegamos, na
equação que está no código acima.
28
3.5 – EXERCÍCIOS
1 – Utilize o conversor ADC para ler a grandeza analógica na porta A0 e
escreva o valor lido no display. Utilize o circuito mostrado abaixo.
2 – Efetuar a leitura do sensor de temperatura LM35 e mostrar em uma
display LCD. Utilize o circuito abaixo:
3 – Faça um sensor de corrente para monitorar as condições de operação
dos motores do circuito abaixo utilizando os recursos do conversor A/D.
Mostre o valor de corrente detectado em um LCD. Abaixo segue o circuito a
ser utilizado:
29
4 – PWM (Pulse Widht Modulation)
A Modulação por Largura de Pulso (PWM) é um recurso muito
utilizado para o controle de motores DC (corrente contínua). Utilizando essa
ferramenta, é possível gerar um sinal analógico através de uma saída
digital. A saída gerada é uma onda quadrada com frequência constante e
largura de pulso variável. Estes conceitos estão diretamente relacionados
com o período fixo e o ciclo ativo (duty cycle), respectivamente.
A frequência de uma onda pode ser definida como a quantidade de
vezes em que uma onda oscila no tempo. Já o período, é o tempo gasto
para uma oscilação. O duty cycle define o tempo de sinal ativo (nível lógico
alto) em um período fixo. Assim, quando temos um duty cycle de 100%,
temos nível lógico alto por todo o período. Um duty cycle de 50% define a
metade do período em nível lógico alto e a outra metade em nível lógico
baixo. Se uma saída TTL for utilizada, a tensão média de saída em um duty
cycle de 50% será 2,5V. Estes conceitos são demonstrados na figura
abaixo. Devemos lembrar que o PWM nem sempre se inicia em nível lógico
alto, podendo iniciar em zero.
O microcontrolador PIC18F4520 possui internamente 2 módulos CCP
(Capture/Compare/PWM Module), CCP1 e CCP2. Podemos manipular com
grande facilidade as instruções para geração de sinal PWM no MikroC.
30
4.1 – COMANDOS
Os comandos para manipular o módulo CCP1 são os seguintes:
• PWM1_Init
• PWM1_Set_Duty
• PWM1_Start
• PWM1_Stop
4.1.1 – PWM1_Init
No MikroC utilizamos a função Pwm1_Init() para informar a
frequência do sinal PWM:
Sintaxe:
Onde:
valor_da_freqüência: fator da freqüência em Hz do sinal PWM.
PS.: Consultar datasheet do PIC utilizado para saber a freqüência de
oscilação.
Como por exemplo:
PWM1_Init (4000) //inicia pwm com freqüência de 4khz
4.1.2 – PWM1_Set_Duty
Através da função PWM1_Set_Duty () podemos controlar o duty cycle
do sinal PWM. A configuração da porcentagem do Duty Cycle é feita através
de uma variável de 8 bits, ou seja, os valores inseridos devem estar no
intervalo de 0-255. Com isso, se o valor do duty cycle é "0" a porcentagem
correspondente será igual a 0%, para "127" será igual a 50% e para "255"
igual a 100%.
Sintaxe:
Onde:
valor_duty_cycle: valor do tipo char (0 à 255) que determina a
porcentagem do duty cycle PWM.
Exemplo:
PWM1_Set_Duty (192); // carrega duty cycle para 75%
31
4.2 - EXEMPLOS
4.2.1 – Variando a velocidade de um motor
Um sinal de PWM foi programado, onde uma alteração do duty cycle
no código, varia a velocidade do motor. A variação na onda pode ser
vizualizada através do osciloscópio.
unsigned short duty_variavel;
void main() {
trisc=0;
portc=0;
PWM1_init(8000);
duty_variavel = 250;
PWM1_Set_Duty(duty_variavel);
PWM1_start();
while(1){
}}
Circuito para o Exemplo 1
4.2.2 – Alterando o duty cycle com um botão
O exemplo a seguir utiliza o PIC18f4550 que possui duas saídas para
PWM. O ajuste do duty cycle é feito através de uma variável denominada
current_duty.
Os botões ligados aos pinos RB0 e RB1 são dedicados ao PWM1.
Quando acionamos a porta RB0 o contador aumenta, aumentando assim o
duty cicle. Já o acionamento da porta RB1 faz decrescer o valor do mesmo.
32
unsigned short duty_atual;
void main() {
ANSEL = 0; // Configura as portas analógicas como digitais
ANSELH = 0;
C1ON_bit = 0; // Desabilita o comparador 1
PORTB = 255;
TRISB = 255; // configura PORTA como entrada
PORTB = 0; // define PORTB inicialmente em 0
TRISB = 0; // configura PORTB como saída
PORTC = 0; // define PORTC inicialmente em 0
TRISC = 0; //configura PORTC como saída
PWM1_Init(5000); // Habilita o PWM1 com frequencia de 5KHz
duty_atual = 16; // Valor inicialda variável current_duty
PWM1_Start(); // Inicia PWM1
PWM1_Set_Duty(duty_atual); // Define o duty atual para o PWM1
while (1) { // Loop infinito
if (RB0_bit) { // botão em RB0 pressionado
Delay_ms(40);
duty_atual++; // Incrementa o valor de duty_atual
PWM1_Set_Duty(duty_atual);
}
if (RB1_bit) { // Botão em RB1 pressionado
Delay_ms(40);
duty_atual--; // decrement duty_atual
PWM1_Set_Duty(duty_atual);
}
Delay_ms(5);
}
}
Circuito para o Exemplo
33
4.3 – EXERCÍCIOS
1 – Seguindo o esquemático abaixo, faça um programa que ajuste a faixa
de PWM de acordo com a entrada analógica de tensão, o potenciômetro
definirá a tensão na entrada analógica. Resumindo, controle a velocidade do
motor com um potenciômetro, e escreva o duty cicle do PWM no display
LCD.
34
5 – TIMER
5.1 – INTRODUÇÃO
A grande jogada dos timer's, em um microcontrolador, é que você
não precisa manter o processador travado em delay aguardando o
momento de realizar uma função. Em alguns casos, sem o uso de timer's,
seria quase que impossível de realizar determinadas tarefas em conjunto
(controle de servo motores por exemplo).
A ineficiência do delay, em alguns casos, pode ser comparada a uma
pessoa que tem compromissos durante o dia só que, ao invés de olhar no
relógio ou usar um despertador, a pessoa fica parada só contando os
segundos até chegar o momento dela realizar determinada tarefa (almoçar,
trabalhar, etc.) desperdiçando tempo que poderia ser gasto com outras
tarefas.
5.2 – TIMER/COUNTERS
Os timer's são registradores que servem como contadores em que, a
cada pulso de clock, ele realiza um incremento nesse registrador (timer =
timer + 1 ou timer++). Após o timer incrementar até o seu valor limite
(que depende da quantidade de bit do timer que você esta utilizando)
ocorre o que chamamos de "estouro de contagem", este então é zerado e é
acionada a interrupção, o mesmo é limitado pela quantidade de bit que
comporta:
8 bit , Valores de 0-255
16 bit Valores de 0-65536
32 bit, Valores de 0-4294967296
Para uma melhor visualização da configuração dos TIMERS vamos
tomar como exemplo o PIC18F4520 que possui internamente 4 TIMERS:
TIMER0
TIMER1
TIMER2
TIMER3
Vamos estudar cada TIMER logo a seguir.
35
5.3 – CLOCK
O clock de um timer está intimamente ligado com o cristal oscilador
também conhecido por cristal que comumente varia na faixa de 1Mhz –
20Mhz. A entrada de clock utilizada para incremento do timer pode ser
configurada da seguinte forma.
5.3.1 – Interno/Temporização baseado no ciclo de maquina
O clock do oscilador (cristal) utilizado no microcontrolador é dividido
automaticamente por 4, ou seja, se o oscilador utilizado pelo seu
microcontrolador for de 4 MHz, o clock utilizado para a contagem do timer
será de 1MHz ( 4.000.000 / 4 = 1.000.000).
5.3.2 – Externo
O clock é gerado a cada mudança de estado do sinal externo
(proveniente dos pinos para essa finalidade). O incremento pode ser
configurado para a borda de subida ou borda de descida.
5.4 – PRESCALER
Em seguida, esse clock passa por um prescaler programável antes de
chegar aos timers. Cada timer, registrador ou ainda temporizador é
característica de cada microcontrolador, que por sua vez possui um
prescaler dedicado.
O prescaler funciona como um divisor de frequência de 8 bits em que
o valor que você carregar nele, que deve ser múltiplo de 2, funcionará como
o fator de divisão, ou seja, você pode dividir o sinal de entrada no prescaler
em até 256 vezes.
A configuração do prescaler pode ser efetuada de duas formas:
Configuração direta pela plataforma MikroC, utilizada no exemplo, ajusta
pela ferramenta Project -> Edit Project ->Timer Prescale;
Através de um registrador dedicado para cada timer.
36
5.5 – REGISTRADORES
5.5.1 – TIMER0
T0CON é um registrador dedicado responsável pela configuração do
prescaler do temporizador TIMER0 do PIC18f4520, abaixo temos o registro
e a função de cada bit.
PSA: Bit de seleção do Prescaler
0 = prescaler será utilizado
1 = Prescaler não será utilizado. Neste caso, a tabela acima não tem valor,
ou seja, conseguimos então Prescaler 1:1 – a cada pulso o timer0 será
incrementado.
T0SE: Bit que faz a seleção da borda
0 = sensível à borda de subida em T0CKI
1 = sensível à borda de descida em T0CKI
T0CS: Bit que seleciona como será o clock do Timer0
0 = Cristal interno incrementa o timer
1 = Pulso externo aplicado no pino T0CKI incrementa o timer
T08BIT: Bit que seleciona o modo de operação
0 = 16 Bits
1 = 8 Bits
37
TMR0ON: Bit que ativa/desativa o Timer0
0 = Timer0 desabilitado
1 = Timer0 habilitado
Existe também 2 Registradores que trabalham juto com o Timer0. São eles:
TMR0L: Responsável pela contagem da parte baixa (0 a 255).
TMR0H: Responsável pela contagem da parte alta (0 a 65535).
Exemplo de Utilização:
Utilizaremos o Timer0 para piscar um led, ficando aceso 1 segundo e
apagado por 1 segundo, como se indicasse o funcionamento de algum
equipamento. Para isso, utilizaremos um cristal de 4MHz e um Prescaler de
1:64;
Tempo = ciclo de máquina * Prescaler * X
Onde X é o valor a ser colocado nos Registradores e dependendo deste
valor utilizaremos modo 8 bits (valores até 256) ou 16 bits (valores até
65536).
1s = 1µs * 64 * X
X = 1s / (64 * 1µs)
X = 15625
Como valor é maior que 256 teremos que usar Modo 16 bits
Com isso, fazemos a seguinte conta: 65536 – 15625 = 49911
Este valor 49911 deve ser convertido de decimal para hexadecimal = C2F7
Então, TMR0H = C2 e TMR0L = F7
38
EXEMPLOS
1 – Se tivermos conectado ao nosso PIC um cristal de 8 MHz e o
TIMER0 seja programado como temporizador, com prescaler de 1:4, modo
8 bits e contagem inicial em TMR0L = 0. Calcule o tempo de estouro do
timer para este caso.
Resolução
A fómula para cálculo do tempo de estouro é:
Tempo de estouro = ciclo*prescaler*(Modo 8 ou 16 bits – valor incial
TMR0)
Com isso, temos:
Tempo de estouro =
1
8
4
. 4 . (255 − 0) = 510𝑢𝑠
2 – O objetivo do programa a seguir é ativar o contador do TIMER0,
utilizando PIC18F4520 com um cristal de 8MHz.
void main(){
TRISD = 0; // 'define portd como saída
PORTD = 0; // 'zera portd
/*
'******************************calculo temporização 1 segundo ***************
'calculo de temporização de 1 segundo:
'tempo = ciclo_maquina * prescaler * (modo 8/16 - valor inicial)
'logo
'1000.000us = 0.5us * 128 * (65536 - valor_inicial)
'valor inicial = 49911 ou C2F7h */
T0CON = 0B11101000;//'modo contador, prescaler off, borda descida, modo 8bits
TMR0L = 246; //'contar 10 pulsos | 256 - 10 = 246 carrega valores de contagem
TMR0H = 0;
INTCON.TMR0IF = 0; //'apaga flag de estou do timer0
while (1){
if (INTCON.TMR0IF==1){
PORTD.RD0 = ~ PORTD.RD0; // 'inverte o valor do led1
TMR0L = 246; //'recarga do timer0
INTCON.TMR0IF = 0; //'apaga flag de estou do timer0
}
}
}
39
Circuito para o Exemplo 2
EXERCICIOS
1 – Se tivermos conectado ao nosso PIC um cristal de 4 MHz e o
TIMER0 seja programado como temporizador, com prescaler de 1:2, modo
8 bits e contagem inicial em TMR0L= 0. Calcule o tempo de estouro do
timer para este caso.
2 – Se tivermos conectado ao nosso PIC um cristal de 20 MHz e o
TIMER0 seja programado como temporizador, com prescaler de 1:64,
modo 16 bits e contagem inicial em TMR0L = 0 e TMR0H=0. Calcule o
tempo de estouro do timer para este caso.
3 – Se tivermos conectado ao nosso PIC um cristal de 20 MHz e o
TIMER0 seja programado como temporizador, com prescaler de 1:256,
modo 16 bits e contagem inicial em TMR0L = 0 e TMR0H=0. Calcule o
tempo de estouro do timer para este caso.
4 – Se tivermos conectado ao nosso PIC um cristal de 20 MHz e o
TIMER0 seja programado como temporizador , modo 16 bits, contagem
inicial em TMR0L = 0 e TMR0H=0 e tempo de estouro de 1 segundo. Calcule
o prescaler utilizador.
5 – O TIMER0 foi programado como temporizador , modo 16 bits,
contagem inicial em TMR0L = 0 e TMR0H=0, prescaler de 1:128 e tempo de
estouro de 1 segundo. Calcule a frequência do cristal utilizado.
6 – Você precisa de um tempo de estouro de 60ms, o seu circuito possui
um cristal oscilador de 4Mhz e o timer0 do seu microcontrolador está
configurado com prescaler de 1:256 e 8bits. Calcule os valores iniciais de
TMR0L e TRM0H.
7 – Você precisa de um tempo de estouro de 0,1s, o seu circuito possui um
cristal oscilador de 8Mhz e o timer0 do seu microcontrolador está
40
configurado com prescaler de 1:4 e 16bits. Calcule os valores iniciais de
TMR0L e TMR0H.
8 – Faça um cronômetro em segundos utilizando o timer0, faça o visor do
cronômetro em um LCD. Utilize o circuito abaixo.
9 – Programe um relógio utilizando os recursos do timer0. Utilize o circuito
do exercício anterior.
5.5.2 – TIMER1
T1CON
RD16
T1CKPS
1
T1CKPS
0
T10SCE
N
T1SYN
C
TMR1C
S
TMR1O
N
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
RD16: bit de leitura e escrita em 16bits (utilizado para o modo comparador
do canal CCP)
1 – leitura e escrita em 16 bits habilitada
0 – leitura e escrita em 16 bits desabilitada
T1CKPS1 e T1CKPS0: Bits de seleção de fonte de prescaler
T1CKPS1 T1CKPS0 Prescaler
1 1 1:08
1 0 1:04
0 1 1:02
0 0 1:01
41
T1OSCEN: Habilitação do oscilador externo de baixa frequência nos pinos
T1OSO e T1OSI
0 - Oscilador desligado
1 - Oscilador Ligado
T1SYNC: Controle do sincronismo interno. Caso TMR1CS = 0, esse bit é
descartado.
0 - Sincronismo ligado
EXEMPLOS
1 – Este programa tem por objetivo ativar a temporização máxima do
TIMER1 utilizando cristal de 8Mhz.
void main(){
/*'******************************calculo temporização timer1 ***************
'calculo de temporização máxima do timer1
'tempo = ciclo_maquina * prescaler * (modo 16 - valor inicial)
'logo
'Tempo = 0.5us * 8 * (65536 - 0)
'Tempo = 262.144 us ou 262ms */
TRISD = 0; //'define portb como saida
PORTD = 0; //'apaga todos os leds conectados ao portd
T1CON = 0b10110001; //'liga TIMER1, prescaler 1:8, modo 16bits.
TMR1L = 0; //'carrega valor de contagem baixa do TIMER1
TMR1H = 0; //'carrega valor de contagem alta do TIMER1
PIR1.TMR1IF = 0; //'apaga flag de estouro do TIMER1
while (1){
if (PIR1.TMR1IF == 1) {
PORTD.RD0 = ~PORTD.RD0; //'inverte o valor do led1
TMR1L = 0; //'carrega valor de contagem baixa do TIMER1
TMR1H = 0; //'carrega valor de contagem alta do TIMER1
PIR1.TMR1IF = 0; //'apaga flag de estouro do TIMER1
}
}
}
EXERCÍCIOS
1 – Faça um cronômetro em segundos utilizando o timer1, faça o visor do
cronômetro em um LCD. Utilize o circuito abaixo.
2 – Programe um relógio utilizando os recursos do timer1. Utilize o circuito
do exercício anterior.
42
5.5.3 – TIMER2
TMR2: Registrador de contagem do TIMER2 (8 bits);
PR2: Registrador de comparação do TIMER2
Dizemos que o TIMER2 é um timer com recarga automática, pois
quando o valor carregado em PR2 é igual ao de contagem TMR2, o valor de
TMR2 é zerado e inicia-se uma nova contagem, ou melhor dizendo,
temporização.
Através do registrador T2CON, podemos configurar o modo de
operação do TIMER2, tais como o valor do prescale e postcale e ligar ou
desligar o timer2.
T2CON
TOUTP
S3
TOUTP
S2
TOUTP
S1
TOUTP
S0
TMR2O
N
T2CKP
S1
T2CKP
S0
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
TOUTPS3, TOUTPS2, TOUTPS1 e TOUTPS0: Bits de ajuste do postscale;
TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 Postscale
0 0 0 0 1:01
0 0 0 1 1:02
0 0 1 0 1:03
0 0 1 1 1:04
0 1 0 0 1:05
0 1 0 1 1:06
0 1 1 0 1:07
0 1 1 1 1:08
1 0 0 0 1:09
1 0 0 1 1:10
1 0 1 0 1:11
1 0 1 1 1:12
1 1 0 0 1:13
1 1 0 1 1:14
1 1 1 0 1:15
1 1 1 1 1:16
O funcionamento do postcale é muito semelhante ao prescaler, sua
diferença básica está na contagem. Em vez de contar pulsos de ciclos de
máquina, o postscale conta n comparações do TMR2 com PR2. Após n
comparações, o flag de estouro do TIMER2 é sinalizado com nível lógico 1.
43
TMR2ON: Habilitação do TIMER2;
0 - TIMER2 desligado
1 - TIMER 2 ligado
T2CKPS1 T2CKPS0: Bits responsáveis pelo ajuste de prescaler;
T2CKPS1 T2CKPS0 Prescaler
0 0 1:01
0 1 1:04
1 X 1:16
Obs: X pode ser 1 ou 0.
EXEMPLOS
1 – Se tivermos conectado ao nosso PIC um cristal de 20 MHz e o
TIMER2 seja programado como temporizador, com prescaler de 1:1, com
postscaler de 1:12 e PR2=150 . Calcule o tempo de estouro do timer para
este caso.
Resolução
A fómula para cálculo do tempo de estouro é:
Tempo de estouro = ciclo*prescaler*postscaler*(PR2)
Com isso, temos:
Tempo de estouro =
1
20
4
. 1 . (12) ∗ 150 = 360𝑢𝑠
EXERCÍCIOS
1 – Se tivermos conectado ao nosso PIC um cristal de 8 MHz e o
TIMER2 seja programado como temporizador, com prescaler de 1:4, com
postscaler de 1:5 e PR2=255 . Calcule o tempo de estouro do timer para
este caso.
2 – Se tivermos conectado ao nosso PIC um cristal de 36 MHz e o
TIMER2 seja programado como temporizador, com prescaler de 1:2, com
postscaler de 1:4 e PR2=15 . Calcule o tempo de estouro do timer para
este caso.
3 – Se tivermos conectado ao nosso PIC um cristal de 4 MHz e o
TIMER2 seja programado como temporizador, com prescaler de 1:8, com
postscaler de 1:16 e tempo de estouro 12800us. Calcule o tempo de
estouro do timer para este caso.
4 – Faça um cronômetro em segundos utilizando o timer2, faça o visor do
44
cronômetro em um LCD. Utilize o circuito abaixo.
5 – Programe um relógio utilizando os recursos do timer2. Utilize o circuito
do exercício anterior.
5.5.4 – TIMER3
O TIMER3 é um temporizador e contador de 16 bits. Possui internamente
dois registradores de 8 bits, TMR3L e TMR3H, que juntos formam um
registrador de 16 bits (contagem de 0 a 65535). Diferente do TIMER1, o
TIMER3 somente pode operar no modo 16 bits.
Através do registrador T3CON, podemos configurar o modo de operação
do TIMER3, tais como valor do prescale,, ligar ou desligar o TIMER3,
seleção de clock interno ou externo (contador) e fonte do timer para o
módulo CCP do PIC.
O registrador de controle do TIMER3;
T3CON
RD16 T3CCP2 T3CKPS1 T3CKPS0 T3CCP1 T3SYNC TMR3CS TMR3ON
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
RD16: bit de leitura e escrita em 16bits
0 – leitura e escrita em 16 bits desabilitada (utilizado no modo CCP)
1 – leitura e escrita em 16 bits habilitada (utilizado no modo CCP)
T3CCP2 T3CCP1: Habilita a fonte de timer para o módulo CCP;
T3CCP2 T3CCP1 Prescaler
0 0 TIMER1 fonte de timer para os módulos CCP
0 1 TIMER1 fonte de timerpara o módulo CCP1
1 0 TIMER3 fonte de timer para o módulo CCP2
1 1 TIMER3 fonte de timer para os módulos CCP
T3CKPS1 T3CKPS0: bits de ajuste do prescaler do TIMER3;
T3CKPS1 T3CKPS0 Prescaler
0 0 1:01
0 1 1:02
1 0 1:04
1 1 1:08
45
T3SYNC: Controle de sincronismo interno. Caso TMR3CS = 0, este bit é
descartado;
obs: este bit somente é utilizado para trabalhar com o periférico RTC
(segundo oscilador ligado aos pinos T1OSO e T1OSI).
0 - Sincronismo ligado
1 - Sincronismo desligado
TMR3CS: Seleção de Clock
0 - Clock Interno -TIMER3 programado como Temporizador ( clock baseado
no ciclo de máquina)
1 - clock externo no pino T1CK1 - Habilitar modo contador do TIMER1
TMR3ON: Habilitação do TIMER3;
0 - TIMER3 desligado
1 - TIMER3 ligado
EXEMPLOS
1 – Faça um cronômetro em segundos utilizando o timer3, faça o visor do
cronômetro em um LCD. Utilize o circuito abaixo.
EXERCÍCIOS
1 – Programe um relógio utilizando os recursos do timer3. Utilize o circuito
do exercício anterior.
46
6 – INTERRUPÇÕES
6.1 – FUNCIONAMENTO DAS INTERRUPÇÕES
Nessa parte da apostila, daremos início à uma explicação
generalizada a respeito das interrupções e para que servem. Em seguida
entraremos em detalhes.
Como se deve imaginar, uma interrupção tem a função de
interromper a execução do programa imediatamente. Com isso, o
programador tem a opção de tomada de atitudes instantâneas. Por serem
ações tratadas diretamente pelo hardware, as interrupções são rápidas e
disponíveis em qualquer ponto do sistema. Imagine você realizando algum
trabalho em sua casa e de repente o telefone toca. Você irá pausar sua
atividade, atender o telefone e em seguida retornar para seus afazeres de
onde havia parado. De maneira análoga à situação acima, quando uma
interrupção é ativada, o programa é imediatamente pausado e uma função
estabelecida pelo programador é executada, em seguida, o programa
retorna sua execução de onde havia parado. Essa ferramenta se torna
muito útil na solução de problemas de maior complexidade. Abaixo seguem
algumas interrupções existentes no PIC e alguns exemplos de aplicação.
6.2 – INTERRUPÇÕES DO PIC
Nos Modelos mais antigos de microcontroladores da família PIC não
havia interrupções, contudo, hoje em dia elas estão presentes em todos os
modelos mais novos. A quantidade de interrupções e suas finalidades são
diversas e variam dependendo do modelo do PIC selecionado. Veremos
nessa apostila apenas as interrupções por timer e externa.
6.3 – INTERRUPÇÕES POR TIMER
Ocorrem sempre que um dos contadores de tempo interno,
denominados TMR0 (Timer 0) e TMR1 (Timer 1), estouram. O TMR0 pode
ser tanto um contador de 8 bits (0-255) quanto um contador de 16 bits (0-
65535). Quando o mesmo se encontra configurado com 8 bits, sempre que
ele passar de 255 para 0, ocorrerá a interrupção. Já no caso do TMR1, que
se trata de um contador com 16 bits, a interrupção ocorrerá quando o
mesmo passar de 65535 para 0. Também há a interrupção por TMR2 (Timer
2). Essa é uma interrupção que também conta com um contador de 8 bits
de precisão, porém se difere da interrupção por TMR0 por não ocorrer
necessariamente quando o timer estoura o limite (255) e sim por atingir um
valor pré-definido em outro registador especial (PR2). Esse tipo de
interrupção é geralmente utilizada para a contagem de tempo. Como ela
pode ocorrer a qualquer momento, a contagem fica precisa, sendo
desnecessário fazer verificações periódicas durante a execução do programa
para assegurar que o tempo está sendo contado. TMR0 e TMR1 podem ser
incrementados tanto pelo clock da máquina quanto por um sinal externo.
Neste caso, eles funcionam como contadores de pulsos, podendo ser
utilizados para outras finalidades.
47
6.4 – INTERRUPÇÃO EXTERNA
Esse tipo de interrupção ocorre quando um sinal externo é enviado à
uma porta específica (RB0, RB1 e RB2 na família 18F) do PIC, caso ela
esteja configurada como entrada. A interrupção externa possibilita a
identificação e o processamento imediato de um sinal externo. Ela é
utilizada, por exemplo, para reconhecimento de um botão ou outro sinal
que exija resposta imediata.
6.5 – IMPLEMENTANDO AS INTERRUPÇÕES
Para implementarmos uma interrupção, é necessário manipularmos
alguns registradores. Mas afinal o que são esses registradores? São apenas
endereços de memória especiais denominados SFR’s (Special Function
Registers) utilizados para guardarem as configurações e o estado de
funcionamento atual do microcontrolador. Cada registrador é composto por
8 bits e cada bit é responsável por ativar/desativar uma configuração
específica. Veremos mais abaixo os registradores reservados para a
configuração das interrupções que iremos utilizar e o significado da
ativação/desativação de seus respectivos bits.
Note abaixo que os comandos dos registradores são, em alguns
casos, bem sugestivos. Como por exemplo, os comandos TMR0IE ou
TMR0IF que nada mais são do que configurações referentes ao timer 0. As
terminações IE significam Interrupt Enable (Habilitar Interrupção) e as
terminações IF significam Interrupt Flag (Flag de Interrupção). Sendo
assim, no registrador INTCON (Interrupt Control), se quisermos
ativar/desativar o timer 0, basta fazermos a seguinte linha de comando:
INTCON.TMR0IE = x
Onde x pode ser 1 (habilitar) ou 0 (desabilitar).
Você deve estar se perguntando o que são esses flags citados no
texto acima. Os flags (na tradução, bandeiras) são sinalizadores que
indicam a entrada de uma determinada interrupção. Daqui para baixo esse
termo será sempre utilizado. Por exemplo:
INTCON.TMR0IF = x
Onde x pode ser 1 (Entrou na Interrupção por estouro do timer 0) ou
0 (ainda não ocorreu interrupção por estouro do timer 0).
48
6.5.1 – Registradores
INTCON
GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF
GIE -> Chave geral para habilitar o tratamento de interrupções.
0 – Microcontrolador não irá tratar nenhuma interrupção.
1 – Microcontrolador irá tratar interrupções.
GIEH -> Chave geral para habilitar o tratamento de interrupções de alta
prioridade.
0 – desabilita interrupção de alta prioridade
1 – habilita interrupção de alta prioridade.
PEIE -> Chave individual para habilitar interrupção dos periféricos.
0 – desabilita interrupção dos periféricos.
1 – habilita interrupção dos periféricos.
GIEL -> Chave geral para habilitar o tratamento de interrupções de baixa
prioridade.
0 – desabilita interrupção de baixa prioridade
1 – habilita interrupção de baixa prioridade.
TMR0IE -> Chave individual que ativa interrupção do TIMER0.
0 – desabilita.
1 – habilita.
INT0IE -> Chave individual que ativa interrupção do INT0.
0 – desabilita.
1 – habilita.
RBIE -> Chave individual que ativa interrupção por mudança de estado (RB4
à RB7).
0 – desabilita.
1 – habilita.
49
TMR0IF -> Flag de sinalização da interrupção do estouro do TIMER0.
0 – não ocorreu interrupção por estouro do TIMER0.
1 – ocorreu interrupção por estouro do TIMER0.
INT0IF -> Flag de sinalização da interrupção da mudança de Estado do INT0.
0 – não ocorreu interrupção por mudança de Estado no pino RB0.
1 – ocorreu interrupção por mudança de Estado no pino RB0.
RBIF -> Flag de sinalização da interrupção da mudança de Estado (RB4 a
RB7).
0 – não ocorreu interrupção por mudança de Estado nos pinos RB4 à RB7.
1 – ocorreu interrupção por mudança de Estado nos pinosRB4 à RB7.
INTCON2
RBPU INTEDG0 INTEDG1 INTEDG2 ---------- TMR0IP --------- RBIP
RBPU -> Chave que define se vai haver ou não resistores de Pull-Up no
PORTB.
0 – Habilita resistores de pull-up.
1 – desabilita resistores de pull-up.
INTEDG0 -> Define a borda que acionará o evento de interrupção no INT0.
0 – evento ocorrerá na borda de descida.
1 – evento ocorrerá na borda de subida.
INTEDG1 -> Define a borda que acionará o evento de interrupção no INT1.
0 – evento ocorrerá na borda de descida.
1 – evento ocorrerá na borda de subida.
INTEDG2 -> Define a borda que acionará o evento de interrupção no INT2.
0 – evento ocorrerá na borda de descida.
1 – evento ocorrerá na borda de subida.
50
TMR0IP -> Define a prioridade da interrupção do TIMER0.
0 – definida como baixa prioridade.
1 – definida como alta prioridade.
RBIP -> Define a prioridade da interrupção da mudança de Estado (RB4 à
RB7).
0 – definida como baixa prioridade.
1 – definida como alta prioridade.
INTCON3
INT2IP INT1IP ---------- INT2IE INT1IE --------- INT2IF INT1IF
INT2IP -> Define a prioridade da interrupção externa no INT2.
0 – definida como baixa prioridade.
1 – definida como alta prioridade.
INT1IP -> Define a prioridade da interrupção externa no INT1.
0 – definida como baixa prioridade.
1 – definida como alta prioridade.
INT2IE -> Chave individual que ativa interrupção do INT2.
0 – desabilita.
1 – habilita.
INT1IE -> Chave individual que ativa interrupção do INT1.
0 – desabilita.
1 – habilita.
INT2IF -> Flag de sinalização da interrupção da mudança de Estado do INT2.
0 – não ocorreu interrupção por mudança de Estado no pino RB2.
1 – ocorreu interrupção por mudança de Estado no pino RB2.
INT1IF -> Flag de sinalização da interrupção da mudança de Estado do INT1.
0 – não ocorreu interrupção por mudança de Estado no pino RB1.
1 – ocorreu interrupção por mudança de Estado no pino RB1.
51
PIE1
PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE
PSPIE -> Chave individual que habilita interrupção da Porta Paralela Escrava
(R/W);
0 – desabilita.
1 – habilita.
ADIE -> Chave individual que habilita interrupção do Conversor A/D.
0 – desabilita.
1 – habilita.
RCIE -> Chave individual que habilita interrupção por recebimento de dados
na USART.
0 – desabilita.
1 – habilita.
TXIE -> Chave individual que habilita interrupção por transmissão de dados
na USART.
0 – desabilita.
1 – habilita.
SSPIE -> Chave individual que habilita interrupção do Módulo SSP (Máster
Syncronous Serial Port).
0 – desabilita.
1 – habilita.
CCP1IE -> Chave individual que habilita interrupção de Captura/Compare no
TIMER1.
0 – desabilita.
1 – habilita.
TMR2IE -> Chave individual que habilita interrupção por igualdade entre
TMR2 e PR2.
0 – desabilita.
1 – habilita.
52
TMR1IE -> Chave individual que habilita interrupção de estouro do TIMER1.
0 – desabilita.
1 – habilita.
PIR1
PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF
PSPIF -> Flag de sinalização da interrupção da Porta Paralela Escrava (R/W);
0 – não ocorreu leitura ou escrita.
1 – ocorreu leitura ou escrita na porta paralela.
ADIF -> Flag de sinalização da interrupção do Conversor A/D.
0 – conversão não está completa.
1 – conversão finalizada.
RCIF -> Flag que sinaliza interrupção por recebimento de dados na USART.
0 – buffer está vazio.
1 – buffer tem dados recebidos.
TXIF -> Flag que sinaliza interrupção por transmissão de dados na USART.
0 – buffer tem dados para enviar.
1 – buffer está vazio.
SSPIF -> Flag de sinalização do Módulo SSP (Máster Syncronous Serial Port).
0 – aguardando transmissão/recepção.
1 – Transmissão/Recepção está completa.
CCP1IF -> Flag de sinalização da interrupção de Captura/Compare no
TIMER1.
Modo Captura
0 – não ocorreu interrupção por captura no TIMER1.
1 – ocorreu interrupção por captura no TIMER1.
53
Modo Compara
0 – não ocorreu interrupção por comparação no TIMER1.
1 – ocorreu interrupção por comparação no TIMER1.
TMR2IF -> Flag de sinalização da interrupção por igualdade entre TMR2 e
PR2.
0 – não ocorreu interrupção por igualdade entre TMR2 e PR2.
1 – ocorreu interrupção por igualdade entre TMR2 e PR2.
TMR1IF -> Flag de sinalização de estouro do TIMER1.
0 – não ocorreu interrupção por estouro do TIMER1.
1 – ocorreu interrupção por estouro do TIMER1.
54
6.6 – EXEMPLOS
6.6.1 – Interrupção Externa
Segue abaixo um exemplo de aplicação da interrupção externa, onde
três LEDs irão ascender e apagar sucessivamente quando um botão for
pressionado.
Código para o exemplo 5.6.1:
void interrupt(){ //Função reservada para interrupção
if(intcon.int0if==1){ //Verificando se a interrupção já ocorreu (Se Flag = 1)
portc.rc0=1; //Nível Lógico Alto na porta rc0
delay_ms(500); //Seguido de delay de 500 milissegundos
portc.rc0=0; //Nível Lógico baixo na porta rc0
portc.rc1=1; //Nível Lógico Alto na porta rc1
delay_ms(500); //Seguido de delay de 500 milissegundos
portc.rc1=0; //Nível Lógico baixo na porta rc1
portc.rc2=1; //Nível Lógico Alto na porta rc2
delay_ms(500); //Seguido de delay de 500 milissegundos
portc.rc2=0; //Nível Lógico baixo na porta rc2
intcon.int0if=0; //Limpeza do Flag da interrupção externa (Flag = 0)
}
}
void main() {
trisb.rb0=1; // Porta rb0(responsável pela interrupção externa Int0) como entrada.
trisc=0; //Definindo as portas c como saídas
portc=0; //Colocando as portas c inicialmente em nível lógico baixo
intcon=0b11010000; //Ativando interrupção geral, periféricos e externa INT0
intcon2.intedg0=0; //Ativar interrupção na borda de descida (Quando o botão for solto)
while(1){}
}
Figura 2 - Circuito para o exemplo 5.6.1
55
6.6.2 – Interrupção por timer 0
Nesse exemplo utilizaremos o timer 0 em 8bits para piscar um LED
em intervalos de 1 segundo, como se o mesmo indicasse o funcionamento
de algum equipamento. Para isso, utilizaremos um prescaler de 1:4 e um
oscilador de 4Mhz. Isso nos garante que o estouro do timer 0 se dará em
intervalos de 1,02ms. Sendo assim, a cada 1000 estouros, teremos
aproximadamente 1 segundo.
unsigned cont; //Variável utilizada como contador
void interrupt(){ //Função reservada para a interrupção
cont++; //Acréscimo do contador
TMR0l=0; //Timer 0 em zero
INTCON=0b00100000; //Ativa a interrupção por TMR0 e limpa o flag da mesma.
}
void main() {
T0CON = 0b11000001; //Ativa o TMR0, configura para 8 bits e prescaler 1:4
trisc.rc4 = 0;
portc.rc4=0;
TMR0L=0;
TMR0H=0;
INTCON = 0b10100000; //Habilita Interrupção Geral e a Interrupção por TMR0.
cont=0; //Inicializa o Contador
while(1){
if(cont == 1000){ //Se o cont = 1000 -> 1,02x1000 = 1,02s
portc.rc4=~portc.rc4; //Troca estado da porta rc4
cont = 0; //Zera o contador}
}
}
Figura 3 - Circuito para o exemplo 5.6.2
56
6.6.3 – Interrupção por timer 2
Esse exemplo faz com que um motor fique desligado durante 5
segundos e em seguida permaneça ligado durante 10 segundos. Quando
desligado, um LED vermelho permanece aceso e de maneira análoga,
quando ligado, um LED verde permanece aceso. Para esse exemplo,
utilizamos um oscilador interno de 8Mhz e TMR2 com prescaler de 1:16,
PR2 = 250 e postscale de 1:10. Com isso, através dos cálculos do Timer 2,
sabemos que:
Tempo de estouro = prescaler*postscale*ciclo de máquina*(PR2)
Tempo de estouro = 20.000us
Motor ligado = 20.000*500 = 10 segundos
Motor desligado = 20.000*250 = 5 segundos
#define motor portc.rc0
unsigned int cont; //Declarando o contador
unsigned char alt; //Declarando uma variável para alternar estados
void interrupt(){
cont++; //Incremento do contador a cada estouro do timer 2
if (cont==250 && alt == 0){ //Condição para ficar 5 segundos desligado
motor=~motor; //Alterna o estado do motor
portb.rb1=1; //LEDS de funcionamento
portb.rb0=0;
cont=0; //Zera contador
alt=1; //Alterna o estado
}if(cont==500 && alt==1){ //Condição para ficar 10 segundos ligado
portb.rb0=1;
portb.RB1=0;
motor=~motor;
alt=0;
cont=0;
}
PIR1.TMR2IF=0; // Limpa o flag do timer2
}
void main() {
trisc.rc0=0;
portc.rc0=0; //Motor inicia desligado
trisb=0;
portb.rb0=1; //LED vermelho inicia ligado
portb.rb1=0;
T2CON = 0b01001111; //Timer 2 ligado, prescaler 1:16, postscale 1:10
PR2 = 250;
INTCON=0b11000000; //Interrupção Geral e de periféricos ligada
PIR1.TMR2IF=0; //Flag do timer2 em zero
PIE1.TMR2IE=1; //Timer2 ativado
while(1){}
}
57
Figura 4 - Circuito para o exemplo 5.6.3
58
6.7 – EXERCÍCIOS PROPOSTOS
1 – Faça com que ao pressionar um botão apenas uma vez, um motor ligue,
ao pressionar duas vezes, dois motores liguem e ao pressionar três vezes
os dois motores desliguem. Monte um circuito como na imagem abaixo e
utilize interrupção externa.
2 – Construir um contador em segundos, utilizando o TMR2 e exibir a
contagem em um display LCD juntamente com um LED indicando a
contagem ao piscar uma vez por segundo. Utilizar o circuito abaixo:
59
Bibliografia:
Wendling, Marcelo; Sensores, on-line do site da Unesp.
http://www2.feg.unesp.br/Home/PaginasPessoais/ProfMarceloWendling/
4---sensores-v2.0.pdf
Patsko, Luís F.; Tutorial Aplicações, funcionamento e utilização de
sensores.
http://www.maxwellbohr.com.br/downloads/robotica/mec1000_kdr5000/t
utorial_eletronica_-_aplicacoes_e_funcionamento_de_sensores.pdf
Acessado em: 10/06/2013
SOUZA, David José de. Desbravando o PIC: ampliado e atualizado
para PIC16F628A. 10. ed. São Paulo: Érica, 2006. 268 p. ISBN 85-7194-
867-4