Escolar Documentos
Profissional Documentos
Cultura Documentos
Introdução
Este tutorial foi feito para as pessoas que têm a eletrônica como diversão e
desejam aprender a utilizar microcontroladores em seus projetos.
Também sou um entusiasta da eletrônica e gosto de entender como as coisas
funcionam. Por isso, escrevo os programas para os microcontroladores em linguagem Assembly.
Se você é como eu, creio que gostará deste tutorial.
Boa leitura!
Mulder_Fox
Membro do fórum de Eletrônica do Clube do Hardware
http://forum.clubedohardware.com.br/eletronica/f39
Parte 1
Pisca LED
Nesta primeira parte, vamos montar um circuito para fazer um LED piscar
numa frequência de aproximadamente um Hz.
Vamos utilizar o microcontrolador PIC16F628A, um dos modelos mais
usados hoje em dia.
Figura 1
1
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 2
2
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Início
Configuração
dos registradores
Inicialização das
variáveis
Passou 0,5
segundo? não
sim
Indica o início
3
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 3
4
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
;***********************************************************************************************
; PROGRAMA: PISCA LED
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /2011
;***********************************************************************************************
Tudo o que for digitado na linha após ponto e vírgula será ignorado pelo
MPLAB na hora da montagem do código, portanto, todas as anotações e comentários têm de virem
precedidos de ponto e vírgula.
Repare no ponto e vírgula no início de cada linha que faz com que o
MPLAB ignore o que está escrito após.
Em seguida vamos incluir no nosso programa o arquivo padrão de
definições do PIC16F628A, usando a diretiva #INCLUDE:
;***********************************************************************************************
#INCLUDE <P16F628A.INC> ;ARQUIVO PADRAO MICROCHIP PARA O PIC16F628A
;***********************************************************************************************
Repare que antes de #INCLUDE <P16F628A.INC> não há ponto e vírgula
e portanto o MPLAB irá executar esse comando.
Observe que foi deixado um espaço a partir da margem esquerda. Isso
porque se o MPLAB encontra uma diretiva na margem esquerda, ele envia uma mensagem de alerta
na hora de criar o arquivo a ser gravado no microcontrolador.
Observe que na mesma linha, antes do comentário “ARQUIVO PADRAO
MICROCHIP PARA O PIC16F628A” há ponto e vírgula, pois, não queremos que o MPLAB leve
em consideração o que está escrito, pois se trata de um comentário (não faz parte do programa).
Repare que após digitar #INCLUDE a cor da letra ficou azul, O MPLAB faz
isso sempre que reconhece o termo como uma diretiva. Isso ajuda a perceber quando escrevemos a
diretiva de forma errada, pois, aí ela não ficará azul.
No arquivo P16F628A.INC é onde constam, além do modelo do
microcontrolador, as correspondências entre os nomes dos registradores e as respectivas posições
que eles ocupam na memória de dados, bem como, entre os nomes de cada bit e sua posição no
registrador, entre outras informações, como tamanho e endereços válidos da memória e bits de
configuração.
O que ocorre é que, para facilitar a vida do programador, as localidades da
memória de dados, ou seja, os registradores, recebem nomes.
Quando o MPLAB vai traduzir o programa para a linguagem de máquina ele
usa essas correspondências.
Se você quiser ver o arquivo P16F628A.INC, localize-o na pasta MPASM
Suite que é uma subpasta da pasta Microchip, criada no diretório onde foi instalado o MPLAB IDE.
O próximo passo é ajustar os Bits de Configuração, também conhecidos por
“fusíveis” ou “fuses”. Isso é feito com a diretiva __CONFIG.
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
5
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
6
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
;**********************************************************************************************
A memória de dados está dividida em quatro bancos (figura 4).
Para ter acesso a qualquer registrador a fim de ler ou alterar o seu valor,
precisamos ajustar os valores dos bits RP0 e RP1 do registrador STATUS, para selecionar o banco
onde se encontra o registrador.
Banco 0: RP0 = 0, RP1 = 0
Banco 1: RP0 = 1, RP1 = 0
Banco 2: RP0 = 0, RP1 = 1
Banco 3: RP0 = 1, RP1 = 1
Neste programa que estamos fazendo, não necessitaremos de acessar os
bancos 3 e 4, pois, os Registradores de Uso Específico que neles se encontram também estão nos
bancos 0 ou 1 e não iremos precisar das posições destinadas a Registradores de Uso Geral que lá se
encontram, pois, nos bastarão os disponíveis no banco 0.
Como o bit RP1 inicializa com o valor 0, basta que alteremos o bit RP0,
para alternar entre os bancos 0 e 1.
Usamos a diretiva #DEFINE para que onde houver a palavra BANCO_0 o
microcontrolador execute a instrução BCF STATUS,RP0.
BANCO_0 é o que chamamos de “label” e poderia ser outra palavra de sua
preferência.
A instrução BCF serve para fazer o valor de um determinado bit igual a 0.
Em BCF STATUS,RP0 STATUS é o nome do registrador e RP0 o
nome do bit deste registrador cujo valor ficará igual a 0.
Nós também usamos a diretiva #DEFINE para que onde houver a palavra
BANCO_1 o microcontrolador execute a instrução BSF STATUS,RP0.
A instrução BSF serve para fazer o valor de um determinado bit igual a 1.
Desta forma, fica mais fácil fazer a comutação entre os bancos de memória,
pois basta escrever a palavra BANCO_0 para que o banco 0 da memória de dados seja selecionado
e a palavra BANCO_1 para o banco 1.
Repare que após digitar BCF e BSF, a cor da letra ficou azul e em negrito. O
MPLAB faz isto com qualquer termo reconhecido como uma instrução. Isto nos ajuda a perceber se
escrevermos uma instrução de forma errada.
7
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 4
8
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
variáveis. Por esse motivo, minha forma preferida para defini-las é com o uso da diretiva CBLOCK:
;**********************************************************************************************
; VARIAVEIS
;**********************************************************************************************
;**********************************************************************************************
; CONSTANTES
9
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
;***********************************************************************************************
; SAÍDA
;***********************************************************************************************
10
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
Após a inicialização e depois de um reset, o microcontrolador executa a
instrução que estiver no endereço 0X00 da memória de programa.
Em seguida ele irá executar a instrução presente no endereço 0X01, depois
0X02 e assim por diante.
A diretiva ORG indica em qual endereço da memória de programa deverá
ser escrita a instrução seguinte. No nosso programa, a instrução GOTO INICIO ocupará o endereço
0X00 da memória de programa, ou seja, será a primeira instrução a ser executada pelo
microcontrolador.
O microcontrolador ao executar esta instrução desvia para o endereço da
memória de programa ocupado pela instrução que estiver após a label INICIO.
Mas, porque fazer esse desvio?
Os microcontroladores possuem um recurso muito útil chamado Interrupção,
que é a interrupção da execução do programa devido a um evento provocado por um periférico do
microcontrolador configurado para isso. Periféricos são os circuitos presentes no microcontrolador
que fazem funções específicas como contadores, geradores de sinal PWM, comparadores, etc...
Quando uma interrupção ocorre, o microcontrolador executa a instrução
presente no endereço 0X04 da memória de programa (no caso do PIC16F628A).
Este é o motivo de fazermos um desvio logo no endereço 0X00. Este desvio
será para depois do fim da rotina de interrupção, pois, o programa não caberia entre o endereço
0X00 e 0X03 e ele não pode ocupar os endereços a partir do 0X04, pois, ali estará a rotina de
interrupção.
Como neste programa não iremos utilizar o recurso da interrupção, iremos
escrever no nosso programa a instrução RETFIE no endereço 0X04 para que se, por acaso, ocorrer
uma interrupção indesejada, o programa possa retornar para o ponto de onde foi desviado:
;**********************************************************************************************
; ROTINA DE INTERRUPÇÃO
ORG 0X04 ;VETOR DAS INTERRUPÇÕES
RETFIE ;RETORNA
11
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
;***********************************************************************************************
Em outra parte deste tutorial falaremos detalhadamente sobre interrupções.
O próximo passo é configurar os Registradores de Uso Específico.
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
MOVLW B'00000111'
MOVWF CMCON ;CONFIGURA RA3, RA2, RA1 E RA0 COMO I/O
;***********************************************************************************************
12
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
13
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
MOVWF CMCON
São apenas esses os Registradores de Uso Específico que precisamos
configurar nesse programa.
;***********************************************************************************************
Inicializar as variáveis é escrever nesses registradores os valores que eles
devem ter na inicialização do programa.
Nós criamos 3 variáveis: DELAY_0, DELAY_1 e DELAY_2.
A variável DELAY_0 deve ser iniciada com o valor decimal 255. A
DELAY_1 com o valor decimal 50 e a DELAY_3 com o valor decimal 13.
Nós criamos constantes para esses valores, que foram INI_DELAY_0, para
o valor 255, INI_DELAY_1, para o valor 50 e INI_DELAY_2, para o valor 13.
Por isso, quando escrevemos MOVLW INI_DELAY_0, o registrador W
assume o valor 255, ocorrendo o mesmo para os outros dois valores.
14
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Vamos lá!
Primeiramente escrevemos a label PRINCIPAL.
Toda vez que quisermos que o programa volte a este ponto escreveremos:
GOTO PRINCIPAL. (goto em Inglês significa vá para).
Há certo preconceito a respeito da instrução GOTO. Algumas pessoas dizem
que se deve evitar usar essa instrução.
O que se deve evitar é usá-la desnecessariamente.
Sempre que for necessário usar essa instrução use-a sem medo. Ela foi feita
para ser usada!
A primeira instrução é DECFSZ DELAY_0,F
Essa instrução decrementa o valor de DELAY_0 e, após, verifica se o valor
ficou igual a 0.
Repare na letra F após o DELAY_0. Ela indica que o resultado será gravado
nele próprio, ou seja, supondo que o valor de DELAY_0 fosse 255, então, ficará igual a 254.
Se a letra fosse W, o resultado seria gravado no registrador W e o registrador
DELAY_0 teria ficado com o mesmo valor de antes, ou seja, W ficaria com o valor de 254 e
DELAY_0 com 255.
Se após decrementar DELAY_0, o seu valor for igual a 0, a próxima linha
do programa será pulada, se não, a próxima linha será executada.
Repare no nome desta instrução: DEC vem de decrementar, F, o registrador
que será decrementado, S, da palavra skip (neste caso, pular, em Inglês) e Z de zero. DECFSZ =
decrementa o registrador F e pula a próxima linha se o resultado for zero.
Se você procurar fazer essas associações entre o nome das instrução e sua
função, irá memorizá-las mais facilmente.
Voltando ao nosso programa, se o resultado da operação for diferente de
zero, a próxima linha do programa será executada.
O que precisamos que ocorra quando a variável DELAY_0 ainda não
chegou a 0?
Precisamos que ela continue a ser decrementada até que o seu valor seja
igual a 0.
Por isso, na próxima linha escrevemos: GOTO PRINCIPAL.
Isso faz com que a variável DELAY_0 seja decrementada novamente até
que seu valor chegue a 0, quando então, a linha após a instrução DECFSZ será pulada.
Neste momento em que DELAY_0 chega a zero, nós iremos reiniciá-la.
Fazemos isto, da mesma forma que fizemos para escrever o seu valor, na
parte de Inicialização das Variáveis:
MOVLW INI_DELAY_0
MOVWF DELAY_0
Se o seu valor não for igual a 0, o programa deverá voltar para decrementar
DELAY_0 e por isto, usamos a mesma instrução de antes:
GOTO PRINCIPAL
15
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
MOVLW INI_DELAY_1
MOVWF DELAY_1
DECFSZ DELAY_2,F
GOTO PRINCIPAL
MOVLW INI_DELAY_2
MOVWF DELAY_2
************************************************************************************************
16
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Agora que passou o tempo de meio segundo, devemos testar o LED para ver
se ele está aceso ou apagado.
O LED estará aceso se o pino RA0 estiver em nível alto e apagado se estiver
em nível baixo.
Para testar o estado deste pino, devemos verificar qual o valor do bit 0 do
registrador PORTA.
Para verificar o valor de um bit, existem 2 instruções: BTFSS E BTFSC.
BTFSS testa o bit e pula a próxima linha se o valor for 1. (BTFSS = testa o
bit do registrador F e pula se estiver setado).
BTFSC testa o bit e pula a próxima linha se o valor for 0. (BTFSC = testa o
bit do registrador F e pula se estiver limpo (clean)).
A escolha entre uma ou outra depende das particularidades do trecho do
programa onde serão usadas.
Neste nosso programa não faz diferença e, portanto, vamos escolher BTFSS:
BTFSS LED
Você se lembra de que nós definimos a label LED para o bit 0 do registrador
PORTA. Portanto, quando escrevemos esta instrução, é aquele bit que será testado.
Vamos supor que o valor do bit seja igual a 1 e, neste caso, a próxima linha
do programa será pulada.
Se o valor do bit 0 do PORTA é igual a 1, significa que o LED está aceso e,
então, devemos apagá-lo e para isso devemos fazer o valor do bit 0 do PORTA igual a 0.
Lembre-se de que para fazer o valor de um bit igual a 0, usamos a instrução
BCF.
BCF LED
17
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Faremos assim:
ACENDE_LED
BSF LED ;ACENDE O LED
GOTO PRINCIPAL ;desvia
Desta forma, quando o valor do bit for igual a 0, o programa será desviado
para onde está escrito ACENDE_LED, executando a instrução BSF LED.
Repare que depois de acender ou de apagar o LED ele desvia para o começo
da rotina principal, onde, começará novamente a decrementar as rotinas.
Com isso chegamos ao final do nosso programa.
Devemos indicar o fim do programa ao MPLAB através da diretiva END.
Lembre-se de que nós ativamos o WDT nos bits de configuração.
O WDT é um circuito que reinicia o microcontrolador caso o programa
trave.
Ele é um contador que é incrementado continuamente e quando atinge o
valor máximo, provoca o reset do microcontrolador.
Em algum ponto do nosso programa deveremos escrever a instrução
CLRWDT, que reinicia o contador do WDT toda vez que é executada.
;***********************************************************************************************
; PROGRAMA: PISCA LED
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
18
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
; VARIAVEIS
;**********************************************************************************************
; CONSTANTES
;***********************************************************************************************
; SAÍDA
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
19
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
;**********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
;***********************************************************************************************
;**********************************************************************************************
END ;FIM DO PROGRAMA
;**********************************************************************************************
20
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 5
Figura 6
21
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 7
Figura 8
22
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 9
Figura 10
23
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 11
Figura 12
24
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 13
25
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 14
A mensagem “BUILD SUCCEEDED”, confirma que não ocorreu nenhum
erro na compilação.
Com isto, nós já temos disponível o arquivo Pisca LED.hex para ser gravado
no microcontrolador, criado na mesma pasta onde está o arquivo Pisca LED.asm., mas, antes vamos
simular a execução do programa.
A mensagem “Message[302] E:\PISCA LED.ASM 56 : Register in operand
not in bank 0. “Ensure that bank bits are correct” é um aviso de que o registrador objeto da
instrução presente naquela linha do programa (linha 56), não está no banco 0, afim de que nos
certifiquemos de ter setado corretamente o banco. É uma mensagem que aparece mesmo que o
banco tenha sido selecionado corretamente.
Abra o arquivo Pisca LED.asm, clicando no menu “File” em “Open”.
Clique no menu “Edit”, depois em “Properties” e depois na aba “ASM File
Types” e selecione “Line Numbers”.
Aparecerão os números das linhas à esquerda.
Vá à linha 56 e veja que o registrador em questão é o TRISA, que está no
banco 1. Repare que nós selecionamos esse banco antes e, por isso, não precisamos nos preocupar.
O mesmo ocorre para a mensagem da linha 58.
Agora vamos à simulação:
Clique no menu “Debugger” e depois, em “Select Tool”, selecione “MPLAB
SIM”.
Clique novamente no menu “Debugger” e depois em “Settings”
Na aba “Osc/Trace”, em “Processor Frequency” digite 4 e selecione Mhz.
Na aba “Animation / Real Time Updates”, selecione “Enable Real Time
Watch Updates” e leve o cursor todo para a esquerda “Fastest”.
Clique em “OK”.
No menu “View”, clique em “Watch”.
26
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 15
Figura 16
27
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 17
28
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 18
Clique no botão “Reset”.
O cursor vai para a linha 46 onde está a instrução GOTO INICIO.
Esta é a posição 0X00 da memória de programa, e, portanto é a instrução
contida nesta posição que o microcontrolador irá executar em primeiro lugar, quando for ligado ou
resetado.
Repare que apareceu uma seta verde do lado esquerdo:
Figura 19
29
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 20
30
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
31
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 21
32
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 22
33
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 23
34
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 24
35
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 25
Figura 26
36
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 27
37
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 28
Para utilizá-lo é necessário o programa IC-prog:
http://www.ic-prog.com/icprog106B.zip
Também é necessário o driver para Windows XP:
http://www.ic-prog.com/icprog_driver.zip.
Até hoje apenas utilizei este programa no Windows XP, e por isso, não
posso garantir que o mesmo funcione em versões posteriores do Windows.
Descompacte os arquivos do programa e do driver numa mesma pasta.
Na primeira vez que o IC-prog é executado ele apresenta a janela mostrada
na figura a seguir. Clique em OK.
38
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 29
Na próxima janela também clique em OK, deixando como está, pois, este
gravador é baseado no JDM.
Figura 30
39
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 31
Figura 32
40
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 33
Figura 34
41
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 35
42
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED
Figura 36
43
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
Parte 2
Pisca LED II
Nesta 2ª parte iremos montar o mesmo circuito da Parte 1, mas utilizaremos
o Timer 0 do PIC16F628A para obter a frequência de cerca de 1 Hz para o LED.
O Timer 0 é um circuito do microcontrolador que incrementa um registrador
chamado TMR0, ou seja, é um circuito que faz com que o valor desse registrador vá aumentando de
1 em 1.
O registrador TMR0 é de 8 bits (como todos os registradores do
PIC16F628A) e, portanto, seu valor pode variar de 0 a 255. O seu valor pode ser lido e também
alterado, ou seja, podemos escrever o valor que quisermos nele (de 0 a 255).
O Timer 0 pode ser configurado para incrementar o registrador TMR0 a
partir do ciclo de instrução ou a partir do ciclo de um sinal externo aplicado no pino T0CKI (pino 3).
Quando ele é incrementado pelo ciclo de instrução, diz-se que ele está sendo
usado como timer e quando é incrementado por um sinal aplicado no pino T0CKI, diz-se que ele
está sendo usado como contador (pois pode ser usado para contar os ciclos do sinal externo).
No nosso caso vamos configurá-lo para que seja incrementado a partir do
ciclo de instrução, pois, desejamos obter um determinado intervalo de tempo, conhecendo o tempo
de duração do ciclo de instrução.
Podemos configurar o Timer 0 para que o registrador TMR0 seja
incrementado a cada ciclo ou para que seja incrementado a cada 2, 4, 8, 16, 32, 64, 128 e 256 ciclos.
Isso é o que se chama de Prescaler. Quando ele estiver configurado para incrementar a cada ciclo,
dizemos que o valor do prescaler é 1:1, quando for incrementado a cada 2 ciclos, 1:2, e assim por
diante.
Quando o registrador TMR0 estiver com o valor 255, o próximo incremento
fará seu valor voltar a 0 e, então, dizemos que ele “estourou”.
Quando o TMR0 estoura, o bit T0IF do registrador INTCON é setado, ou
seja, o valor desse bit passa a ser igual a 1, sendo que ele precisa ser apagado na rotina do programa
para que se detecte nova mudança de seu estado. Ao mesmo tempo uma interrupção é provocada, se
estiver habilitada.
A vantagem de se usar o Timer 0 para obter o tempo que desejamos é que o
programa fica livre para executar outras funções, bastando monitorar o estado do bit T0IF para ver
se o tempo que desejamos já passou. Outra opção é habilitar a interrupção de estouro do Timer 0.
O intervalo de tempo que precisamos é de 500 milissegundos.
Para uma frequência do oscilação de 4 MHz, o ciclo de instrução é de 1
microssegundo, como já vimos na parte 1 deste tutorial.
Dividindo 500 milissegundos por 1 microssegundo, obtemos o valor de
500.000, ou seja, a cada 500.000 ciclos de instrução terão se passado 500 milissegundos.
Se configurarmos o prescaler do Timer 0 para 1:1, ou seja, se o registrador
TMR0 for incrementado a cada ciclo de instrução, ele irá estourar a cada 256 microssegundos.
Como este tempo é muito menor do que o que estamos querendo, vamos
configurar o prescaler para o seu valor máximo, isto é, para 1:256.
44
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
;***********************************************************************************************
; PROGRAMA: PISCA LED II
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;**********************************************************************************************
Para não ter de escrever tudo de novo, no MPLAB, abra o arquivo Pisca
LED.asm e, no menu “File”, clique em “Save As...” e mude o nome do arquivo para Pisca LED
II.asm e vá fazendo as alterações.
O próximo passo do programa é a definição das variáveis.
Iremos utilizar apenas uma variável, que será usada para contar os estouros
do TMR0.
Vamos nomeá-la de CONT_EST_TMR0:
;**********************************************************************************************
; VARIÁVEIS
45
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
;**********************************************************************************************
;**********************************************************************************************
; CONSTANTES
;***********************************************************************************************
; SAÍDA
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
;***********************************************************************************************
O bit 3 define se o prescaler será usado pelo Timer 0. Para que o Timer 0
use o prescaler, o valor desse bit deve ser igual a 0.
Os bits 2, 1 e 0 definem o valor do prescaler. No nosso caso, iremos utilizar
o valor 1:32, e, portanto, os valores desses bits deverão ser 1, 0 e 0, respectivamente.
Os demais bits não nos interessam e, portanto, vamos deixá-los com o valor
1, valor com o qual eles são inicializados.
Dessa forma, iremos escrever o seguinte número binário no registrador
OPTION_REG: 11010100.
As configurações dos outros registradores são as mesmas.
A seguir, inicializamos a variável e teremos chegado à rotina principal:
46
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
; INICIALIZACAO DA VARIAVEL
;***********************************************************************************************
A seguir, iremos reiniciar o TMR0 com o valor 131, usando a constante que
criamos:
MOVLW INI_TMR0 ;W = INI_TMR0
MOVWF TMR0 ;REINICIA TMR0
Se o seu valor não for igual a 0, a próxima linha será executada e, nesse caso,
desviaremos o programa para o começo da rotina principal:
47
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
;***********************************************************************************************
; PROGRAMA: PISCA LED II
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;**********************************************************************************************
; VARIÁVEIS
;**********************************************************************************************
; CONSTANTES
;***********************************************************************************************
; SAÍDA
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
48
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
; INICIALIZACAO DA VARIAVEL
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
;**********************************************************************************************
END ;FIM DO PROGRAMA
;**********************************************************************************************
Salve o arquivo.
A seguir iremos simular a execução do programa com o MPLAB SIM.
No menu “Project”, clique em “Open”. Localize o projeto de nome Pisca
LED, selecione-o e clique em “Abrir”.
No menu “Project”, em “Remove Files to Project”, clique no arquivo Pisca
LED.asm (o da parte I) para removê-lo.
No menu “Project”, clique em “Add Files to Project...”, localize o arquivo
Pisca LED II.asm (o novo), selecione-o e clique em “Abrir”.
No menu “Project”, clique em “Buid All”.
Verifique se a montagem foi feita com sucesso, selecionando a janela
“Output” no menu “Window”:
49
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
Figura 1
Figura 2
50
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
Figura 3
O erro de 5 milissegundos é devido ao tempo gasto com as instruções que reiniciam o TMR0 com o
valor 131 toda vez que ele estoura.
Experimente mudar este valor para 132 (na constante), monte novamente o
projeto e volte a fazer a simulação e medir o tempo.
Você verá que o tempo agora é de 497 milissegundos:
Figura 4
51
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II
Este projeto não exige um tempo exato, pois, não se trata, por exemplo, de
um relógio.
Programas de relógio usam cristais cujo valor da frequência é um múltiplo
de 2 e desta forma, não é preciso reiniciar o Timer, deixando que ele rode de 0 a 255.
Em outra parte deste tutorial voltaremos a falar sobre esse assunto.
Grave o programa no microcontrolador e constate o seu funcionamento!
Aqui termina a 2ª parte deste tutorial.
Na próxima parte, vamos continuar com este circuito, mas utilizaremos o
recurso da interrupção provocada pelo estouro do Timer 0.
52
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
Parte 3
Pisca LED III
;***********************************************************************************************
; PROGRAMA: PISCA LED III
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
53
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;**********************************************************************************************
;**********************************************************************************************
54
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
; CONSTANTES
;***********************************************************************************************
; SAÍDA
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
Nos programas utilizados nas partes 1 e 2 deste tutorial, havia aqui apenas a
instrução RETFIE, pois não utilizamos o recurso de interrupção, e a instrução RETFIE servia para
se, por acaso, ocorresse uma interrupção inesperada, o programa voltasse ao ponto de onde havia
sido desviado.
Agora iremos habilitar a interrupção de estouro do Timer 0 e, quando ela
ocorrer, o microcontrolador irá executar o código contido a partir daqui.
Primeiramente vamos salvar os valores dos registradores W e STATUS,
copiando-os para as variáveis W_TEMP e STATUS_TEMP.
A Microchip, fabricante do PIC16F628A, recomenda a seguinte sequência
de instruções para salvar os conteúdos dos registradores W e STATUS:
Se o bit T0IF não estiver setado, significando que a interrupção não foi
causada pelo estouro do Timer 0, a próxima linha do programa será executada, e, nesse caso, temos
de fazer o programa voltar da interrupção.
55
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
Se o bit T0IF estiver setado, indicando que a interrupção foi causada pelo
estouro do Timer 0, a linha com a instrução GOTO SAI_INT será pulada, e, nesse caso, na próxima
instrução apagaremos o bit T0IF:
56
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
ACENDE_LED
BSF LED ;ACENDE O LED
Recapitulando:
O Timer 0 foi configurado para estourar a cada 4 milissegundos. A cada vez
que o registrador TMR0 estoura, é gerada uma interrupção, onde a variável CONT_EST_TMR0 é
decrementada. Como essa variável é iniciada com o valor 125, quando ela chega a 0, terão se
passado cerca de 500 milissegundos, quando, então, o estado do LED é testado e alterado.
Ou seja, o que era feito na rotina principal do programa na parte 2 deste
tutorial, agora é feito dentro da rotina de interrupção.
O programa da parte 2 fica testando o bit T0IF para detectar quando ele for
setado. Aqui, não precisamos fazer isto, porque, quando o bit é setado, é gerada uma interrupção.
A cada interrupção, a variável CONT_EST_TMR0 é decrementada. Quando
o seu valor chega a 0, mudamos o estado do LED.
Neste programa tão simples, talvez você não veja muita vantagem nisso,
mas, em programas mais complexos, o recurso da interrupção é muito útil.
Nosso objetivo aqui foi explicar como usar o recurso da interrupção do
microcontrolador.
Com isso concluímos a rotina de interrupção que ficou assim:
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
57
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
;**********************************************************************************************
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
MOVLW B'11111111'
MOVWF TRISB ;TODOS OS PINOS DO PORTB COMO ENTRADAS
BANCO_0 ;SELECIONA BANCO 0 DE MEMORIA
MOVLW B'00000111'
MOVWF CMCON ;CONFIGURA RA3, RA2, RA1 E RA0 COMO I/O
MOVLW B'11100000'
MOVWF INTCON ;HABILITA INTERRUPÇÃO DO TIMER 0
;**********************************************************************************************
A seguir vem a inicialização da variável CONT_EST_TRMR0.
Não é necessário inicializar W_TEMP e STATUS_TEMP, pois, não são
variáveis que precisam ter um determinado valor na inicialização.
Finalmente, vem a rotina principal, que consiste apenas na execução da
instrução CLRWDT.
O programa fica executando a instrução CLRWDT até que ocorra uma
interrupção.
O programa completo ficou assim:
58
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
;***********************************************************************************************
; PROGRAMA: PISCA LED III
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;**********************************************************************************************
; VARIÁVEIS
;***********************************************************************************************
; CONSTANTES
;***********************************************************************************************
; SAÍDA
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
59
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
ACENDE_LED
BSF LED ;ACENDE O LED
SAI_INT
SWAPF STATUS_TEMP,W ;W = SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
; INICIALIZACAO DA VARIÁVEL
;***********************************************************************************************
;**********************************************************************************************
END ;FIM DO PROGRAMA
60
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
Figura 1
No menu “File”, clique em “Open”, localize e abra o arquivo Pisca LED III.
Na barra de ferramentas do simulador, clique no botão “Reset”:
61
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
Figura 2
62
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 3 – Pisca LED III
Figura 3
63
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Parte 4
64
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
65
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;********************************************************************************************
; VARIÁVEIS
;********************************************************************************************
A seguir, vamos criar as constantes para a inicialização das variáveis
DB_BTA e DB_BTB:
;**********************************************************************************************
; CONSTANTES
;**********************************************************************************************
;***********************************************************************************************
; ENTRADA
;***********************************************************************************************
;***********************************************************************************************
; FLAGS
;***********************************************************************************************
66
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;***********************************************************************************************
A variável FLAGS foi inicializada com a instrução CLRF. Esta instrução faz
todos os bits de um registrador iguais a 0.
Na rotina principal, após a instrução CLRWDT, temos a instrução BTFSS
SOLTAR_BOTAO que testa o estado desse bit de flag.
Se o valor desse bit for 0, significando que não está se aguardando soltar o
botão, a próxima linha será executada e programa será desviado para onde está a label
TESTA_BOTAO, onde será testado o estado do pino onde o botão está ligado (RA1) para ver se
está pressionado.
Porém, se o bit estiver setado, significando que está se aguardando soltar o
botão, devemos verificar se o botão já foi solto. Nesse caso, a próxima linha será pulada e será
executada a instrução BTFSS BOTAO, para testar o RA1.
Se o estado do RA1 for igual a 0, significa que o botão ainda não foi solto e
por isso o programa é desviado para o início da rotina “PRINCIPAL”, para que voltemos a testá-lo
até que ele tenha sido solto.
Se o estado do RA1 for igual a 1, significa que o botão foi solto e, então,
apagamos o flag SOLTAR_BOTAO.
Após a label TESTA_BOTAO, temos a instrução BTFSC BOTAO, onde
testamos o estado do bit RA1 para verificarmos se o botão está pressionado.
Se ele não estiver pressionado, o estado deste bit será igual a 1, e, portanto, a
próxima linha será executada, desviando o programa para REINC_CONT_DEB, onde as variáveis
DB_BTA e DB_BTB são reinicializadas e depois o programa é desviado para o início da rotina
principal.
Se o botão estiver pressionado (estado do bit RA1 igual a 0), a próxima
linha será pulada e a instrução DECFSZ DB_BTA ,F será executada, começando o de-bouncing.
A instrução DECFSZ DB_BTA,F decrementa a variável e ao mesmo tempo
verifica se o seu valor chegou a 0. Se não chegou, o programa retorna para o início da rotina
PRINCIPAL e, se o botão permanecer pressionado, esta variável será novamente decrementada.
Toda vez que o valor de DB_BTA chega a 0, ela é reinicializada e a variável DB_BTB é
decrementada. Quando o valor de DB_BTB chegar a 0, o de-bouncing terá terminado.
Mas, para que isso ocorra, é necessário que o estado do pino RA1 se
mantenha em nível baixo durante todo esse tempo, que iremos ajustar para cerca de 50
milissegundos, através dos valores de inicialização de DB_BTA e DB_BTB.
Se antes disso o nível de RA1 voltar a 1, o programa será desviado para a
subrotina REINC_CONT_DEB, onde as variáveis DB_BTA e DB_BTB são reinicializadas, para
que se comece uma nova contagem de 50 milissegundos, quando for detectado nível baixo em RA1.
67
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
TESTA_BOTAO
BTFSC BOTAO ;O BOTÃO ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB ;NÃO, DESVIA
DECFSZ DB_BTA,F ;SIM, DECREMENTA DB_BTA. DB_BTA = 0?
GOTO PRINCIPAL ;NAO, DESVIA
MOVLW INI_DB_BTA ;SIM, W = INI_DB_BTA
MOVWF DB_BTA ;INICIALIZA DB_BTA
DECFSZ DB_BTB,F ;DECREMENTA DB_BTB. DB_BTB = 0?
GOTO PRINCIPAL ;NAO, DESVIA
MOVLW INI_DB_BTB ;SIM, W = INI_DB_BTB
MOVWF DB_BTB ;INICIALIZA DB_BTB
BTFSS ESTADO_DO_LED ;LED ESTÁ PISCANDO?
GOTO PISCAR_O_LED ;NAO, DESVIA
BCF ESTADO_DO_LED ;SIM, APAGA O LED
BSF SOLTAR_BOTAO ;SETA O FLAG PARA AGUARDAR SOLTAR O BOTAO
GOTO PRINCIPAL ;DESVIA
PISCAR_O_LED
BSF ESTADO_DO_LED ;FAZ O LED PISCAR
BSF SOLTAR_BOTAO ;SETA O FLAG PARA AGUARDAR SOLTAR O BOTAO
GOTO PRINCIPAL ;DESVIA
REINC_CONT_DEB
MOVLW INI_DB_BTA ;W = INI_DB_BTA
MOVWF DB_BTA ;INICIALIZA DB_BTA
MOVLW INI_DB_BTB ;W = INI_DB_BTB
68
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;*********************************************************************************************
END ;FIM DO PROGRAMA
;**********************************************************************************************
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
CONT_INTERRUPCAO
MOVLW INI_TMR0 ;W = INI_TMR0
MOVWF TMR0 ;REINICIA TMR0
DECFSZ CONT_EST_TMR0,F ;DECREMENTA CONT_EST_TMR0. CONT_EST_TMR0 = 0?
GOTO SAI_INT ;NAO
MOVLW INI_CONT_EST_TMR0 ;SIM, W = INI_CONT_EST_TMR0
MOVWF CONT_EST_TMR0 ;REINICIALIZA CONT_EST_TMR0
BTFSS LED ;TESTA O VALOR DO BIT 0 DO PORTA
GOTO ACENDE_LED ;VALOR = 0, DESVIA
BCF LED ;VALOR = 1, APAGA O LED
GOTO SAI_INT ;SAIR DA INTERRUPCAO
ACENDE_LED
BSF LED ;ACENDE O LED
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
69
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;***********************************************************************************************
Nosso programa está pronto para ser simulado, tendo ficado assim:
;***********************************************************************************************
; PROGRAMA: PISCA LED IV
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;**********************************************************************************************
; VARIÁVEIS
;**********************************************************************************************
; CONSTANTES
;***********************************************************************************************
; SAÍDA
70
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;***********************************************************************************************
; ENTRADA
;***********************************************************************************************
; FLAGS
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
CONT_INTERRUPCAO
MOVLW INI_TMR0 ;W = INI_TMR0
MOVWF TMR0 ;REINICIA TMR0
DECFSZ CONT_EST_TMR0,F ;DECREMENTA CONT_EST_TMR0. CONT_EST_TMR0 = 0?
GOTO SAI_INT ;NAO
MOVLW INI_CONT_EST_TMR0 ;SIM, W = INI_CONT_EST_TMR0
MOVWF CONT_EST_TMR0 ;REINICIALIZA CONT_EST_TMR0
BTFSS LED ;TESTA O VALOR DO BIT 0 DO PORTA
GOTO ACENDE_LED ;VALOR = 0, DESVIA
BCF LED ;VALOR = 1, APAGA O LED
GOTO SAI_INT ;SAIR DA INTERRUPCAO
ACENDE_LED
BSF LED ;ACENDE O LED
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
71
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
;***********************************************************************************************
TESTA_BOTAO
BTFSC BOTAO ;O BOTÃO ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB ;NÃO, DESVIA
DECFSZ DB_BTA,F ;SIM, DECREMENTA DB_BTA. DB_BTA = 0?
GOTO PRINCIPAL ;NAO, DESVIA
MOVLW INI_DB_BTA ;SIM, W = INI_DB_BTA
MOVWF DB_BTA ;INICIALIZA DB_BTA
DECFSZ DB_BTB,F ;DECREMENTA DB_BTB. DB_BTB = 0?
GOTO PRINCIPAL ;NAO, DESVIA
MOVLW INI_DB_BTB ;SIM, W = INI_DB_BTB
MOVWF DB_BTB ;INICIALIZA DB_BTB
BTFSS ESTADO_DO_LED ;LED ESTÁ PISCANDO?
GOTO PISCAR_O_LED ;NAO, DESVIA
BCF ESTADO_DO_LED ;SIM, APAGA O LED
BSF SOLTAR_BOTAO ;SETA O FLAG PARA AGUARDAR SOLTAR O BOTAO
GOTO PRINCIPAL ;DESVIA
72
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
PISCAR_O_LED
BSF ESTADO_DO_LED ;FAZ O LED PISCAR
BSF SOLTAR_BOTAO ;SETA O FLAG PARA AGUARDAR SOLTAR O BOTAO
GOTO PRINCIPAL ;DESVIA
REINC_CONT_DEB
MOVLW INI_DB_BTA ;W = INI_DB_BTA
MOVWF DB_BTA ;INICIALIZA DB_BTA
MOVLW INI_DB_BTB ;W = INI_DB_BTB
MOVWF DB_BTB ;INICIALIZA DB_BTB
GOTO PRINCIPAL ;DESVIA
;*********************************************************************************************
END ;FIM DO PROGRAMA
;**********************************************************************************************
73
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 1
74
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 2
Figura 3
75
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 4
76
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 5
Figura 6
Clicando nesse botão estará fazendo com que o pino RA1 fique em nível
alto, ou seja, que o seu valor seja igual a 1.
Volte para a janela do programa e clique mais uma vez no botão “Step Into” .
77
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 7
78
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 8
Após fazer isso, vá clicando no botão “Step Into” até que o cursor chegue à
linha da instrução CLRWDT.
Abra a janela do “Stopwatch” e clique em “Zero”.
Clique no botão “Run” do simulador e quando o programa parar no
“breakpoint”, verifique o tempo indicado pelo “Stopwatch”.
Repare que o tempo do “de-bouncing” agora foi de cerca de 46
milissegundos o que está bom, pois, não precisa ser de exatos 50 milissegundos.
Vá clicando no botão “Step Into” e acompanhe a execução do programa.
Quando ele retornar para o início da rotina “PRINCIPAL”, terão sido
setados os dois bits de flag: o que indica que se está aguardando soltar o botão e o que indica que o
LED deve piscar. Repare, no “Watch”, que esses dois bits estão setados.
Vá clicando no botão “Step Into” e repare que o programa está aguardando o
botão ser solto.
Vamos simular que o botão foi solto clicando, no “Stimulus”, no botão da
primeira linha, fazendo com que o RA1 vá para nível alto.
Vá clicando em “Step Into” e repare que ele apaga o flag
“SOLTAR_BOTAO”.
Continue clicando no botão “Step Into” e acompanhando a execução do
programa e repare que ele ficará em loop até que o botão seja novamente pressionado.
Como o flag que indica que o botão deve piscar foi setado, vamos ver se o
pino onde o LED está ligado (RA0) está alternando de nível.
79
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 9
80
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 10
Posicione as janelas de forma que possa visualizar os valores do PORTA, na
janela do “Watch” e ao mesmo tempo possa clicar nos botões do “Stimulus”:
Figura 11
81
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 4 – Pisca LED IV
Figura 12
82
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Parte 5
Desta vez iremos montar o circuito da figura abaixo onde o botão 1 irá
incrementar o número exibido no display, enquanto o botão 2 o decrementará.
Figura 1
83
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
84
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 2
85
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 3
86
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
; VARIÁVEIS
;***********************************************************************************************
;**********************************************************************************************
; CONSTANTES
;***********************************************************************************************
Na seção “SAÍDAS”, vamos definir a label “DIGITO_1” para o pino RA2 e
a label “DIGITO_2” para o pino RA3.
Relembrando que quando RA2 estiver em nível alto, o dígito 1 do display
estará ativo e quando RA3 estiver em nível alto, o dígito 2 estará ativo:
;***********************************************************************************************
; SAÍDAS
;***********************************************************************************************
Na seção “ENTRADAS”, vamos definir a label “BOTAO_1” para o pino
RA0 e a label “BOTAO_2” para o pino RA1, conforme o esquema do circuito:
;***********************************************************************************************
; ENTRADAS
;***********************************************************************************************
87
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
; FLAGS
;***********************************************************************************************
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
A seguir, vamos verificar qual o dígito que está ativo, desativá-lo, e ativar o
outro:
DESATIVA_DIGITO_2
BCF DIGITO_2 ;DESATIVA DIGITO 2
CLRF PORTB ;TODOS OS BITS DO PORT B = 0
BSF DIGITO_1 ;ATIVA DIGITO 1
88
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Segmento Bit
a RB0
b RB1
c RB2
d RB3
e RB4
f RB5
g RB6
Tabela 1
O display utilizado é do tipo catodo comum, portanto os segmentos são
ativados com nível alto. Sendo assim, os valores a serem escritos no PORTB para cada algarismo a
ser exibido no display são os constantes na tabela abaixo. O bit 7 do PORTB está desconectado,
portanto, seu valor é indiferente, pelo que lhe atribuímos o valor 0 para todos os algarismos.
Algarismo PORTB
0 00111111
1 00000110
2 01011011
3 01001111
4 01100110
5 01101101
6 01111101
7 00000111
8 01111111
9 01101111
Tabela 2
89
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
00111111 00000110
01011011 01001111
90
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
01100110 01101101
01111101 00000111
91
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
01111111 01101111
Após o dígito ser ativado, devemos enviar para o PORTB o valor referente
ao algarismo que deve ser exibido.
O dígito 1 do display exibe a dezena do número e o dígito 2, a unidade.
O algarismo da dezena está gravado na variável “DEZENA”, enquanto que
o da unidade está gravado na variável “UNIDADE”, porém, esses algarismos estão gravados nessas
variáveis no formato binário, conforme a tabela abaixo:
92
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Esses valores são diferentes dos que deve assumir o PORTB para que os
algarismos sejam exibidos no display de 7 segmentos, conforme a tabela comparativa abaixo:
Tabela 4
93
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
94
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Esse estouro do PCL provocado quando somamos um número a ele não faz
com que o PCH seja incrementado, como ocorre quando o PC é incrementado pelo ciclo de
instrução.
Desta forma, antes de somarmos um número ao PCL, devemos ter o cuidado
de verificar se isso não irá provocar o estouro do PCL, pois, se provocar, o programa será desviado
para uma localidade que não é a que queremos.
Por exemplo, vamos supor que o valor do PC seja 00FCh, onde o PCL está
com o valor hexadecimal FC que corresponde ao valor decimal 252.
Se nesse momento, somarmos ao PCL o valor 5, o PC irá assumir o seguinte
valor hexadecimal: 0001h. Mas, o correto seria que ele assumisse o valor 0101h, o que não ocorreu
porque o estouro do PCL não provocou o incremento do PCH.
Ou seja, o programa seria desviado para o endereço 0001h quando
queríamos que fosse desviado para 0101h.
Se virmos que a soma ao PCL irá provocar o seu estouro, devemos, antes de
efetuar a soma, incrementar manualmente o PCH, através do registrador PCLATH, fazendo o seu
valor igual ao que deverá assumir o PCH após a soma. No momento da soma ao PCL, o PCH
assumirá o mesmo valor do PCLATH, pois, toda vez que ocorre uma alteração no PCL, o conteúdo
do PCLATH é copiado para o PCH.
Para verificarmos se uma soma ao PCL irá provocar o seu estouro,
verificamos as localidades que assumiram as instruções, depois que o código esteja montado.
Veremos como fazer isso ainda nesta parte do tutorial, quando o programa estiver pronto.
Voltemos ao programa!
Após o dígito 2 ser ativado, o programa é desviado para onde se encontra a
label “COPIAR_UNIDADE”.
Com a instrução MOVF, copiamos o valor da variável “UNIDADE” para o
registrador W:
COPIAR_UNIDADE
MOVF UNIDADE,W ;W = UNIDADE
CONVERTE_BINARIO_7_SEGMENTOS
ADDWF PCL,F ;PCL = PCL + W
RETLW B'00111111' ;W = 0
RETLW B'00000110' ;W = 1
RETLW B'01011011' ;W = 2
RETLW B'01001111' ;W = 3
RETLW B'01100110' ;W = 4
RETLW B'01101101' ;W = 5
RETLW B'01111101' ;W = 6
RETLW B'00000111' ;W = 7
RETLW B'01111111' ;W = 8
RETLW B'01101111' ;W = 9
95
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
DESATIVA_DIGITO_2
BCF DIGITO_2 ;DESATIVA DIGITO 2
CLRF PORTB ;TODOS OS BITS DO PORT B = 0
BSF DIGITO_1 ;ATIVA DIGITO 1
MOVF DEZENA,W ;W = DEZENA
CALL CONVERTE_BINARIO_7_SEGMENTOS ;CHAMA SUBROTINA
MOVWF PORTB ;PORTB RECEBE O VALOR CONVERTIDO
GOTO SAI_INT ;DESVIA
COPIAR_UNIDADE
MOVF UNIDADE,W ;W = UNIDADE
CALL CONVERTE_BINARIO_7_SEGMENTOS ;CHAMA SUBROTINA
MOVWF PORTB ;PORTB RECEBE O VALOR CONVERTIDO
GOTO SAI_INT ;DESVIA
CONVERTE_BINARIO_7_SEGMENTOS
ADDWF PCL,F ;PCL = PCL + W
RETLW B'00111111' ;W = 0
96
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
RETLW B'00000110' ;W = 1
RETLW B'01011011' ;W = 2
RETLW B'01001111' ;W = 3
RETLW B'01100110' ;W = 4
RETLW B'01101101' ;W = 5
RETLW B'01111101' ;W = 6
RETLW B'00000111' ;W = 7
RETLW B'01111111' ;W = 8
RETLW B'01101111' ;W = 9
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
;***********************************************************************************************
O próximo passo é configurar os registradores de uso específico.
Devemos configurar o Timer 0 para estourar a cada 5 milissegundos,
aproximadamente.
Como ele será incrementado pelo ciclo de instrução, que dura 1
microssegundo, se definirmos o seu prescaler para 1:16, ele será incrementado a cada 16
microssegundos e portanto irá estourar a cada 4 milissegundos aproximadamente (16 x 256).
Esse valor é próximo o suficiente daquele que precisávamos.
Para configurar o prescaler do Timer 0 para 1:16, devemos ajustar os valores
dos bits 2, 1 e 0 do registrador OPTION_REG para 0,1 e 1, respectivamente, conforme consta no
datasheet do PIC16F628A.
Temos de configurar também o registrador TRISA para definirmos os pinos
RA0 e RA1 como entrada e os pinos RA2 e RA3 como saída. Os demais pinos do PORTA,
deixaremos como entrada.
Devemos configurar ainda o registrador TRISB para definirmos os pinos
RB0 a RB6 como saída deixando o RB7 como entrada, pois não é usado.
As demais configurações são as mesmas do programa anterior:
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
97
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
;***********************************************************************************************
Chegamos à rotina principal do programa.
Aqui vamos introduzir um conceito conhecido como “Programação
Estruturada”, onde, na rotina principal, chamamos através da instrução CALL as subrotinas do
programa.
Teremos duas subrotinas que serão as que tratam os dois botões.
Nossa rotina “PRINCIPAL” ficará assim:
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
;***********************************************************************************************
;***********************************************************************************************
TRATA_BOTAO_1
98
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
TESTA_BOTAO_1
BTFSC BOTAO_1 ;O BOTÃO 1 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_1 ;NÃO, DESVIA
DECFSZ DB1_BTA,F ;SIM, DECREMENTA DB1_BTA. DB1_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB1_BTA ;SIM, W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
DECFSZ DB1_BTB,F ;DECREMENTA DB1_BTB. DB1_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB1_BTB ;SIM, W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
Como ficou definido, a cada vez que o botão 1 for pressionado o número
exibido no display será incrementado.
O número é composto de dois dígitos: unidade e dezena. Para incrementar
esse número, devemos incrementar a unidade, o que fazemos com a instrução INCF:
99
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
TRATA_BOTAO_1
TESTA_BOTAO_1
BTFSC BOTAO_1 ;O BOTÃO 1 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_1 ;NÃO, DESVIA
DECFSZ DB1_BTA,F ;SIM, DECREMENTA DB1_BTA. DB1_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB1_BTA ;SIM, W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
DECFSZ DB1_BTB,F ;DECREMENTA DB1_BTB. DB1_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB1_BTB ;SIM, W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
BSF SOLTAR_BOTAO_1 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 1
100
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
REINC_CONT_DEB_1
MOVLW INI_DB1_BTA ;W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
MOVLW INI_DB1_BTB ;W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
RETURN ;RETORNA
;**********************************************************************************************
;***********************************************************************************************
TRATA_BOTAO_2
TESTA_BOTAO_2
BTFSC BOTAO_2 ;O BOTÃO 2 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_2 ;NÃO, DESVIA
DECFSZ DB2_BTA,F ;SIM, DECREMENTA DB2_BTA. DB2_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB2_BTA ;SIM, W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
DECFSZ DB2_BTB,F ;DECREMENTA DB2_BTB. DB2_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB2_BTB ;SIM, W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
BSF SOLTAR_BOTAO_2 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 2
101
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;**********************************************************************************************
TRATA_BOTAO_2
TESTA_BOTAO_2
BTFSC BOTAO_2 ;O BOTÃO 2 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_2 ;NÃO, DESVIA
DECFSZ DB2_BTA,F ;SIM, DECREMENTA DB2_BTA. DB2_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB2_BTA ;SIM, W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
DECFSZ DB2_BTB,F ;DECREMENTA DB2_BTB. DB2_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB2_BTB ;SIM, W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
BSF SOLTAR_BOTAO_2 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 2
DECF UNIDADE,F ;DECREMENTA UNIDADE
MOVLW .255 ;W = 255
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 255?
102
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
REINC_CONT_DEB_2
MOVLW INI_DB2_BTA ;W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
MOVLW INI_DB2_BTB ;W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
RETURN ;RETORNA
;**********************************************************************************************
;***********************************************************************************************
; PROGRAMA: CONTADOR CRESCENTE E DECRESCENTE
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF
& _LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;***********************************************************************************************
; VARIÁVEIS
103
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
; CONSTANTES
;***********************************************************************************************
; SAÍDAS
;***********************************************************************************************
; ENTRADAS
;***********************************************************************************************
; FLAGS
#DEFINE SOLTAR_BOTAO_1 FLAGS,0 ;SE = 1 AGUARDA SOLTAR O BOTÃO 1
#DEFINE SOLTAR_BOTAO_2 FLAGS,1 ;SE = 1 AGUARDA SOLTAR O BOTÃO 2
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
DESATIVA_DIGITO_2
BCF DIGITO_2 ;DESATIVA DIGITO 2
104
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
COPIAR_UNIDADE
MOVF UNIDADE,W ;W = UNIDADE
CALL CONVERTE_BINARIO_7_SEGMENTOS ;CHAMA SUBROTINA
MOVWF PORTB ;PORTB RECEBE O VALOR CONVERTIDO
GOTO SAI_INT ;DESVIA
CONVERTE_BINARIO_7_SEGMENTOS
ADDWF PCL,F ;PCL = PCL + W
RETLW B'00111111' ;W = 0
RETLW B'00000110' ;W = 1
RETLW B'01011011' ;W = 2
RETLW B'01001111' ;W = 3
RETLW B'01100110' ;W = 4
RETLW B'01101101' ;W = 5
RETLW B'01111101' ;W = 6
RETLW B'00000111' ;W = 7
RETLW B'01111111' ;W = 8
RETLW B'01101111' ;W = 9
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
105
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
;***********************************************************************************************
TRATA_BOTAO_1
TESTA_BOTAO_1
BTFSC BOTAO_1 ;O BOTÃO 1 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_1 ;NÃO, DESVIA
DECFSZ DB1_BTA,F ;SIM, DECREMENTA DB1_BTA. DB1_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB1_BTA ;SIM, W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
DECFSZ DB1_BTB,F ;DECREMENTA DB1_BTB. DB1_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB1_BTB ;SIM, W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
BSF SOLTAR_BOTAO_1 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 1
INCF UNIDADE,F ;INCREMENTA UNIDADE
MOVLW .10 ;W = 10
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 10?
RETURN ;NAO, RETORNA
CLRF UNIDADE ;SIM, UNIDADE = 0
INCF DEZENA,F ;INCREMENTA DEZENA
MOVLW .10 ;W = 10
XORWF DEZENA,W ;W = W XOR DEZENA
BTFSS STATUS,Z ;DEZENA = 10?
RETURN ;NAO, RETORNA
CLRF DEZENA ;SIM, DEZENA = 0
RETURN ;RETORNA
REINC_CONT_DEB_1
MOVLW INI_DB1_BTA ;W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
MOVLW INI_DB1_BTB ;W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
RETURN ;RETORNA
106
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
;********************************************************************************************
TRATA_BOTAO_2
TESTA_BOTAO_2
BTFSC BOTAO_2 ;O BOTÃO 2 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_2 ;NÃO, DESVIA
DECFSZ DB2_BTA,F ;SIM, DECREMENTA DB2_BTA. DB2_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB2_BTA ;SIM, W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
DECFSZ DB2_BTB,F ;DECREMENTA DB2_BTB. DB2_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB2_BTB ;SIM, W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
BSF SOLTAR_BOTAO_2 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 2
DECF UNIDADE,F ;DECREMENTA UNIDADE
MOVLW .255 ;W = 255
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 255?
RETURN ;NAO, RETORNA
MOVLW .9 ;SIM, W = 9
MOVWF UNIDADE ;UNIDADE = 9
DECF DEZENA,F ;DECREMENTA DEZENA
MOVLW .255 ;W = 255
XORWF DEZENA,W ;W = W XOR DEZENA
BTFSS STATUS,Z ;DEZENA = 255?
RETURN ;NAO, RETORNA
MOVLW .9 ;SIM, W = 9
MOVWF DEZENA ;DEZENA = 9
RETURN ;RETORNA
REINC_CONT_DEB_2
MOVLW INI_DB2_BTA ;W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
MOVLW INI_DB2_BTB ;W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
RETURN ;RETORNA
;**********************************************************************************************
107
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 4
108
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 5
109
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 6
110
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 7
111
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 8
112
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 9
113
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 10
114
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 5 – Contador Crescente e Decrescente
Figura 11
115
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Parte 6
O contador da parte anterior não retinha o seu valor quando a alimentação era
desligada, pois ele era salvo apenas na memória de dados, que é uma memória volátil, isto é, cujo
conteúdo só é mantido enquanto há energia elétrica.
Desta vez, vamos utilizar a memória EEPROM do PIC16F628A para manter
salvo o valor do contador mesmo que a alimentação seja desligada.
O PIC16F628A possui 128 localidades de memória EEPROM, cada uma com
8 bits. Essas localidades devem ser lidas ou escritas uma de cada vez, como ocorre na memória de
dados. Segundo informa a Microchip, fabricante desse microcontrolador, cada localidade dessas
suporta ser regravada cerca de um milhão de vezes, não havendo indicação do limite de número de
leituras. Iremos utilizar duas localidades: uma para o valor da unidade e outra para o valor da dezena.
Poderíamos escolher duas localidades para serem sempre as mesmas onde
seriam salvos os valores da unidade e da dezena e, dessa forma, essas localidades estariam
deterioradas após cerca de um milhão de vezes que os valores fossem salvos. Quando isso
acontecesse, teríamos de trocar o microcontrolador ou reescrever o programa para definir outras duas
localidades. Porém, se todas as vezes que salvarmos aqueles valores, alterarmos as localidades,
estaremos prolongando esse tempo.
As localidades da memória EEPROM do PIC16F628A não são acessadas
diretamente como as da memória de dados. Para ler ou escrever na memória EEPROM, utilizamos
quatro registradores de uso específico:
EEADR: Nesse registrador, devemos escrever o endereço da localidade da
memória EEPROM, que queremos ler ou escrever;
EEDATA: É o registrador onde devemos escrever o valor que queremos que
seja escrito na localidade que consta no EEADR. É também no EEDATA onde o valor escrito na
localidade da memória EEPROM aparece quando efetuamos uma leitura.
EECON1: É o registrador de controle de leitura e escrita.
EECON2: Esse registrador não existe fisicamente, ou seja, não é uma
localidade da memória. Seu nome é usado para prover uma forma de segurança contra escrita
indesejada, conforme veremos adiante.
O tempo necessário para se efetuar uma gravação na memória EEPROM é
tipicamente de 4 milissegundos. Já, no caso de leitura, ela ocorre em apenas 1 ciclo de instrução.
Para efetuarmos a leitura de uma localidade da memória EEPROM, devemos
adotar os seguintes procedimentos:
116
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
117
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
;***********************************************************************************************
;***********************************************************************************************
; FLAGS
118
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
;***********************************************************************************************
Para verificarmos se a gravação da EEPROM terminou, podemos escolher
entre testar o estado do bit “WR” até que ele seja zerado ou habilitar a interrupção de gravação
completa na EEPROM. Ficaremos com o teste do bit, por ser mais simples e, portanto, não iremos
fazer nenhuma alteração na rotina de interrupção.
A próxima alteração é na seção de Inicialização das Variáveis, onde
incluímos as instruções para a inicialização das variáveis criadas para a contagem do tempo de espera
pelo fim da escrita na EEPROM.
As variáveis UNIDADE e DEZENA não serão inicializadas com o valor 0,
como fizemos na parte anterior deste tutorial, mas, sim, com os valores que houverem sido salvos na
memória EEPROM, pois, queremos que quando o circuito seja ligado, ele mostre o valor que tinha
antes de ser desligado.
Como havíamos comentado, todas as vezes que formos salvar os valores da
unidade e da dezena, iremos alterar as localidades da memória EEPROM, a fim de prolongar sua vida
útil. Assim sendo, quando o programa for iniciado, ele terá de encontrar as localidades onde os
valores estão salvos.
Como o valor da unidade varia entre 0 e 9, apenas os quatro bits menos
significativos (bits 0 a 4) da localidade da memória são necessários para salvá-lo:
Tabela 1
Sendo assim, usaremos os bits 5 a 8 para gravar um código que fará com que
o programa identifique a localidade onde está armazenado o valor da unidade.
O código que utilizaremos será este: 0110, ou seja, esses serão os valores dos
bits 5 a 8 da localidade onde o valor da unidade estiver salvo. Esse código será gravado todas as
vezes que salvarmos o valor da unidade, porém, na gravação do programa no microcontrolador,
devemos escrever o código na primeira localidade da memória EEPROM, caso contrário, não haverá
nenhuma localidade com o código para que o programa encontre na primeira vez que o
microcontrolador for ligado. Isso é feito com o uso da diretiva “DE”, desta forma:
119
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
;**********************************************************************************************
; INICIALIZAÇÃO DA EEPROM
ORG 2100 ;APONTA PARA O ENDEREÇO 00H DA EEPROM
DE B'01100000', .0 ;ESCREVE O NÚMERO BINÁRIO 01100000 NO ENDEREÇO 00H DA EEPROM
;E O NÚMERO DECIMAL 0, NA LOCALIDADE 01H
;**********************************************************************************************
A diretiva “DE” serve para escrevermos nas localidades da memória
EEPROM durante a gravação do programa no microcontrolador. Para o PIC16F628A, devemos nos
referir à primeira localidade da memória EEPROM como 2100. Se quisermos escrever em localidades
sequenciais, basta separar os valores por vírgula. Por exemplo, se escrevêssemos assim:
DE .1, .5, .3 escreveríamos os números decimais 1, 5 e 3, nas três localidades iniciadas pela que foi
apontada na diretiva “ORG”.
No nosso caso, o número binário 01100000 será escrito na localidade 00h e o
número decimal 0 na localidade seguinte, ou seja, a 01h. Assim, na primeira vez que o programa for
executado, ele encontrará o código na primeira localidade da memória EEPROM, iniciando a unidade
com o valor 0. Na localidade seguinte, escrevemos 0 para que a dezena também seja iniciada com o
valor 0.
Insira a seção “INICIALIZAÇÃO DA EEPROM”, entre as seções “BITS DE
CONFIGURAÇÃO” e “PAGINAÇÃO DE MEMÓRIA”.
Voltando à seção “INICIALIZAÇÃO DAS VARIÁVEIS”, o programa irá ler
a primeira localidade da memória EEPROM (00h) em busca do código. Se encontrar, ele saberá que
o valor da unidade está salvo naquela localidade e, portanto, que o valor da dezena está salvo na
próxima (01h). Se não encontrar, ele irá ler a terceira localidade (02h). Se encontrar o código, ele
saberá que o valor da unidade está salvo naquela localidade, e a dezena na próxima (03h) e assim por
diante até encontrar onde estão salvos os valores:
120
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
121
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
;***********************************************************************************************
122
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
;***********************************************************************************************
TESTA_BOTAO_1
BTFSC BOTAO_1 ;O BOTÃO 1 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_1 ;NÃO, DESVIA
DECFSZ DB1_BTA,F ;SIM, DECREMENTA DB1_BTA. DB1_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB1_BTA ;SIM, W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
DECFSZ DB1_BTB,F ;DECREMENTA DB1_BTB. DB1_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB1_BTB ;SIM, W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
BSF SOLTAR_BOTAO_1 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 1
INCF UNIDADE,F ;INCREMENTA UNIDADE
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
MOVLW .10 ;W = 10
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 10?
RETURN ;NAO, RETORNA
CLRF UNIDADE ;SIM, UNIDADE = 0
INCF DEZENA,F ;INCREMENTA DEZENA
MOVLW .10 ;W = 10
XORWF DEZENA,W ;W = W XOR DEZENA
BTFSS STATUS,Z ;DEZENA = 10?
RETURN ;NAO, RETORNA
CLRF DEZENA ;SIM, DEZENA = 0
RETURN ;RETORNA
123
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
REINC_CONT_DEB_1
MOVLW INI_DB1_BTA ;W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
MOVLW INI_DB1_BTB ;W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
RETURN ;RETORNA
;********************************************************************************************
TESTA_BOTAO_2
BTFSC BOTAO_2 ;O BOTÃO 2 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_2 ;NÃO, DESVIA
DECFSZ DB2_BTA,F ;SIM, DECREMENTA DB2_BTA. DB2_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB2_BTA ;SIM, W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
DECFSZ DB2_BTB,F ;DECREMENTA DB2_BTB. DB2_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB2_BTB ;SIM, W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
BSF SOLTAR_BOTAO_2 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 2
DECF UNIDADE,F ;DECREMENTA UNIDADE
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
MOVLW .255 ;W = 255
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 255?
RETURN ;NAO, RETORNA
MOVLW .9 ;SIM, W = 9
MOVWF UNIDADE ;UNIDADE = 9
DECF DEZENA,F ;DECREMENTA DEZENA
MOVLW .255 ;W = 255
XORWF DEZENA,W ;W = W XOR DEZENA
BTFSS STATUS,Z ;DEZENA = 255?
RETURN ;NAO, RETORNA
MOVLW .9 ;SIM, W = 9
MOVWF DEZENA ;DEZENA = 9
RETURN ;RETORNA
REINC_CONT_DEB_2
MOVLW INI_DB2_BTA ;W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
MOVLW INI_DB2_BTB ;W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
RETURN ;RETORNA
;**********************************************************************************************
124
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Se esse flag estiver setado, o programa é desviado para onde está a label
“TESTA_FIM_DA_GRAVACAO”:
GOTO TESTA_FIM_DA_GRAVACAO ;SIM
Se o flag estiver zerado, testamos o flag que informa se já podemos conferir a
gravação:
BTFSC CONF_GRV_EEPROM ;NAO, CONFERIR A GRAVAÇÃO?
Se esse flag estiver setado, o programa é desviado para onde está a label
“CONFERE_DEZENA”:
GOTO CONFERE_DEZENA ;SIM
Se o flag estiver zerado, testamos o flag que informa se é a vez de apagar a
localidade anterior da unidade:
125
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
126
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
127
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Se passar 10 milissegundos sem que o bit “WR” tenha sido zerado, ou seja,
sem que a gravação tenha sido concluída, iremos setar os flags APAGAR_UNIDADE,
GRAVAR_UNIDADE e GRAVAR_DEZENA para reiniciar todo o processo de gravação e
apagaremos os flags “ESP_FIM_GRV_EEPROM” e “CONF_GRV_EEPROM” (este último estará
setado se a demora ocorreu na gravação da dezena).
Raramente isso irá ocorrer, mas temos de contar com essa situação.
Quando o bit “WR” for zerado, apagaremos o flag
“ESP_FIM_GRV_EEPROM”. Em seguida, iremos zerar o bit “WREN” para desabilitar a gravação
da EEPROM. A seguir, reiniciaremos as variáveis de contagem do tempo e retornaremos:
TESTA_FIM_DA_GRAVACAO
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
BTFSC EECON1,WR ;A GRAVAÇÃO TERMINOU?
GOTO DEC_CONT_TEMPO_FIM_ESCRITA ;NAO, DESVIA
BCF ESP_FIM_GRV_EEPROM ;SIM, APAGA FLAG
BCF EECON1,WREN ;DESABILITA ESCRITA NA EEPROM
MOVLW INI_ESC_EEPROM_A ;W = INI_ESC_EEPROM_A
MOVWF ESC_EEPROM_A ;REINICIA ESC_EEPROM_A
MOVLW INI_ESC_EEPROM_B ;W = INI_ESC_EEPROM_B
MOVWF ESC_EEPROM_B ;REINICIA ESC_EEPROM_B
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
DEC_CONT_TEMPO_FIM_ESCRITA
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
DECFSZ ESC_EEPROM_A,F ;DECREMENTA ESC_EEPROM_A. ESC_EEPROM_A = 0?
RETURN ;NAO, RETORNA
MOVLW INI_ESC_EEPROM_A ;SIM, W = INI_ESC_EEPROM_A
MOVWF ESC_EEPROM_A ;REINICIA ESC_EEPROM_A
DECFSZ ESC_EEPROM_B,F ;DECREMENTA ESC_EEPROM_B.ESC_EEPROM_B = 0?
RETURN ;NAO, RETORNA
MOVLW INI_ESC_EEPROM_B ;SIM, W = INI_ESC_EEPROM_B
MOVWF ESC_EEPROM_B ;REINICIA ESC_EEPROM_B
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
BCF ESP_FIM_GRV_EEPROM ;APAGA FLAG DE ESPERA PELO FIM DA GRAVACAO
BCF CONF_GRV_EEPROM ;APAGA O FLAG PARA CONFERIR A GRAVAÇÃO DA EEPROM
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
128
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
GRAVA_A_UNIDADE
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
INCF EEADR,F ;INCREMENTA EEADR
INCF EEADR,F ;INCREMENTA EEADR
O registrador EEADR é de 8 bits, o que significa que seu valor pode variar de
0 a 255, porém, no PIC16F628A, existem somente 128 localidades de memória EEPROM. Por isso, o
valor do EEADR deverá variar entre 0 e 127. Por esse motivo, depois de incrementar o EEADR,
testamos se o seu valor é igual a 128. Se for, zeramos o EEADR:
MOVLW .128 ;W = 128
XORWF EEADR,W ;W = W XOR EEADR
BTFSS STATUS,Z ;EEADR = 128?
GOTO CONT_GRV_UNIDADE ;NAO, DESVIA
CLRF EEADR ;SIM, EEADR = 0
129
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
GRAVA_A_DEZENA
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
INCF EEADR,F ;INCREMENTA EEADR
A seguir, copiamos o valor da dezena apara o registrador EEDATA:
MOVF DEZENA,W ;W = DEZENA
MOVWF EEDATA ;EEDATA = DEZENA
Em seguida, escrevemos as instruções que realizam a gravação na EEPROM:
BSF EECON1,WREN ;HABILITA ESCRITA NA EEPROM
BCF INTCON,GIE ;DESABILITA AS INTERRUPÇÕES
BTFSC INTCON,GIE ;BIT GIE ESTÁ ZERADO?
GOTO $-2 ;DESVIA O PROGRAMA PARA 2 LINHAS ACIMA
MOVLW 0x55 ;W = NUMERO 55 HEXADECIMAL
MOVWF EECON2 ;EECON2 = 55 HEXADECIMAL
MOVLW 0xAA ;W = NUMERO AA HEXADECIMAL
MOVWF EECON2 ;EECON2 = AA HEXADECIMAL
BSF EECON1,WR ;INICIA A GRAVAÇÃO
BSF INTCON,GIE ;HABILITA INTERRUPÇÕES
130
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Como o EEADR é um registrador de 8 bits, cujo valor pode variar entre 0 e 255 e,
supondo que seu valor seja 1 (unidade atualmente na localidade 00 e dezena na 01), após decrementá-lo três vezes,
ele irá exibir o valor 254 (1 – 1 = 0; 0 – 1 = 255; 255 – 1 = 254), mas, como só existem 128 localidades de memória
EEPROM no PIC16F628A, o valor do EEADR deve variar entre 0 a 127. Qualquer valor além disso é inválido, pois,
corresponde a uma localidade que não existe na EEPROM. Por esse motivo, após decrementarmos três vezes o
EEADR, iremos testar seu valor. Se ele for igual a 254, iremos fazê-lo igual a 126, pois é esse valor que ele deve
assumir após ser decrementado três vezes partindo do valor 1 (1 – 1 = 0; 0 – 1 = 127; 127 – 1 = 126).
131
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Pode ser que você esteja se perguntando o que ocorreria se o valor do EEADR fosse 0 ou
2.
Isso não é possível, pois, neste ponto do programa, o EEADR aponta para o endereço
onde a dezena está gravada atualmente. A dezena estará sempre gravada numa localidade ímpar (01, 03, 05, etc.),
pois, ela é gravada pela primeira vez na localidade 01, durante a gravação do programa no microcontrolador, por
meio da diretiva “DE”. A partir daí, ela sempre será gravada duas localidades após a anterior, na subrotina de
gravação da EEPROM.
Por esse motivo, após decrementarmos o EEADR, testamos se o seu valor é igual a 254 e,
se for, o fazemos igual a 126.
CONFERE_APAGAMENTO
DECF EEADR,F ;DECREMENTA EEADR
DECF EEADR,F ;DECREMENTA EEADR
DECF EEADR,F ;DECREMENTA EEADR
MOVLW .254 ;W = 254
XORWF EEADR,W ;W = W XOR EEADR
BTFSS STATUS,Z ;EEADR = 254?
GOTO CONT_CONFERENCIA ;NAO, DESVIA
MOVLW .126 ;SIM, W = 126
MOVWF EEADR ;EEADR = 126
CONT_CONFERENCIA
BSF EECON1,RD ;INICIA LEITURA
MOVF EEDATA,W ;W = VALOR DA LOCALIDADE DA EEPROM
132
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
CONFERE_UNIDADE
INCF EEADR,F ;INCREMENTA EEADR
INCF EEADR,F ;INCREMENTA EEADR
MOVLW .128 ;W = 128
XORWF EEADR,W ;W = W XOR EEADR
BTFSS STATUS,Z ;EEADR = 128?
GOTO CONT_CONF_UNIDADE ;NAO, DESVIA
CLRF EEADR
Em seguida, procedemos da mesma forma que foi feito na conferência do
valor da dezena, com a diferença de que após copiarmos a unidade para o W, inserimos o código nos
bits 5 a 8 do W, com a instrução IORWF, antes de comparar com o registrador EEDATA.
Se a gravação estiver correta, o programa é desviado para onde está a label
GRAVACAO_CORRETA, onde apagamos o flag “CONF_GRV_EEPROM”, copiamos o valor do
EEADR para a variável LOCAL_DA_UNIDADE, atualizando essa variável e retornamos,
finalizando o processo de gravação.
Mas, se o valor da unidade não houver sido gravado corretamente, apagamos
o flag “CONF_GRV_EEPROM”, setamos os flags APAGAR_UNIDADE, GRAVAR_UNIDADE e
GRAVAR_DEZENA para que o processo de gravação seja repetido:
CONT_CONF_UNIDADE
BSF EECON1,RD ;INICIA LEITURA
MOVF UNIDADE,W ;W = UNIDADE
IORLW B'01100000' ;W = W OR B'01100000'
XORWF EEDATA,W ;W = W XOR EEDATA
BTFSC STATUS,Z ;VALOR DA UNIDADE FOI GRAVADO CORRETAMENTE?
GOTO GRAVACAO_CORRETA ;SIM
BCF CONF_GRV_EEPROM ;NAO, APAGA FLAG
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
GRAVACAO_CORRETA
BCF CONF_GRV_EEPROM ;APAGA FLAG
MOVF EEADR,W ;W = EEADR
MOVWF LOCAL_DA_UNIDADE ;LOCAL_DA_UNIDADE = EEADR
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
;***********************************************************************************************
; PROGRAMA: CONTADOR CRESCENTE E DECRESCENTE
; VERSÃO 1.1
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
#INCLUDE <P16F628A.INC> ;ARQUIVO PADRAO MICROCHIP PARA O PIC16F628A
;***********************************************************************************************
133
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF &
_LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; INICIALIZAÇÃO DA EEPROM
ORG 2100 ;APONTA PARA O ENDEREÇO 00H DA EEPROM
DE B'01100000', .0 ;ESCREVE O NÚMERO BINÁRIO 01100000 NO ENDEREÇO 00H DA EEPROM
;E O NÚMERO DECIMAL 0 NA LOCALIDADE 01h
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;***********************************************************************************************
; VARIÁVEIS
;***********************************************************************************************
; CONSTANTES
;***********************************************************************************************
134
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
; ENTRADAS
;***********************************************************************************************
; FLAGS
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
DESATIVA_DIGITO_2
BCF DIGITO_2 ;DESATIVA DIGITO 2
CLRF PORTB ;TODOS OS BITS DO PORT B = 0
BSF DIGITO_1 ;ATIVA DIGITO 1
MOVF DEZENA,W ;W = DEZENA
CALL CONVERTE_BINARIO_7_SEGMENTOS ;CHAMA SUBROTINA
MOVWF PORTB ;PORTB RECEBE O VALOR CONVERTIDO
GOTO SAI_INT ;DESVIA
COPIAR_UNIDADE
MOVF UNIDADE,W ;W = UNIDADE
CALL CONVERTE_BINARIO_7_SEGMENTOS ;CHAMA SUBROTINA
MOVWF PORTB ;PORTB RECEBE O VALOR CONVERTIDO
GOTO SAI_INT ;DESVIA
135
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
CONVERTE_BINARIO_7_SEGMENTOS
ADDWF PCL,F ;PCL = PCL + W
RETLW B'00111111' ;W = 0
RETLW B'00000110' ;W = 1
RETLW B'01011011' ;W = 2
RETLW B'01001111' ;W = 3
RETLW B'01100110' ;W = 4
RETLW B'01101101' ;W = 5
RETLW B'01111101' ;W = 6
RETLW B'00000111' ;W = 7
RETLW B'01111111' ;W = 8
RETLW B'01101111' ;W = 9
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
;***********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
136
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
;***********************************************************************************************
TRATA_BOTAO_1
TESTA_BOTAO_1
BTFSC BOTAO_1 ;O BOTÃO 1 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_1 ;NÃO, DESVIA
DECFSZ DB1_BTA,F ;SIM, DECREMENTA DB1_BTA. DB1_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB1_BTA ;SIM, W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
DECFSZ DB1_BTB,F ;DECREMENTA DB1_BTB. DB1_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB1_BTB ;SIM, W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
BSF SOLTAR_BOTAO_1 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 1
INCF UNIDADE,F ;INCREMENTA UNIDADE
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
MOVLW .10 ;W = 10
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 10?
RETURN ;NAO, RETORNA
CLRF UNIDADE ;SIM, UNIDADE = 0
137
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
REINC_CONT_DEB_1
MOVLW INI_DB1_BTA ;W = INI_DB1_BTA
MOVWF DB1_BTA ;INICIALIZA DB1_BTA
MOVLW INI_DB1_BTB ;W = INI_DB1_BTB
MOVWF DB1_BTB ;INICIALIZA DB1_BTB
RETURN ;RETORNA
;********************************************************************************************
TRATA_BOTAO_2
TESTA_BOTAO_2
BTFSC BOTAO_2 ;O BOTÃO 2 ESTÁ PRESSIONADO?
GOTO REINC_CONT_DEB_2 ;NÃO, DESVIA
DECFSZ DB2_BTA,F ;SIM, DECREMENTA DB2_BTA. DB2_BTA = 0?
RETURN ;NAO,RETORNA
MOVLW INI_DB2_BTA ;SIM, W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
DECFSZ DB2_BTB,F ;DECREMENTA DB2_BTB. DB2_BTB = 0?
RETURN ;NAO, RETORNA
MOVLW INI_DB2_BTB ;SIM, W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
BSF SOLTAR_BOTAO_2 ;SETA FLAG PARA AGUARDAR SOLTAR O BOTÃO 2
DECF UNIDADE,F ;DECREMENTA UNIDADE
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
MOVLW .255 ;W = 255
XORWF UNIDADE,W ;W = W XOR UNIDADE
BTFSS STATUS,Z ;UNIDADE = 255?
RETURN ;NAO, RETORNA
MOVLW .9 ;SIM, W = 9
MOVWF UNIDADE ;UNIDADE = 9
DECF DEZENA,F ;DECREMENTA DEZENA
MOVLW .255 ;W = 255
XORWF DEZENA,W ;W = W XOR DEZENA
BTFSS STATUS,Z ;DEZENA = 255?
RETURN ;NAO, RETORNA
MOVLW .9 ;SIM, W = 9
MOVWF DEZENA ;DEZENA = 9
RETURN ;RETORNA
138
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
EINC_CONT_DEB_2
MOVLW INI_DB2_BTA ;W = INI_DB2_BTA
MOVWF DB2_BTA ;INICIALIZA DB2_BTA
MOVLW INI_DB2_BTB ;W = INI_DB2_BTB
MOVWF DB2_BTB ;INICIALIZA DB2_BTB
RETURN ;RETORNA
;**********************************************************************************************
GRAVA_EEPROM
APAGA_UNIDADE_ANTERIOR
BANCO_1 ;SELECIONA BANCO 1 DE MEMÓRIA
MOVF LOCAL_DA_UNIDADE,W ;W = ENDEREÇO DA EEPROM ONDE ESTÁ GRAVADA A UNIDADE
MOVWF EEADR ;EEADR RECEBE ENDERECO
CLRF EEDATA ;EEDATA = 0
BSF EECON1,WREN ;HABILITA ESCRITA NA EEPROM
BCF INTCON,GIE ;DESABILITA AS INTERRUPÇÕES
BTFSC INTCON,GIE ;BIT GIE ESTÁ ZERADO?
GOTO $-2 ;DESVIA O PROGRAMA PARA 2 LINHAS ACIMA
MOVLW 0x55 ;W = NUMERO 55 HEXADECIMAL
MOVWF EECON2 ;EECON2 = 55 HEXADECIMAL
MOVLW 0xAA ;W = NUMERO AA HEXADECIMAL
MOVWF EECON2 ;EECON = AA HEXADECIMAL
BSF EECON1,WR ;INICIA A GRAVAÇÃO
BSF INTCON,GIE ;HABILITA INTERRUPÇÕES
BCF APAGAR_UNIDADE ;APAGA O FLAG
BSF ESP_FIM_GRV_EEPROM ;SETA O FLAG PARA ESPERAR PELO FIM DA GRAVAÇÃO
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
GRAVA_A_UNIDADE
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
INCF EEADR,F ;INCREMENTA EEADR
INCF EEADR,F ;INCREMENTA EEADR
MOVLW .128 ;W = 128
XORWF EEADR,W ;W = W XOR EEADR
BTFSS STATUS,Z ;EEADR = 128?
GOTO CONT_GRV_UNIDADE ;NAO, DESVIA
CLRF EEADR ;SIM, EEADR = 0
CONT_GRV_UNIDADE
MOVF UNIDADE,W ;W = UNIDADE
MOVWF EEDATA ;EEDATA = UNIDADE
MOVLW B'01100000' ;W = 01100000
IORWF EEDATA,F ;EEDATA = EEDATA OR 01100000
BSF EECON1,WREN ;HABILITA ESCRITA NA EEPROM
BCF INTCON,GIE ;DESABILITA AS INTERRUPÇÕES
139
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
GRAVA_A_DEZENA
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
INCF EEADR,F ;INCREMENTA EEADR
MOVF DEZENA,W ;W = DEZENA
MOVWF EEDATA ;EEDATA = DEZENA
BSF EECON1,WREN ;HABILITA ESCRITA NA EEPROM
BCF INTCON,GIE ;DESABILITA AS INTERRUPÇÕES
BTFSC INTCON,GIE ;BIT GIE ESTÁ ZERADO?
GOTO $-2 ;DESVIA O PROGRAMA PARA 2 LINHAS ACIMA
MOVLW 0x55 ;W = NUMERO 55 HEXADECIMAL
MOVWF EECON2 ;EECON2 = 55 HEXADECIMAL
MOVLW 0xAA ;W = NUMERO AA HEXADECIMAL
MOVWF EECON2 ;EECON2 = AA HEXADECIMAL
BSF EECON1,WR ;INICIA A GRAVAÇÃO
BSF INTCON,GIE ;HABILITA INTERRUPÇÕES
BCF GRAVAR_DEZENA ;APAGA O FLAG
BSF ESP_FIM_GRV_EEPROM ;SETA O FLAG PARA ESPERAR PELO FIM DA GRAVAÇÃO
BSF CONF_GRV_EEPROM ;SETA O FLAG PARA CONFERIR A GRAVAÇÃO DA EEPROM
BANCO_0 ;SELECIONA BANCO 0 DE MEMORIA
RETURN ;RETORNA
TESTA_FIM_DA_GRAVACAO
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
BTFSC EECON1,WR ;A GRAVAÇÃO TERMINOU?
GOTO DEC_CONT_TEMPO_FIM_ESCRITA ;NAO, DESVIA
BCF ESP_FIM_GRV_EEPROM ;SIM, APAGA FLAG
BCF EECON1,WREN ;DESABILITA ESCRITA NA EEPROM
MOVLW INI_ESC_EEPROM_A ;W = INI_ESC_EEPROM_A
MOVWF ESC_EEPROM_A ;REINICIA ESC_EEPROM_A
MOVLW INI_ESC_EEPROM_B ;W = INI_ESC_EEPROM_B
MOVWF ESC_EEPROM_B ;REINICIA ESC_EEPROM_B
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
DEC_CONT_TEMPO_FIM_ESCRITA
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
DECFSZ ESC_EEPROM_A,F ;DECREMENTA ESC_EEPROM_A. ESC_EEPROM_A = 0?
RETURN ;NAO, RETORNA
MOVLW INI_ESC_EEPROM_A ;SIM, W = INI_ESC_EEPROM_A
MOVWF ESC_EEPROM_A ;REINICIA ESC_EEPROM_A
DECFSZ ESC_EEPROM_B,F ;DECREMENTA ESC_EEPROM_B.ESC_EEPROM_B = 0?
RETURN ;NAO, RETORNA
MOVLW INI_ESC_EEPROM_B ;SIM, W = INI_ESC_EEPROM_B
MOVWF ESC_EEPROM_B ;REINICIA ESC_EEPROM_B
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
140
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
CONFERE_DEZENA
BANCO_1 ;SELECIONA O BANCO 1 DE MEMÓRIA
BSF EECON1,RD ;INICIA LEITURA
MOVF DEZENA,W ;W = DEZENA
XORWF EEDATA,W ;W = W XOR EEDATA
BTFSC STATUS,Z ;VALOR DA DEZENA FOI GRAVADO CORRETAMENTE?
GOTO CONFERE_APAGAMENTO ;SIM
BCF CONF_GRV_EEPROM ;NAO, APAGA FLAG
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
CONFERE_APAGAMENTO
DECF EEADR,F ;DECREMENTA EEADR
DECF EEADR,F ;DECREMENTA EEADR
DECF EEADR,F ;DECREMENTA EEADR
MOVLW .254 ;W = 254
XORWF EEADR,W ;W = W XOR EEADR
BTFSS STATUS,Z ;EEADR = 254?
GOTO CONT_CONFERENCIA ;NAO, DESVIA
MOVLW .126 ;SIM, W = 126
MOVWF EEADR ;EEADR = 126
CONT_CONFERENCIA
BSF EECON1,RD ;INICIA LEITURA
MOVF EEDATA,W ;W = VALOR DA LOCALIDADE DA EEPROM
BTFSC STATUS,Z ;LOCALIDADE ANTERIOR DA UNIDADE FOI APAGADO CORRETAMENTE?
GOTO CONFERE_UNIDADE ;SIM
BCF CONF_GRV_EEPROM ;NAO, APAGA FLAG
BSF APAGAR_UNIDADE ;SETA O FLAG PARA APAGAR LOCALIDADE ANTERIOR DA UNIDADE
BSF GRAVAR_UNIDADE ;SETA O FLAG PARA GRAVAÇÃO DA UNIDADE
BSF GRAVAR_DEZENA ;SETA O FLAG PARA GRAVAÇÃO DA DEZENA
BANCO_0 ;SELECIONA O BANCO 0 DE MEMÓRIA
RETURN ;RETORNA
CONFERE_UNIDADE
INCF EEADR,F ;INCREMENTA EEADR
INCF EEADR,F ;INCREMENTA EEADR
MOVLW .128 ;W = 128
XORWF EEADR,W ;W = W XOR EEADR
BTFSS STATUS,Z ;EEADR = 128?
GOTO CONT_CONF_UNIDADE ;NAO, DESVIA
CLRF EEADR ;SIM, EEADR = 0
CONT_CONF_UNIDADE
BSF EECON1,RD ;INICIA LEITURA
MOVF UNIDADE,W ;W = UNIDADE
IORLW B'01100000' ;W = W OR B'01100000'
XORWF EEDATA,W ;W = W XOR EEDATA
BTFSC STATUS,Z ;VALOR DA UNIDADE FOI GRAVADO CORRETAMENTE?
GOTO GRAVACAO_CORRETA ;SIM
BCF CONF_GRV_EEPROM ;NAO, APAGA FLAG
141
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
142
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Figura 1
143
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
No “Stimulus”, clique nos botões que fixam o RA0 e o RA1 em nível alto
para simular que os botões estão soltos.
Continue clicando em “Step Into” até chegar à subrotina de gravação da
EEPROM.
Em “TESTA_FIM_DA_GRAVACAO”, insira um “breakpoint” na linha que
contém a instrução BCF ESP_FIM_GRV_EEPROM, dando um duplo clique nessa linha.
Quando o programa for executar essa instrução, o tempo de espera terá
terminado.
Precisamos setar manualmente o flag “ESP_FIM_GRV_EEPROM” para que
o programa entre em “TESTA_FIM_DA_GRAVACAO”.
Para fazer isso, no “Watch”, dê um duplo clique no campo “Binary” da linha
do registrador FLAGS, e altere o bit 5 para 1:
Figura 2
144
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Figura 3
145
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Figura 4
Podemos deixar este tempo pois, está bem próximo dos 10 milissegundos que
pretendíamos.
Vamos desfazer a alteração feita em “TESTA_FIM_DA_GRAVACAO”,
voltando a instrução para: BTFSC EECON1,WR.
Após isso, monte o projeto novamente, clicando em “Build All”, no menu
“Project”.
Clique no botão “Reset” do simulador e depois vá clicando no botão “Step
Into” até chegar à inicialização das variáveis.
No “Stimulus”, clique nos botões que fixam o RA0 e o RA1 em nível alto
para simular que os botões estão soltos.
No menu “Debugger”, clique em “Breakpoints”. Na janela que se abre, clique
em “Remove All”.
Posicione as janelas para que possa clicar nos botões do “Stimulus” enquanto
observa os valores dos registradores no “Watch”.
Clique no botão “Run” do simulador.
No “Stimulus”, clique no botão que simula que o botão 1 foi pressionado e
solto (RA0 “Pulse Low”).
No “Watch” repare que o valor da unidade foi incrementado.
Clique no botão “Halt” do simulador.
No menu “Window”, selecione a janela “EEPROM”. Se ela não estiver na
lista, clique em “EEPROM” no menu “View” para exibi-la.
146
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Figura 5
147
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 6 – Contador II
Figura 6
148
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Parte 7
Dimmer para LED
Nesta parte do tutorial, vamos montar o circuito da figura abaixo para
controlar o brilho de um LED usando dois botões: um para aumentá-lo e outro para diminui-lo.
Figura 1
Figura 2
149
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 3
Figura 4
Como você pode observar, o tempo de duração do ciclo do sinal não muda,
portanto a frequência do sinal PWM, que é igual ao inverso do valor do tempo de duração do ciclo,
não muda. O que irá mudar é o tempo de duração do semiciclo ativo, isto é, o tempo em que o sinal
ficará em nível alto.
150
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Para que não se perceba que o LED está piscando, temos de escolher uma
frequência de, pelo menos, 75 Hz para o sinal PWM.
Vamos ver como o PIC16F628A produz o sinal PWM.
Na parte 2 deste tutorial, falamos sobre o Timer 0. O PIC16F628A possui
outros dois circuitos semelhantes: o Timer 1 e o Timer 2.
A principal diferença do Timer 1 em relação ao Timer 0 é que ele é composto
por dois registradores de 8 bits enquanto que o Timer 0 possui apenas um. Os registradores do Timer
1 são o TMR1L e o TMR1H.
Quando o Timer 1 é incrementado, esse incremento ocorre no TMR1L que
pode ir até o valor 255. No próximo incremento, ele volta para o valor 0 e o TMR1H é incrementado.
Assim, o Timer 1 pode ser incrementado até o valor 65535, o que o torna ideal para contagem de
tempos mais longos.
O Timer 1 pode ser incrementado tanto a partir do ciclo de instrução como a
partir de um sinal externo aplicado no pino 13 (RB7/T1OSI/PGD). Um cristal pode ser ligado entre
esse pino e o pino 12 (RB6/T1OSO/T1CKI/PGC), para fazer funcionar um oscilador interno
otimizado para a frequência de 32.768 KHz, ideal para relógios.
O Timer 1 possui um prescaler que pode ser configurado para 1:1, 1:2, 1:4 ou
1:8.
O Timer 2, assim como o Timer 0, é constituído de apenas um registrador de 8
bits, o TMR2 e, portanto, seu valor pode ser incrementado até 255, porém, somente é possível
incrementá-lo a partir do ciclo de instrução, não sendo possível incrementá-lo a partir de um sinal
externo.
O Timer 2 possui algumas características diferentes dos demais:
Existe um registrador chamado PR2 cujo valor define até onde o registrador
TMR2 poderá ser incrementado. Por exemplo, se o valor do PR2 for igual a 255, o TMR2 poderá ser
incrementado até esse valor e, no próximo incremento ele irá estourar, ou seja, seu valor voltará para
0. Já, se o valor do PR2 for, por exemplo, 100, o TMR2 poderá ser incrementado até esse valor
estourando no próximo incremento. Podemos escrever qualquer valor entre 0 e 255 no PR2.
O seu Prescaler pode assumir apenas os seguintes valores: 1:1, 1:4 ou 1:16, ou
seja, ele pode incrementado a cada ciclo de instrução ou a cada quatro ciclos ou a cada dezesseis
ciclos.
O Timer 2 possui um Postscaler, que pode ser configurado de 1:1 até 1:16. O
Postscaler define o número de vezes que o TMR2 deverá estourar para gerar uma interrupção. Por
exemplo, se ele estiver configurado para 1:1, a cada vez que o TMR2 estourar, o flag TMR2IF será
setado, gerando uma interrupção (desde que ela esteja habilitada). Já, se o Postscaler estiver
configurado, por exemplo, para 1:5, uma interrupção será gerada a cada 5 estouros do TMR2.
As configurações do Prescaler e do Postscaler são feitas no registrador
T2CON, onde também há um bit para ligar e desligar o Timer 2.
É no módulo CCP do PIC16F628A que é gerado o sinal PWM. A
configuração do módulo CCP é feita no registrador CCP1CON. Devemos setar os bits 3 e 2 desse
registrador para habilitar o modo PWM.
151
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
O ciclo do sinal PWM reinicia toda vez que o TMR2 estoura. A fórmula para
o cálculo do tempo de duração do ciclo do sinal PWM é esta:
Ciclo = (PR2 + 1) x ciclo de instrução x prescaler do TMR2
Mas, o valor máximo para o PR2 é de 255. Vamos ver qual seria o valor do
PR2 para um prescaler de 1:4:
Novamente obtivemos um valor muito alto para o PR2. Vamos, então, aumen-
tar o valor do prescaler para 1:16:
152
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
O valor a ser escrito no PR2 continua acima de 255. Isto mostra que não é
possível obter um sinal PWM de 75 Hz se a frequência de oscilação do microcontrolador é de 4 MHz.
Teríamos de diminuir a frequência do oscilador se quiséssemos um sinal PWM de 75 Hz. Poderíamos
fazer isso alterando a frequência do oscilador interno para 48 KHz ou então usando um cristal externo.
Escrevendo no PR2 o seu valor máximo (255) e configurando o prescaler
também para seu valor máximo (16), obtemos a máxima duração do ciclo do sinal PWM para uma
frequência de oscilação de 4 MHz:
Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
CCP1CON CCP1CON
CCPR1L Bit 5 Bit 4
Tabela 1
153
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
0 0 0 1 1 0 0 1 1 0
Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
CCP1CON CCP1CON
CCPR1L Bit 5 Bit 4
Tabela 2
Que resulta no valor 102,4 que havíamos encontrado quando dividimos o nú-
mero 1024 por 10.
A figura abaixo mostra os eventos que provocam o reinício do ciclo e o fim
do semiciclo ativo do sinal PWM.
154
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 5
No nosso circuito, quando o botão 1 for pressionado, o brilho do LED irá au-
mentar até o máximo e, quando o botão 2 for pressionado, o brilho irá diminuir até o LED apagar.
Com o LED apagado, o botão 1 deverá ficar pressionado por cerca de 5 se-
gundos para que o brilho atinja o máximo. Esse também será o tempo que o botão 2 deverá ser man-
tido pressionado para que o LED apague, partindo do brilho máximo.
Como vimos, é possível definir 1024 valores diferentes para o tempo de dura-
ção do semiciclo ativo do sinal PWM, escrevendo na combinação de 10 bits, um valor entre 0 e 1024.
Não precisamos de uma resolução tão alta. Se modificarmos apenas o valor do
registrador CCPR1L, já teremos 256 valores diferentes, o que é mais do que suficiente para uma vari-
ação suave no brilho. Dividindo 5 segundos por 256, obtemos 0,01953125 segundo, ou seja, aproxi-
madamente 19 milissegundos.
Iremos configurar o Timer 0 para que ele provoque uma interrupção a cada
cerca de 19 milissegundos. Na rotina da interrupção, iremos verificar qual botão está pressionado. Se
for o botão 1, iremos incrementar o registrador CCPR1L. Se for o botão 2 decrementaremos o
CCPR1L. Se nenhum botão estiver pressionado, manteremos o valor do CCPR1L.
Para configurarmos o Timer 0 a fim de que ele provoque uma interrupção a
cada 19 milissegundos, primeiramente dividimos 19 milissegundos pelo tempo de duração de um
ciclo de instrução, que é de 1 microssegundo: 0,019 / 0,000001 = 19.000.
Isto significa que 19 milissegundos equivalem a 19.000 ciclos de instrução, ou
seja, o registrador TMR0 deverá estourar a cada 19.000 ciclos de instrução. Como o registrador
TMR0 estoura a cada 256 incrementos, se fizéssemos o valor do prescaler igual a 1:1, onde, o TMR0
é incrementado a cada ciclo de instrução, ele iria estoura a cada 256 ciclos de instrução apenas. Então,
precisamos aumentar o valor do prescaler para que ele estoure a cada 19.000 ciclos de instrução.
155
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
;***********************************************************************************************
; ENTRADAS
;***********************************************************************************************
;************************************************************************************************
; ROTINA DE INTERRUPÇÃO
156
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
INCREMENTA_CCPR1L
MOVLW .255 ;W = 255
XORWF CCPR1L,W ;W = W XOR CCPRR1L
BTFSC STATUS,Z ;CCPR1L = 255?
RETFIE ;SIM, SAI DA INTERRUPÇÃO
DECREMENTA_CCPR1L
MOVLW .0 ;W = 0
XORWF CCPR1L,W ;W = W XOR CCPRR1L
BTFSC STATUS,Z ;CCPR1L = 0?
RETFIE ;SIM, SAI DA INTERRUPÇÃO
DECF CCPR1L,F ;NAO, DECREMENTA CCPR1L
RETFIE ;SAI DA INTERRUPÇÃO
157
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
Em seguida zeramos o CCPR1L para que quando o circuito for ligado o LED
esteja apagado:
CLRF CCPR1L ;ZERA CCPR1L
158
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
;**********************************************************************************************
;**********************************************************************************************
;***********************************************************************************************
; PROGRAMA: DIMMER PARA LED
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF &
_LVP_OFF & _CP_OFF & DATA_CP_OFF
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;***********************************************************************************************
; ENTRADAS
;***********************************************************************************************
159
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
;***********************************************************************************************
; VETOR DE RESET
;***********************************************************************************************
; ROTINA DE INTERRUPÇÃO
INCREMENTA_CCPR1L
MOVLW .255 ;W = 255
XORWF CCPR1L,W ;W = W XOR CCPRR1L
BTFSC STATUS,Z ;CCPR1L = 255?
RETFIE ;SIM, SAI DA INTERRUPÇÃO
INCF CCPR1L,F ;NAO, INCREMENTA CCPR1L
RETFIE ;SAI DA INTERRUPÇÃO
DECREMENTA_CCPR1L
MOVLW .0 ;W = 0
XORWF CCPR1L,W ;W = W XOR CCPRR1L
BTFSC STATUS,Z ;CCPR1L = 0?
RETFIE ;SIM, SAI DA INTERRUPÇÃO
DECF CCPR1L,F ;NAO, DECREMENTA CCPR1L
RETFIE ;SAI DA INTERRUPÇÃO
;************************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
160
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
;**********************************************************************************************
; ROTINA PARA AGUARDAR A INTERRUPÇÃO
;**********************************************************************************************
161
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 6
162
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 7
163
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 8
Vamos medir o tempo que o botão 1 deve ficar pressionado para o CCPR1L ir
de 0 até 255.
Clique no botão “Halt” do simulador.
Insira um “breakpoint” na linha que contem a instrução RETFIE, que é
executada quando o valor do CCPR1L for igual a 255:
164
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 9
165
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 7 – Dimmer para LED
Figura 10
Remova o “breakpoint”.
Clique no botão “Run” do simulador.
No “Stimulus”, volte o pino RA0 para nível alto.
Repare que, quando o valor do CCPR1L é igual a 255, o pino RB3 fica fixo
em nível alto. Por outro lado, quando o valor do CCPR1L é igual a 0, ele fica fixo em nível baixo.
Com o valor do CCPR1L num ponto intermediário, o estado do RB3 varia
entre 0 e 1, indicando que temos o sinal PWM nesse pino.
Grave o programa no microcontrolador, monte o circuito na protoboard e
comprove o seu funcionamento. É muito interessante.
Se usarmos um relé de estado sólido, ligado no pino RB3 podemos controlar
equipamentos de maior potência, como por exemplo, lâmpadas incandescentes, aquecedores, motores
elétricos, etc.
Aqui termina esta parte do tutorial. Espero que tenha sido útil para você. Na
próxima parte iremos desenvolver um frequencímetro. Até lá!
166
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Parte 8
Frequencímetro
Figura 1
10 µF – 1 Hz a 40 Hz
1 µF – 16 Hz a 460 Hz
100 nF – 150 Hz a 4.100 Hz
10 nF – 1.400 Hz a 9.999 Hz
167
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
1
Frequência do sinal =
número de incrementos x 0,000001
168
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
1 1 1
Frequência do sinal = x
número de incrementos 0,000001
1.000.000
Frequência do sinal =
número de incrementos
169
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
100.000.000
Frequência do sinal =
número de incrementos
;***********************************************************************************************
; VARIÁVEIS
170
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
;***********************************************************************************************
;***********************************************************************************************
; SAÍDAS
;***********************************************************************************************
171
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
;***********************************************************************************************
; FLAGS
;***********************************************************************************************
;*************************************************************************************************
; ROTINA DE INTERRUPÇÃO
O prescaler do Timer 0 será configurado para 8:1. Assim, ele irá gerar uma
interrupção a cada 2,048 milissegundos (0,000001 x 256 x 8). No intervalo entre cada interrupção do
Timer 0, apenas um dos dígitos estará ativo. A cada interrupção, desativaremos o dígito que estiver
ativo e ativaremos o próximo. Com isso, cada dígito ficará ativado por 2,048 milissegundos e
desativado por 6,144 milissegundos, num período total de 8,192 milissegundos, o que corresponde a
uma frequência de 122 Hz.
Na rotina de interrupção do Timer 0, primeiramente apagamos o flag TMR0IF:
INT_TIMER_0
172
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
CONT_DIG_DEZ
BCF DIG_CEN ;DESATIVA DÍGITO DA CENTENA
BCF SEG_A ;APAGA SEGMENTO
BCF SEG_B ;APAGA SEGMENTO
BCF SEG_C ;APAGA SEGMENTO
BCF SEG_D ;APAGA SEGMENTO
BCF SEG_E ;APAGA SEGMENTO
BCF SEG_F ;APAGA SEGMENTO
BCF SEG_G ;APAGA SEGMENTO
BSF DIG_DEZ ;ATIVA DÍGITO DA DEZENA
MOVF DEZENA,W ;COPIA DEZENA PARA O W
GOTO CONV_BIN_7_SEG ;CHAMA SUBROTINA
CONT_DIG_UNI
BCF DIG_DEZ ;DESATIVA DÍGITO DA DEZENA
BCF SEG_A ;APAGA SEGMENTO
BCF SEG_B ;APAGA SEGMENTO
BCF SEG_C ;APAGA SEGMENTO
BCF SEG_D ;APAGA SEGMENTO
173
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
CONV_BIN_7_SEG
ADDWF PCL,F ;PCL = PCL + W
GOTO NUM_ZERO ;W = 0
GOTO NUM_UM ;W = 1
GOTO NUM_DOIS ;W = 2
GOTO NUM_TRES ;W = 3
GOTO NUM_QUATRO ;W = 4
GOTO NUM_CINCO ;W = 5
GOTO NUM_SEIS ;W = 6
GOTO NUM_SETE ;W = 7
GOTO NUM_OITO ;W = 8
GOTO NUM_NOVE ;W = 9
NUM_ZERO
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_UM
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_DOIS
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
174
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
NUM_TRES
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_QUATRO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_CINCO
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_SEIS
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_SETE
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_OITO
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_NOVE
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
175
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Para obtermos o valor decimal do Timer 1 a partir dos valores decimais dos
registradores, multiplicamos o valor do TMR1H por 256 e somamos ao valor do TMR1L.
Por exemplo, se o valor decimal do TMR1H é 35 e o valor decimal do
TMR1L é 23, o valor decimal do Timer 1 é igual a 35 x 256 + 23 = 8983.
Para calcularmos os valores decimais dos registradores a partir do valor
decimal do Timer 1, dividimos o valor decimal do Timer 1 por 256. A parte inteira da divisão é o
valor do TMR1H. A seguir, multiplicamos a parte decimal por 256 e obtemos o valor do TMR1L.
Por exemplo, se o valor decimal do Timer 1 é de 8983, dividindo esse valor
por 256, obtemos 35,08984375. Portanto, TMR1H = 35. Multiplicando 0,08984375 por 256, obtemos
23, que é o valor do TMR1L.
No nosso projeto, o Timer 1 será incrementado continuamente. Quando
ocorrer uma captura, ele estará com um valor qualquer entre 0 e 65.535.
Vamos supor que na primeira captura, o valor do Timer 1 seja igual a 34.328
(TMR1H = 134 e TMR1L = 24) e que na segunda captura, o valor do Timer 1 seja igual a 43.436
(TMR1H = 169 e TMR1L = 172).
Se calcularmos a diferença entre esses dois valores, obtemos 9.108. Então, o
Timer 1 teria sido incrementado esse número de vezes entre as duas capturas. Mas, também pode ser
que ele tenha sido incrementado 74.644 vezes. Isso porque ele pode ter estourado entre as duas
capturas. Partindo do valor 34.328, com 31.208 incrementos ele irá estourar (65.536 – 34.328).
Somando 31.208 com 43.436, obtemos que ele foi incrementado 74.644 vezes.
Para sabermos se o Timer 1 estourou entre as capturas, usaremos a variável
REG3B, que iremos incrementar a cada vez que o Timer 1 estourar. Essa variável será como se fosse
o terceiro registrador do Timer1.
Assim, não haverá dúvida quanto ao número de incrementos que ocorreram
no Timer 1 entre as duas capturas, pois, poderemos contar até 16.777.215 incrementos, sendo que o
número máximo de incrementos será de 1.000.000 quando a frequência do sinal for de 1 Hz.
Para obtermos o valor decimal do Timer 1 a partir do valor decimal desses
três registradores, multiplicamos o valor do REG3B por 65.536, o valor do TMR1H por 256 e
somamos os resultados ao valor do TMR1L.
No exemplo anterior, onde na 2ª captura, TMR1H = 169 e TMR1L = 172, se o
REG3 for igual a 1, teremos o seguinte valor para o Timer 1: 1 x 65536 + 169 x 256 + 172 = 108.972.
Subtraindo o valor do Timer 1 na 1ª captura, que era igual a 34.328, obtemos 74.644.
A rotina de interrupção do Timer 1 consiste em apagar o flag TMR1IF e
incrementar a variável REG3B:
INT_TIMER_1
176
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
INT_CCP
CLRF PIR1,CCP1IF ;APAGA FLAG
PRIMEIRA_CAPTURA
MOVF CCPR1L,W ;W = CCPR1L
MOVWF REG1A ;REG1A = CCPR1L
MOVF CCPR1H,W ;W = CCPR1H
MOVWF REG2A ;REG2A = CCPR1H
CLRF REG3B ;REG3B = 0
GOTO SAI_INT ;SAI DA INTERRUPÇÃO
177
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
MOVLW .2 ;NÃO, W = 2
XORWF CAPTURA,W ;W = CAPTURA XOR 2
BTFSC STATUS,Z ;CAPTURA = 2?
GOTO CALC_INC ;SIM
CALC_INC
MOVF CCPR1L,W ;W = CCPR1L
MOVWF REG1B ;REG1B = CCPR1L
MOVF CCPR1H,W ;W = CCPR1H
MOVWF REG2B ;REG2B = CCPR1H
Os passos para efetuar essa operação são semelhantes aos realizados numa
operação de subtração no sistema decimal.
Por exemplo, para subtrair o número 32 do número 164, primeiramente
subtraímos os algarismos menos significativos, ou seja, as unidades:
1 6 4 -
0 3 2
2 =
1 6 4 -
0 3 2
1 3 2 =
178
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
1 9 2 -
0 6 5
=
1 9 2 -
1 8 12
0 6 5
7 =
1 9 2 -
1 8 12
0 6 5
2 7 =
E, finalmente a centena:
1 9 2 -
1 8 12
0 6 5
1 2 7 =
1 0 2 -
0 3 4
=
179
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
1 0 2 -
0 10 2
0 3 4
=
1 0 2 -
0 10 2
0 9 12
0 3 4
8 =
1 0 2 -
0 10 2
0 9 12
0 3 4
6 8 =
1 0 2 -
0 10 2
0 9 12
0 3 4
0 6 8 =
180
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
REG1B -
REG1A
RESULTADO RESULTADO
POSITIVO NEGATIVO
REG2B - DECREMENTA
REG2A REG2B
RESULTADO RESULTADO
REG2B ≠ 255 REG2B = 255
POSITIVO NEGATIVO
OPERAÇÃO
CONCLUÍDA
Figura 2
181
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
182
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
TST_NR_INC
MOVF REG2B,W ;W = REG2B
SUBLW .3 ;W = 3 – REG2B
183
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
TST_MENOR_3
MOVF REG2B,W ;W = REG2B
SUBLW .2 ;W = 2 – REG2B
BTFSC STATUS,C ;REG2B MENOR DO QUE 3?
GOTO SAI_INT ;SIM
Caso REG1B seja igual ou menor do que 232, o resultado será positivo, o que
indica que o número de incrementos é menor do que 1.000 e, por isso, saímos da interrupção:
Se REG1B for maior do que 232, o resultado será negativo, o que significa
que o número de incrementos é maior do que 1.000, então, zeramos a variável CAPTURA, e testamos
se o flag CALCULAR_FREQ está setado:
184
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
185
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
186
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
INICIA_DIVISAO
CLRF UNI_TEMP ;UNI_TEMP = 0
CLRF DEZ_TEMP ;DEZ_TEMP = 0
CLRF CEN_TEMP ;CEN_TEMP = 0
CLRF MIL_TEMP ;MIL_TEMP = 0
187
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Se o valor de MILHAO_4 for igual a 255, a divisão terminou, caso contrário, foi
possível efetuar a divisão e então entramos na subrotina INC_UNI_TEMP:
188
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
MOVLW .10 ;W = 10
XORWF MIL_TEMP,W ;W = MIL_TEMP XOR 10
BTFSS STATUS,Z ;MIL_TEMP = 10?
GOTO CICLO_DE_SUBTRACAO ;NÃO
CLRF MIL_TEMP ;SIM, MIL_TEMP = 0
GOTO DIVISAO_TERMINOU
189
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
;*************************************************************************************************
END ;FIM DO PROGRAMA
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
Configuramos o registrador TRISA para que os pinos RA0, RA1, RA2 e RA3
sejam saídas e os demais entradas e o TRISB para que o pino RB3 seja entrada e os demais saídas:
MOVLW B'00000101'
MOVWF PIE1 ;HABILITA AS INTERRUPÇÕES DO TIMER 1 E DO MÓDULO CCP
190
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
MOVLW B'00000001'
MOVWF T1CON ;HABILITA TIMER 1 COM PRESCALER DE 1:1
MOVLW B'00000101'
MOVWF CCP1CON ;HABILITA MODO CAPTURE A CADA MUDANÇA DE BAIXO PARA ALTO
;***********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
;***********************************************************************************************
; PROGRAMA: FREQUENCIMETRO
; VERSÃO 1.0
; DESENVOLVIDO POR: MULDER_FOX
; DATA DE CONCLUSÃO: / /
;***********************************************************************************************
;***********************************************************************************************
; BITS DE CONFIGURAÇÃO
__CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF &
_LVP_OFF & _CP_OFF & DATA_CP_OFF
191
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
;**********************************************************************************************
; PAGINACAO DE MEMORIA
;***********************************************************************************************
; VARIÁVEIS
;***********************************************************************************************
; SAÍDAS
192
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
;***********************************************************************************************
; FLAGS
;***********************************************************************************************
; VETOR DE RESET
;*************************************************************************************************
; ROTINA DE INTERRUPÇÃO
INT_TIMER_0
BCF INTCON,T0IF ;APAGA FLAG
DECFSZ DISP_DELAY,F ;DECREMENTA DISP_DELAY. DISP_DELAY = 0?
GOTO TESTA_DIG_ATIVO ;NÃO
BSF ATUALIZA_DISP ;SIM, SETA FLAG
TESTA_DIG_ATIVO
BTFSC DIG_MIL ;DÍGITO DO MILHAR ESTÁ ATIVADO?
GOTO CONT_DIG_CEN ;SIM
BTFSC DIG_CEN ;NÃO, DÍGITO DA CENTENA ESTÁ ATIVADO?
GOTO CONT_DIG_DEZ ;SIM
BTFSC DIG_DEZ ;NÃO, DÍGITO DA DEZENA ESTÁ ATIVADO?
GOTO CONT_DIG_UNI ;SIM
GOTO CONT_DIG_MIL ;NAO
CONT_DIG_CEN
BCF DIG_MIL ;DESATIVA DÍGITO DO MILHAR
BCF SEG_A ;APAGA SEGMENTO
BCF SEG_B ;APAGA SEGMENTO
BCF SEG_C ;APAGA SEGMENTO
BCF SEG_D ;APAGA SEGMENTO
BCF SEG_E ;APAGA SEGMENTO
BCF SEG_F ;APAGA SEGMENTO
BCF SEG_G ;APAGA SEGMENTO
BSF DIG_CEN ;ATIVA DÍGITO DA CENTENA
MOVF CENTENA,W ;COPIA CENTENA PARA O W
GOTO CONV_BIN_7_SEG ;CHAMA SUBROTINA
193
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
CONT_DIG_DEZ
BCF DIG_CEN ;DESATIVA DÍGITO DA CENTENA
BCF SEG_A ;APAGA SEGMENTO
BCF SEG_B ;APAGA SEGMENTO
BCF SEG_C ;APAGA SEGMENTO
BCF SEG_D ;APAGA SEGMENTO
BCF SEG_E ;APAGA SEGMENTO
BCF SEG_F ;APAGA SEGMENTO
BCF SEG_G ;APAGA SEGMENTO
BSF DIG_DEZ ;ATIVA DÍGITO DA DEZENA
MOVF DEZENA,W ;COPIA DEZENA PARA O W
GOTO CONV_BIN_7_SEG ;CHAMA SUBROTINA
CONT_DIG_UNI
BCF DIG_DEZ ;DESATIVA DÍGITO DA DEZENA
BCF SEG_A ;APAGA SEGMENTO
BCF SEG_B ;APAGA SEGMENTO
BCF SEG_C ;APAGA SEGMENTO
BCF SEG_D ;APAGA SEGMENTO
BCF SEG_E ;APAGA SEGMENTO
BCF SEG_F ;APAGA SEGMENTO
BCF SEG_G ;APAGA SEGMENTO
BSF DIG_UNI ;ATIVA DÍGITO DA UNIDADE
MOVF UNIDADE,W ;COPIA UNIDADE PARA O W
GOTO CONV_BIN_7_SEG ;CHAMA SUBROTINA
CONT_DIG_MIL
BCF DIG_UNI ;DESATIVA DÍGITO DA UNIDADE
BCF SEG_A ;APAGA SEGMENTO
BCF SEG_B ;APAGA SEGMENTO
BCF SEG_C ;APAGA SEGMENTO
BCF SEG_D ;APAGA SEGMENTO
BCF SEG_E ;APAGA SEGMENTO
BCF SEG_F ;APAGA SEGMENTO
BCF SEG_G ;APAGA SEGMENTO
BSF DIG_MIL ;ATIVA DÍGITO DA MILHAR
MOVF MILHAR,W ;COPIA MILHAR PARA O W
GOTO CONV_BIN_7_SEG ;CHAMA SUBROTINA
CONV_BIN_7_SEG
ADDWF PCL,F ;PCL = PCL + W
GOTO NUM_ZERO ;W = 0
GOTO NUM_UM ;W = 1
GOTO NUM_DOIS ;W = 2
GOTO NUM_TRES ;W = 3
GOTO NUM_QUATRO ;W = 4
GOTO NUM_CINCO ;W = 5
GOTO NUM_SEIS ;W = 6
GOTO NUM_SETE ;W = 7
GOTO NUM_OITO ;W = 8
GOTO NUM_NOVE ;W = 9
NUM_ZERO
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
GOTO SAI_INT
194
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
NUM_UM
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_DOIS
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_TRES
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_QUATRO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_CINCO
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_SEIS
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_SETE
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
GOTO SAI_INT
NUM_OITO
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_E ;ACENDE SEGMENTO
195
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
NUM_NOVE
BSF SEG_A ;ACENDE SEGMENTO
BSF SEG_B ;ACENDE SEGMENTO
BSF SEG_C ;ACENDE SEGMENTO
BSF SEG_D ;ACENDE SEGMENTO
BSF SEG_F ;ACENDE SEGMENTO
BSF SEG_G ;ACENDE SEGMENTO
GOTO SAI_INT
INT_TIMER_1
INT_CCP
PRIMEIRA_CAPTURA
MOVF CCPR1L,W ;W = CCPR1L
MOVWF REG1A ;REG1A = CCPR1L
MOVF CCPR1H,W ;W = CCPR1H
MOVWF REG2A ;REG2A = CCPR1H
CLRF REG3B ;REG3B = 0
GOTO SAI_INT ;SAI DA INTERRUPÇÃO
CALC_INC
MOVF CCPR1L,W ;W = CCPR1L
MOVWF REG1B ;REG1B = CCPR1L
MOVF CCPR1H,W ;W = CCPR1H
MOVWF REG2B ;REG2B = CCPR1H
MOVF REG1A,W ;W = REG1A
SUBWF REG1B,F ;REG1B = REG1B - REG1A
BTFSC STATUS,C ;RESULTADO NEGATIVO?
GOTO SEG_SUB ;NÃO
DECF REG2B,F ;SIM, DECREMENTA REG2B
MOVLW .255 ;W = 255
XORWF REG2B,W ;W = REG2B XOR 255
196
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
TST_NR_INC
MOVF REG2B,W ;W = REG2B
SUBLW .3 ;W = 3 – REG2B
BTFSC STATUS,C ;REG2B MAIOR DO QUE 3?
GOTO TST_MENOR_3 ;NAO
CLRF CAPTURA ;SIM, CAPTURA = 0
BTFSC CALCULAR_FREQ ;FREQUÊNCIA SENDO CALCULADA?
GOTO SAI_INT ;SIM, SAI DA INTERRUPÇÃO
GOTO COPIA_NR_INC ;NAO, DESVIA
TST_MENOR_3
MOVF REG2B,W ;W = REG2B
SUBLW .2 ;W = 2 – REG2B
BTFSC STATUS,C ;REG2B MENOR DO QUE 3?
GOTO SAI_INT ;SIM, SAI DA INTERRUPÇÃO
MOVF REG1B,W ;NÃO, W = REG1B
SUBLW .232 ;W = 232 – REG1B
BTFSC STATUS,C ;REG1B MAIOR DO QUE 232?
GOTO SAI_INT ;NÃO, SAI DA INTERRUPÇÃO
CLRF CAPTURA ;SIM, CAPTURA = 0
BTFSC CALCULAR_FREQ ;FREQUÊNCIA SENDO CALCULADA?
GOTO SAI_INT ;SIM, SAI DA INTERRUPÇÃO
GOTO COPIA_NR_INC ;NAO, DESVIA
SAI_INT
SWAPF STATUS_TEMP,W ;SWAP EM STATUS_TEMP
MOVWF STATUS ;RECUPERA STATUS
SWAPF W_TEMP,F ;SWAP EM W_TEMP
SWAPF W_TEMP,W ;RECUPERA W
RETFIE ;RETORNA DA INTERRUPÇÃO
;***********************************************************************************************
; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO
INICIO
197
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
;***********************************************************************************************
; INICIALIZACAO DAS VARIAVEIS
;***********************************************************************************************
PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA
INICIA_DIVISAO
CLRF UNI_TEMP ;UNI_TEMP = 0
CLRF DEZ_TEMP ;DEZ_TEMP = 0
CLRF CEN_TEMP ;CEN_TEMP = 0
CLRF MIL_TEMP ;MIL_TEMP = 0
CICLO_DE_SUBTRACAO
CLRWDT ;LIMPA O WDT
MOVF REG1C,W ;W = REG1C
SUBWF MILHAO_1,F ;MILHAO_1 = MILHAO_1 - REG1C
BTFSC STATUS,C ;RESULTADO NEGATIVO?
GOTO SEG_DIV_1 ;NÃO
DECF MILHAO_2,F ;SIM, DECREMENTA MILHAO_2
MOVLW .255 ;W = 255
XORWF MILHAO_2,W ;W = MILHAO_2 XOR 255
198
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
199
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
DIVISAO_TERMINOU
BCF CALCULAR_FREQ ;APAGA FLAG
BTFSS ATUALIZA_DISP ;ATUALIZAR O DISPLAY?
GOTO PRINCIPAL ;NÃO
BCF ATUALIZA_DISP ;SIM, APAGA FLAG
MOVF UNI_TEMP,W ;W = UNI_TEMP
MOVWF UNIDADE ;UNIDADE = UNI_TEMP
MOVF DEZ_TEMP,W ;W = DEZ_TEMP
MOVWF DEZENA ;DEZENA = DEZ_TEMP
MOVF CEN_TEMP,W ;W = CEN_TEMP
MOVWF CENTENA ;CENTENA = CEN_TEMP
MOVF MIL_TEMP,W ;W = MIL_TEMP
MOVWF MILHAR ;MILHAR = MIL_TEMP
GOTO PRINCIPAL
;*************************************************************************************************
END ;FIM DO PROGRAMA
200
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Figura 3
Com essa configuração, o pino RB3 ficará alternando de nível a cada 833
ciclos de instrução, ou seja, a cada 833 microssegundos, o que corresponde a um sinal de frequência
de 600 Hz. Ou seja, estamos simulando que um sinal de 600 Hz está presente no pino RB3.
Remova o breakpoint do início da rotina de interrupção e insira um na
primeira instrução da rotina de interrupção do módulo CCP (BCF PIR1,CCP1IF).
Clique no botão “Run”.
Quando a simulação parar no breakpoint, vá clicando no botão “Step Into”.
Repare que é executada a subrotina da primeira captura.
Clique no botão “Run” novamente.
Quando a simulação parar no breakpoint, repare que, por ser a 2ª captura, é
executada a subrotina “CALC_INC”. Depois, em TST_NR_INC, é verificado que o número de
incrementos é maior do que 1.000, e, então, o flag para calcular a frequência é setado.
201
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Figura 4
Para a frequência de 600 Hz, o cálculo foi feito com base no número de
incrementos entre a 1ª e a 2ª capturas.
Vamos testar com um sinal de 3.012 Hz, cujo período é de 332
microssegundos. Sendo maior do que 1.000 Hz, o cálculo será feito com base no número de
incrementos entre a 1ª e a 101ª capturas.
No “Stimulus”, na aba “Clock Stimulus”, mude o valor das colunas “Low
Cyc” e “High Cyc” para 166, valor, em microssegundos, de meio ciclo da frequência de 3.012 Hz e
clique em “Save” e em “Apply”.
Clique no botão “Reset” da barra de ferramentas do simulador.
Insira um breakpoint na linha da primeira istrução da rotina de interrupção do
módulo CCP.
Clique no botão “Run”.
202
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Figura 5
203
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 8 – Frequencímetro
Figura 6
Aqui termina a parte 8 do tutorial. Espero que ela tenha sido útil para você.
Na 9ª parte, vamos usar o PIC16F628A para controlar um LED RGB, onde
iremos gerar 3 sinais PWM por software. Até lá.
204