Baixe o app para aproveitar ainda mais
Prévia do material em texto
Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 1 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 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 2 Os microcontroladores precisam de um sinal de clock para funcionar, mas muitos modelos possuem a alternativa de usar um circuito oscilador interno para gerar esse sinal. Este é o caso do PIC16F628A, onde podemos escolher a frequência de 48 KHz ou a de 4 MHz. A configuração do oscilador interno como fonte do sinal de clock e a sua frequência são feitos no programa que é gravado no PIC. Antes de escrevermos o programa para o microcontrolador, vamos desenhar o esquema do circuito. Segundo consta no datasheet do PIC16F628A, a sua tensão de alimentação pode ser de 3 v até 5,5V, sendo que com 3 v, a frequência máxima do sinal de clock é de 10 MHz enquanto que a partir de 4,5V é de 20Mhz. Vamos utilizar um regulador de tensão LM7805 para fornecer uma tensão de 5 v a partir de 9 v. Além do LM7805 e do PIC16F628A iremos utilizar um LED e um resistor para limitar sua corrente, que serão ligados diretamente no pino do PIC, já que ele tem a capacidade de fornecer a corrente necessária para o LED. Mas, em qual pino do PIC iremos ligar o LED? O PIC16F628A possui 15 pinos que podem ser usados como entrada ou saída: RA0, RA1, RA2, RA3, RA4, RA6, RA7, RB0, RB1, RB2, RB3, RB4, RB5, RB6 e RB7 e 1 pino que só pode ser usado como entrada: RA5. O pino RA4 é o único que, quando configurado como saída, é do tipo open drain, ou seja, a carga conectada a este pino deve estar ligada ao positivo da alimentação. É possível fazer com que resistores de pull-up integrados no PIC sejam conectados nos pinos RB0, RB1, RB2, RB3, RB4, RB5, RB6 e RB7, individualmente, para o caso de um ou mais destes pinos estarem sendo usados como entrada, economizando, desta forma, o uso de resistores externos. Veremos como fazer isto em outra parte deste tutorial. Antes de definirmos qual pino iremos utilizar, precisamos saber se as características do pino atendem às nossas necessidades. No nosso circuito precisaremos de um pino que possa ser usado como saída e, portando, temos 15 à nossa disposição. Podemos escolher qualquer um deles, por exemplo, o RA0. Portanto, o esquema do circuito ficou assim: Figura 2 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 3 Definido o esquema do circuito, vamos elaborar o fluxograma do programa que iremos gravar no PIC. O fluxograma é uma representação gráfica de como o programa se comporta conforme as possíveis situações. Com o fluxograma, fica mais fácil escrever o programa. Eis o fluxograma do nosso programa: Início Configuração dos registradores Indica o início Indica uma subrotina Inicialização das variáveis Passou 0,5 segundo? não sim Acende LED LED está aceso? Apaga LED sim não Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 4 Indica uma decisão Indica acesso a um dispositivo de I/O Agora podemos começar a escrever o programa utilizando o software MPLAB IDE da Microchip. Faça o download do MPLAB IDE do site da Microchip e instale em seu computador. A última versão disponível na data que foi escrito este tutorial é a 8.63.00.00. A tela inicial do MPLAB IDE pode ser vista na figura 3. No menu “File”, clique em “New”. Novamente, no menu “File”, clique em “Save As...” e escolha um nome para o arquivo, com a extensão .asm. Por exemplo: Pisca LED .asm. Figura 3 Primeiramente vamos criar um cabeçalho onde irá constar o nome do programa, sua versão, o nome do autor e a data de conclusão, ficando assim: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 5 ;*********************************************************************************************** ; 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 damemó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 ;********************************************************************************************** Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 6 São 2 “underlines” antes do CONFIG, seguido de espaço e, após, as expressões antecedidas de 1 “underline” separadas pelo símbolo “&” entre espaços. Nos Bits de Configuração selecionamos o tipo de oscilador que será usado e se os seguintes recursos serão ativados: WDT (Watch Dog Timer), PWRTE (Power-up Timer), MCLRE (Master Clear Enable), BOREN (Brown-out Reset), LVP (Low Voltage Program), DATA_CP (proteção da memória de dados), CP (proteção da memória de programa). As opções para seleção do oscilador são: _LP_OSC : Cristal de frequência até cerca de 1MHz ligado entre os pinos OSI e OSO. _XT_OSC : Cristal de frequência de cerca de 1MHz a 4 MHz ligado entre os pinos OSI e OSO. _HS_OSC : Cristal de frequência superior a 4 MHz ligado entre os pinos OSI e OSO. _EXTCLK_OSC : Sinal de clock externo aplicado no pino CLKIN. _INTOSC_OSC_NOCLKOUT : Oscilador interno. _INTOSC_OSC_CLKOUT : O mesmo que o anterior, porém com saída do sinal de clock no pino CLKOUT (¼ da frequência) para fins de sincronização de hardware externo. _RC_OSC_NOCLKOUT : Oscilador a base de resistor e capacitor ligados no pino CLKIN. _RC_OSC_CLKOUT : O mesmo que o anterior, porém com saída do sinal de clock no pino CLKOUT (¼ da frequência) para fins de sincronização de hardware externo. No nosso caso, escolhemos a opção _INTOSC_OSC_NOCLKOUT, ou seja, oscilador interno sem saída do sinal. O WDT (Watch Dog Timer) é um recurso que reinicia o microcontrolador, caso o programa travar. Vamos habilitar esse recuso escrevendo _WDT_ON. Se não quiséssemos ativar o recurso escreveríamos _WDT_OFF. O PWRTE (Power-up Timer) é um circuito que mantém o microcontrolador em reset por 72 ms após a alimentação ser ligada para que dê tempo do oscilador estabilizar. Vamos habilitar também este recurso escrevendo _PWRTE_ON. O MCLRE (Master Clear Enable), se estiver ativado, reserva o pino MCLR para a função de reset do microcontrolador. Este recurso não nos interessa e, por isso, o deixamos desligado, escrevendo _MCLRE_OFF. O BOREN (Brown-out reset) é um recurso que monitora a tensão de alimentação e quando ela cai abaixo de 4,5V provoca o reset. Este recurso também não nos interessa e, por isso, escrevemos _BOREN_OFF. O LVP (Low Voltage Program) é um recurso que permite que o microcontrolador seja gravado sem a necessidade de aplicar uma tensão de cerca de 13V no pino VPP (veremos sobre gravação do PIC no momento oportuno). Esta função não nos interessa e, por isso, escrevemos _LVP_OFF. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 7 DATA_CP é um recurso para proteger a memória de dados contra cópia. CP é um recurso para proteger a memória de programa contra cópias. Estes recursos interessam a quem fabrica aparelhos eletrônicos e quer evitar engenharia reversa. Estes recursos não nos interessam, e, por isso, escrevemos _CP_OFF & DATA_CP_OFF. O próximo passo é definir as “labels” para a comutação dos bancos de memória de dados. Fazemos isto utilizando a diretiva #DEFINE desta forma: ;********************************************************************************************** ; PAGINACAO DE MEMORIA #DEFINE BANCO_0 BCF STATUS,RP0 ;SETA BANCO 0 DE MEMORIA #DEFINE BANCO_1 BSF STATUS,RP0 ;SETA BANCO 1 DE MEMORIA ;********************************************************************************************** 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. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 8 Figura 4 O próximo passo é definir as variáveis que iremos utilizar em nosso programa. Uma variável é um Registrador de Uso Geral, ou seja, é uma das posições da memória de dados que podemos usar para armazenar os valores dos dados que vamos manipular no nosso programa. À medida que vamos escrevendo o programa, vamos precisando criar Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 9 variáveis. Por esse motivo, minha forma preferida para defini-las é com o uso da diretiva CBLOCK: ;********************************************************************************************** ; VARIAVEIS CBLOCK 0X20 ;ENDERECO INICIAL DA MEMORIA DO USUARIO DELAY_0 ;USADO PARA GERAR O TEMPO DE 0,5 SEGUNDO DELAY_1 ;USADO PARA GERAR O TEMPO DE 0,5 SEGUNDO DELAY_2 ;USADO PARA GERAR O TEMPO DE 0,5 SEGUNDO ENDC ;FIM DO BLOCO DE MEMORIA ;********************************************************************************************** A expressão 0X20 após a diretiva CBLOCK indica o endereço na memória de dados que assumirá a primeira variável definida (DELAY_0). Esse endereço está em formato hexadecimal. Veja na figura 4 queele (lá representado por 20h) é o primeiro, no banco 0, que podemos usar como Registrador de Uso Geral. Repare que o último é o 7Fh, totalizando 96 localidades de memória nesse banco. Os do endereço 70 até 7F são espelhados nos outros bancos, permitindo que possam ser acessados sem necessidade de selecionar o banco. No banco 1 temos outras 80 posições e no banco 2 mais 48. Portanto, no PIC16F628A temos um total de 224 posições de memória (registradores) que podemos usar para armazenar valores. Ou seja, podemos criar até 224 variáveis. Voltando a falar da diretiva CBLOCK, após relacionar os nomes das nossas variáveis, encerramos a diretiva com ENDC. Desta forma, definimos o endereço 0X20 para DELAY_0, 0X21 para DELAY_1 e 0X22 para DELAY_2. Se posteriormente quisermos adicionar outras variáveis, podemos intercalá- las sem problemas. Há outras formas de definir variáveis, através das diretivas #DEFINE e EQU, mas creio que a mais prática seja através da diretiva CBLOCK. O próximo passo é definir as constantes. Constantes são valores numéricos que utilizamos durante o programa. Por exemplo, uma determinada variável pode precisar ser reiniciada sempre com o mesmo valor. Este valor é uma constante. No nosso programa, as variáveis DELAY_0, DELAY_1 c DELAY_2 serão reiniciadas, cada qual, com valores que serão sempre os mesmos. Esses valores serão ajustados depois que fizermos a rotina principal do programa, por isso, os valores que iremos escrever agora serão provisórios. Para definir as constantes, usamos a diretiva EQU: ;********************************************************************************************** ; CONSTANTES INI_DELAY_0 EQU .255 ;VALOR QUE DELAY_0 INICIA INI_DELAY_1 EQU .50 ;VALOR QUE DELAY_1 INICIA INI_DELAY_2 EQU .13 ;VALOR QUE DELAY_2 INICIA ;*********************************************************************************************** Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 10 No momento em que o MPLAB for montar o programa, onde estiver escrito INI_DELAY_0, ele irá substituir essa expressão pelo valor 255 (decimal); INI_DELAY_1 por 50 e INI_DELAY_2 por 13. A vantagem de fazer isso é que se constatarmos que os valores para aquelas variáveis não estavam satisfatórios, basta alterá-los ali, em vez de modificá-los em todas as linhas do programa onde forem feitas reinicializações das variáveis. A propósito, vamos falar de como representar, no programa, os valores numéricos usando o número 10 como exemplo. Quando estivermos nos referindo ao número 10 do sistema decimal, escreveremos assim: D'10' ou ainda .10 Se for o numero 10 do sistema binário (2 do sistema decimal), escreveremos assim: B'10' Se for o número 10 do sistema hexadecimal (16 do sistema decimal), escreveremos assim: H'10' ou assim: 0X10 A seguir vamos atribuir a “label” LED para o bit 0 do registrador PORTA. ;*********************************************************************************************** ; SAÍDA #DEFINE LED PORTA,0 ;LED LIGADO EM RA0 ;*********************************************************************************************** A diretiva #DEFINE atribuiu a “label” LED para o bit 0 do registrador PORTA. Toda vez que aparecer no programa a palavra LED, o MPLAB saberá que se trata do bit 0 do registrador PORTA. Os registradores associados aos pinos de I/O são o PORTA e o PORTB. O próprio nome do pino já nos diz qual é o registrador e o bit. Pino RA0 – bit 0 do PORTA Pino RA1 – bit 1 do PORTA Pino RA2 – bit 2 do PORTA Pino RA3 – bit 3 do PORTA Pino RA4 – bit 4 do PORTA Pino RA5 – bit 5 do PORTA Pino RA6 – bit 6 do PORTA Pino RA7 – bit 7 do PORTA Pino RB0 – bit 0 do PORTB Pino RB1 – bit 1 do PORTB Pino RB2 – bit 2 do PORTB Pino RB3 – bit 3 do PORTB Pino RB4 – bit 4 do PORTB Pino RB5 – bit 5 do PORTB Pino RB6 – bit 6 do PORTB Pino RB7 – bit 7 do PORTB Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 11 Quando um pino estiver configurado como entrada (veremos depois como se faz a configuração dos pinos como entradas ou saídas), o nível lógico presente nele poderá ser verificado fazendo-se a leitura do valor do bit correspondente. Se o valor do bit é igual a 1, então o nível lógico no pino é alto e vice-versa. Por exemplo, suponhamos que o pino RB2 esteja configurado como entrada. Para sabermos qual é o seu nível lógico, fazemos a leitura do bit 2 do registrador PORTB (veremos no momento oportuno como verificar o nível lógico de um bit). Para o pino RA6, lemos o bit 6 do PORTA e assim por diante. Se um pino estiver configurado como saída, e quisermos levar o seu nível para alto, tornamos o valor do seu bit correspondente igual a 1. Para levar o pino para nível baixo, tornamos o valor do bit correspondente igual a 0, ou seja, controlando o valor do bit controlamos o nível no pino. O próximo passo é o vetor de reset. ;*********************************************************************************************** ; VETOR DE RESET ORG 0X00 ;ENDERECO INICIAL DE PROCESSAMENTO GOTO INICIO ;DESVIA PARA INICIO ;*********************************************************************************************** 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 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 12 ;*********************************************************************************************** Em outra parte deste tutorial falaremos detalhadamente sobre interrupções. O próximopasso é configurar os Registradores de Uso Específico. ;*********************************************************************************************** ; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO INICIO BANCO_1 ;SELECIONA BANCO 1 DE MEMORIA MOVLW B'11111110' ;W = B'11111110' MOVWF TRISA ;CONFIGURA RA0 COMO SAÍDA E DEMAIS COMO ENTRADAS 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 ;*********************************************************************************************** Repare que aqui está a label INICIO. Nesta parte do programa devemos configurar todos os Registradores de Uso Específico que estejam envolvidos com os recursos do microcontrolador que iremos utilizar. Por exemplo, se formos utilizar o TIMER 0, teremos de configurar o registrador relacionado a ele. Se formos utilizar o módulo de PWM, devemos configurar o registrador a ele relacionado e assim por diante, por isto devemos ler o datasheet do microcontrolador para sabermos quais registradores deveremos configurar. No nosso circuito estamos utilizando o pino RA0 do PORTA e por isto, devemos configurar o registrador TRISA, responsável por definir cada pino do PORTA como entrada ou saída. Aqui também há uma relação direta entre o bit e o pino. O bit 0 do TRISA configura o pino RA0, o bit 1 o pino RA1 e assim por diante. Se for atribuído o valor 0 para o bit, o pino é configurado como saída e se for atribuído o valor 1, o pino é configurado como entrada. Memorize essa regra. Observe, na figura 4, que o registrador TRISA está no banco 1. Para termos acesso a esse registrador precisamos selecionar o banco 1, escrevendo BANCO_1 (label que definimos para isso). Os demais pinos não serão utilizados e não precisamos configurá-los, mas aqui vai uma dica: Configure como entrada os pinos que não estiverem sendo utilizados, pois, se estiverem configurados como saída e se, por engano, um destes pinos for ligado diretamente ao VSS ou ao VDD, poderá provocar a queima do microcontrolador. Estando configurados como entrada, eles assumem alta impedância e não tem problema se forem ligados diretamente no VDD ou no VSS. O pino RA0 será configurado como saída e os demais pinos do PORTA como entrada, então, precisamos escrever o número binário 11111110 no registrador TRISA (os bits em um registrador estão na seguinte ordem: bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0). Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 13 Não existe uma instrução para escrever diretamente um número num registrador do PIC16F628A. No microcontrolador existe um registrador chamado de W (Work). Quando queremos escrever um número num registrador, primeiramente devemos escrever esse número no registrador W. Fazemos isso com a instrução MOVLW, desta forma: MOVLW B'11111110' Assim, escreve-se no registrador W o número binário 11111110. O nome das instruções foram criados de forma a lembrar a sua função. No caso da instrução MOVLW, MOV lembra mover. L lembra literal. A instrução MOVLW move um número para o registrador W. Reparou na correspondência? (move L para W). Com o número já escrito no registrador W, podemos escrevê-lo no registrador TRISA, usando a instrução MOVWF, assim: MOVWF TRISA A instrução MOVWF move o que estiver no registrador W para o registrador escrito após a instrução, no caso, o TRISA. Melhor dizendo, o conteúdo do registrador W é copiado para o TRISA, pois, depois de executada a instrução, o registrador W continua com o mesmo valor que estava antes. Pronto, configuramos o pino RA0 para funcionar como saída e os demais pinos do PORTA para funcionarem como entrada. Agora vamos configurar todos os pinos do PORTB como entrada, pelo mesmo motivo que configuramos os outros pinos do PORTA. O registrador TRISB é onde configuramos os pinos do PORTB como entrada ou saída: MOVLW B'11111111' MOVWF TRISB No PIC16F628A, bem como noutros modelos de microcontroladores, a maioria dos pinos são compartilhados por mais de um recurso do microcontrolador. É o caso do pino RA0 que estamos utilizando. Além de ele ser um pino que podemos usar como entrada ou saída de sinal, também é um dos pinos de entrada do módulo comparador. O módulo comparador é um circuito do PIC16F628A que funciona como um CI comparador de tensão. Na inicialização do PIC16F628A, os pinos RA0, RA1, RA2 e RA3, estão vinculados ao módulo comparador de tensão e, por isso, para que possamos utilizá-los como pinos de entrada ou saída de sinal, precisamos configurar o registrador CMCON. O registrador CMCON está no banco 0 de memória, conforme você pode ver na figura 4 e, então, selecionamos este banco, escrevendo BANCO_0. Conforme pode ser visto no datasheet do PIC16F628A, se os bits 2, 1 e 0 do CMCON tiverem os valores 1, 0, e 1, respectivamente, os pinos RA0 e RA3 ficarão disponíveis para serem usados como entrada ou saída e se os valores desses mesmos bits forem 1, 1 e 1, os pinos RA0, RA1, RA2 e RA3 ficaram disponíveis. No nosso caso qualquer das duas alternativas serve, pois, só iremos usar o pino RA0. Então, vamos escrever o valor B'00000111' no registador CMCON: MOVLW B'00000111' Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 14 MOVWF CMCON São apenas esses os Registradores de Uso Específico que precisamos configurar nesse programa. O próximo passo é inicializar as variáveis. ;*********************************************************************************************** ; INICIALIZACAO DAS VARIAVEIS MOVLW INI_DELAY_0 ;W = INI_DELAY_0 MOVWF DELAY_0 ;INICIALIZA DELAY_0 MOVLW INI_DELAY_1 ;W = INI_DELAY_1 MOVWF DELAY_1 ;INICIALIZA DELAY_1 MOVLW INI_DELAY_2 ;W = INI_DELAY_2 MOVWF DELAY_2 ;INICIALIZA DELAY_2 ;*********************************************************************************************** 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. O próximo passo é a rotina principal do programa. Nosso programa aguarda que passe meio segundo e testa o LED para ver se está aceso ou apagado. Se estiver aceso, apaga e se estiver apagado, acende, voltando a aguardar meio segundo para testar o LED novamente. Há mais de uma forma de contar este tempo de meio segundo. Neste programa vamos fazer isso decrementando os valores de variáveis. No próximo programa iremos utilizar outra forma mais eficiente. Nossa rotina irá decrementar a variável DELAY_0 até que ela chegue ao valor 0. Quando DELAY_0 chega ao valor 0, ela é reiniciada e a variável DELAY_1 é decrementada. Quando DELAY_1 chega a 0, ela é reiniciada e a variável DELAY_2 é decrementada. Quando DELAY_2 chegar a 0 terá passado aproximadamente meio segundo. A maioria das instruções no PIC16F628A são executadas em 1 ciclo de instrução, sendo 1 ciclode instrução igual a 4 ciclos do sinal de clock. Algumas instruções são executadas em 2 ciclos de instrução, entre elas GOTO e CALL. Neste projeto, estamos utilizando o oscilador interno numa frequência de 4 MHz e, portando, o ciclo do sinal de clock é de 250 nanosegundos (1/4.000.000). Sendo assim, o ciclo de instrução é de 1 microssegundo. Durante a simulação, iremos medir o tempo gasto até que DELAY_2 chegue a 0, para então definirmos os valores definitivos das variáveis, pois, os valores que definimos são uma estimativa. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 15 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 Após reinicializar DELAY_0, vamos decrementar DELAY_1 e testar se seu valor chegou a 0: DECFSZ DELAY_1,F 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 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 16 Porém, se o valor de DELAY_1 chegou a 0, reiniciaremos DELAY_1 e iremos decrementar DELAY_2 e testar se o seu valor chegou a 0: MOVLW INI_DELAY_1 MOVWF DELAY_1 DECFSZ DELAY_2,F Igualmente, se DELAY_2 não chegou a 0, o programa deverá voltar para decrementar DELAY_0: GOTO PRINCIPAL Mas, se DELAY_2 chegou a 0, iremos reiniciá-la e terá terminado a contagem do tempo: MOVLW INI_DELAY_2 MOVWF DELAY_2 Parece complicado? Com a prática isso fica bem simples. Recapitulando: DELAY_0 é decrementada até que seu valor chegue a 0, quando então, DELAY_1 é decrementada. Quando DELAY_1 chega a 0, DELAY_2 é decrementada. Quando DELAY_2 chega a 0, a contagem de tempo terminou. Com os valores que escrevemos provisoriamente nestas variáveis, DELAY_0 terá que zerar 50 vezes para que DELAY_1 seja zerada, enquanto que DELAY_1 terá zerar 13 vezes para que DELAY_2 seja zerada. Fazendo os cálculos, DELAY_0 será decrementada 165750 vezes para que a contagem de tempo chegue ao fim. Parece muito? Lembre-se de que o microcontrolador executa 1 instrução em 1 microssegundo. Quando fizermos a simulação da execução do programa, iremos medir o tempo que demorou para DELAY_2 zerar e então, faremos os ajustes nos valores das variáveis, para que esse tempo seja de aproximadamente meio segundo. A rotina principal até o momento está assim: ************************************************************************************************ PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA DECFSZ DELAY_0,F ;DECREMENTA DELAY_0. DELAY_0 = 0? GOTO PRINCIPAL ;NÃO MOVLW INI_DELAY_0 ;SIM, W = INI_DELAY_0 MOVWF DELAY_0 ;REINICIALIZA DELAY_0 DECFSZ DELAY_1,F ;DECREMENTA DELAY_1. DELAY_1 = 0? GOTO PRINCIPAL ;NÃO MOVLW INI_DELAY_1 ;SIM, W = INI_DELAY_1 MOVWF DELAY_1 ;REINICIALIZA DELAY_1 DECFSZ DELAY_2,F ;DECREMENTA DELAY_2. DELAY_2 = 0? GOTO PRINCIPAL ;NÃO MOVLW INI_DELAY_2 ;SIM, W = INI_DELAY_2 MOVWF DELAY_2 ;REINICIALIZA DELAY_2 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 17 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 Com isso o LED irá apagar. Mas, se quando testamos o bit 0 do PORTA com a instrução BTFSS, o valor do bit era igual a 0, então, a próxima linha do programa seria executada. Sendo o valor do bit 0 do PORTA igual a 0, significa que o LED está apagado e, então, precisamos acendê-lo. Para isso usamos a instrução BSF para fazer o valor do bit 0 do PORTA igual a 1: BSF LED Com isso acendemos o LED. Então, este trecho do nosso programa ficou assim: BTFSS LED ;testa o valor do bit 0 do PORTA BSF LED ;valor = 0, acende o LED BCF LED ;valor = 1, apaga o LED Espere. Temos um problema aí: No caso do valor do bit ser igual a 0, ele executa a instrução BSF LED e em seguida executa a instrução BCF LED, ou seja, o LED é aceso e apagado em seguida. Como faremos para resolver isso? Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 18 Faremos assim: BTFSS LED ;testa o valor do bit 0 do PORTA GOTOACENDE_LED ;valor = 0, desvia BCF LED ;valor = 1, apaga o LED GOTO PRINCIPAL ;desvia ACENDE_LED BSF LED ;ACENDE O LED GOTO PRINCIPAL ;desvia END ;Fim do programa 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. Caso o programa trave, esta instrução não será executada, provocando o reset do microcontrolador. É assim que o WDT funciona. Vamos escrevê-la no começo da rotina principal, finalizando o programa: ;*********************************************************************************************** ; PROGRAMA: PISCA LED ; VERSÃO 1.0 ; DESENVOLVIDO POR: MULDER_FOX ; DATA DE CONCLUSÃO: / / ;*********************************************************************************************** #INCLUDE <P16F628A.INC> ;ARQUIVO PADRAO MICROCHIP PARA O PIC16F628A ;*********************************************************************************************** ; 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 #DEFINE BANCO_0 BCF STATUS,RP0 ;SETA BANCO 0 DE MEMORIA #DEFINE BANCO_1 BSF STATUS,RP0 ;SETA BANCO 1 DE MEMORIA ;********************************************************************************************** Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 19 ; VARIAVEIS CBLOCK 0X20 ;ENDERECO INICIAL DA MEMORIA DO USUARIO DELAY_0 ;USADO PARA GERAR O TEMPO DE 0,5 SEGUNDO DELAY_1 ;USADO PARA GERAR O TEMPO DE 0,5 SEGUNDO DELAY_2 ;USADO PARA GERAR O TEMPO DE 0,5 SEGUNDO ENDC ;FIM DO BLOCO DE MEMORIA ;********************************************************************************************** ; CONSTANTES INI_DELAY_0 EQU .255 ;VALOR QUE DELAY_0 INICIA INI_DELAY_1 EQU .50 ;VALOR QUE DELAY_1 INICIA INI_DELAY_2 EQU .13 ;VALOR QUE DELAY_2 INICIA ;*********************************************************************************************** ; SAÍDA #DEFINE LED PORTA,0 ;LED LIGADO EM RA0 ;*********************************************************************************************** ; VETOR DE RESET ORG 0X00 ;ENDERECO INICIAL DE PROCESSAMENTO GOTO INICIO ;DESVIA PARA INICIO ;*********************************************************************************************** ; ROTINA DE INTERRUPÇÃO ORG 0X04 ;VETOR DAS INTERRUPÇÕES RETFIE ;RETORNA ;*********************************************************************************************** ; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO INICIO BANCO_1 ;SELECIONA BANCO 1 DE MEMORIA MOVLW B'11111110' ;W = B'11111110' MOVWF TRISA ;CONFIGURA RA0 COMO SAÍDA E DEMAIS COMO ENTRADAS 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 ;*********************************************************************************************** Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 20 ;********************************************************************************************** ; INICIALIZACAO DAS VARIAVEIS MOVLW INI_DELAY_0 ;W = INI_DELAY_0 MOVWF DELAY_0 ;INICIALIZA DELAY_0 MOVLW INI_DELAY_1 ;W = INI_DELAY_1 MOVWF DELAY_1 ;INICIALIZA DELAY_1 MOVLW INI_DELAY_2 ;W = INI_DELAY_2 MOVWF DELAY_2 ;INICIALIZA DELAY_2 ;*********************************************************************************************** PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA CLRWDT ;LIMPA O WDT DECFSZ DELAY_0,F ;DECREMENTA DELAY_0. DELAY_0 = 0? GOTO PRINCIPAL ;NÃO MOVLW INI_DELAY_0 ;SIM, W = INI_DELAY_0 MOVWF DELAY_0 ;REINICIALIZA DELAY_0 DECFSZ DELAY_1,F ;DECREMENTA DELAY_1. DELAY_1 = 0? GOTO PRINCIPAL ;NÃO MOVLW INI_DELAY_1 ;SIM, W = INI_DELAY_1 MOVWF DELAY_1 ;REINICIALIZA DELAY_1 DECFSZ DELAY_2,F ;DECREMENTA DELAY_2. DELAY_2 = 0? GOTO PRINCIPAL ;NÃO MOVLW INI_DELAY_2 ;SIM, W = INI_DELAY_2 MOVWF DELAY_2 ;REINICIALIZA DELAY_2 BTFSS LED ;TESTA O VALOR DO BIT 0 DO PORTA GOTO ACENDE_LED ;VALOR = 0, DESVIA BCF LED ;VALOR = 1, APAGA O LED GOTO PRINCIPAL ;DESVIA ACENDE_LED BSF LED ;ACENDE O LED GOTO PRINCIPAL ;DESVIA ;********************************************************************************************** END ;FIM DO PROGRAMA ;********************************************************************************************** Nosso próximo passo é simular a execução do programa para ver se ele se comporta como esperamos. No menu “Project”, clique em “Project Wizard”. Na janela que se abre clique em “Avançar”: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 21 Figura 5 Na janela seguinte (“Step One”), selecione o PIC16F628A e clique em “Avançar”: Figura 6 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 22 Na próxima janela (“Step Two”), clique em “Avançar”: Figura 7 Na próxima janela (“Step Three”), clique em “Browse”: Figura 8 Na janela que se abre, escolha um local e dê um nome para o projeto, por exemplo Pisca LED e clique em “Salvar”: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 23 Figura 9 Em seguida clique em “Avançar” Figura 10 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 24 Na janela seguinte (“Step Four”), selecione o arquivo Pisca LED.asm, clique em “Add” e em seguida clique em “Avançar”: Figura 11 Na janela seguinte (“Summary”), clique em concluir: Figura 12 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 25No menu “Project”, clique em “Build All”. Na janela que se abre, clique em “Absolute”: Figura 13 A seguir, expanda a janela chamada “Output”: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 26 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”. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 27 Na janela “Watch”, clique onde está indicado na figura abaixo, selecione o PORTA e clique em “Add SFR”: Figura 15 Depois, clique onde está indicado na figura abaixo e selecione DELAY_0 e clique em “Add Symbol”. Faça o mesmo para DELAY_1 e DELAY_2. Figura 16 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 28 Em “Add SFR” adicionamos os Registradores de Uso Específico que queremos visualizar, enquanto em “Add Symbol” adicionamos as variáveis por nós criadas que queremos visualizar. No menu “Window”, clique em “Pisca LED.asm”: Figura 17 Na imagem abaixo, a seta está apontando para a barra de botões do simulador. Aponte o mouse para cada botão para ver seus nomes. São eles: “Run”, “Halt”, “Animate”, “Step Into”, “Step Over”, “Reset” e “Breakpoints”: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 29 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 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 30 Esta seta indica qual instrução está para ser executada. Clique no botão “Step Into”. Este botão executa uma instrução a cada vez que é pressionado. A instrução GOTO INICIO foi executada e, portanto, o programa foi desviado para a linha após a label INICIO. Clique novamente em “Step Into”. Agora, a instrução representada pela label BANCO_1, ou seja, BSF STATUS, RP0 foi executada e o banco 1 foi selecionado. Repare na parte de baixo da janela, que o banco selecionado é o 1: Figura 20 Outras informações podem ser vistas nessa barra, como o modelo do microcontrolador, o valor do contador de programa (0X2), o valor do registrador W, dos bits z, dc e c do registrador STATUS, etc... O contador de programa – PC, armazena o endereço na memória de programa onde está a instrução que será executado pelo microcontrolador. Veremos o significado dos valores dos bits z, dc e c do registrador STATUS em outra parte deste tutorial. Continue clicando no botão “Step Into” e acompanhando a simulação da execução do programa. Após ser executada a instrução MOVWF DELAY_0, no menu “Window” escolha a janela “Watch” e repare que a variável DELAY_0 assumiu o valor 255. Volte para a janela do programa, escolhendo-a no menu “Window”, continue clicando em “Step Into” e depois visualize na janela “Watch” que DELAY_1 e DELAY_2, assumem os valores 50 e 13 respectivamente. Continue clicando no botão “Step Into” e veja que após a instrução DECFSZ DELAY_0 ser executada, o valor de DELAY_0 passa a ser 254 e que como o seu valor é diferente de 0, o programa volta para a linha após a label PRINCIPAL, pois, executa a instrução GOTO PRINCIPAL. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 31 Se continuar clicando em “Step Into”, você poderá acompanhar a variável DELAY_0 sendo decrementada. Ela irá ser decrementada até chegar ao valor 0, quando, então, o programa irá pular a linha com a instrução GOTO PRINCIPAL. Para agilizar, na janela “Watch”, dê um duplo clique no valor da variável DELAY_0, e altere o seu valor para 1. Depois, volte a clicar em “Step Into” e repare que, como DELAY_0 chegou ao valor 0, a linha com a instrução GOTO PRINCIPAL é pulada, sendo executadas as instruções que reiniciam DELAY_0 e depois a que decrementa DELAY_1. DELAY_1, agora vale 49 e como é diferente de 0, o programa é desviado para onde está a label PRINCIPAL. A partir de agora, DELAY_0 voltará a ser decrementada até chegar a 0 de novo. Vamos mudar os valores de DELAY_0 e de DELAY_1 para 1 e continuar clicando em “Step Into”. Veremos que DELAY_1 chega a 0, é reiniciada e DELAY_2 é decrementada. Agora vamos mudar o valor das três para 1. Clicando em “Step Into” veremos que agora DELAY_2 chega a 0, é reiniciada e o programa irá executar a instrução BTFSS LED para testar o valor do bit 0 do PORTA, o que é o mesmo que verificar se o LED está aceso ou apagado. Neste teste ele constata que o valor do bit é igual a 0 e o programa, então, é desviado para a instrução após a label ACENDE_LED, onde é executada a instrução BSF LED. Em seguida ele volta para PRINCIPAL. Vá para a janela “Watch” e veja que o bit 0 do PORTA foi setado, isto é, seu valor é igual a 1, acendendo o LED. Agora, o programa voltará a decrementar as variáveis. Vamos agilizar, alterando o valor das três variáveis para 1. Desta vez no teste do bit ele verifica que o valor é 1 e executa a instrução BCF LED, fazendo o valor do bit igual a 0, apagando o LED. Verifique na janela “Watch” que o bit 0 do PORTA foi apagado (= 0). Agora vamos medir se o tempo que demora para a variável DELAY_2 chegar a 0 é de aproximadamente 500 milissegundos. Dê um duplo clique na linha que contêm a instrução BTFSS LED. Você verá que aparece uma letra B dentro de um círculo vermelho, conforme a figura abaixo: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 32 Figura 21 Você acaba de inserir um Breakpoint. O programa será interrompido toda vez que encontrar um Breakpoint ativo. Clique no botão “Reset” da barra de ferramentas do simulador e depois vá clicando em “Step Into” até chegar à linha onde está a instrução CLRWDT. No menu “Debugger”, clique em “StopWatch”. Eis a janela do “StopWatch”: Tutorial de Programação Assembly para Microcontroladores PIC- Parte 1 – Pisca LED 33 Figura 22 Nesta janela, clique no botão “Zero”. Volte para a janela do programa, selecionando-a no menu “Window” e clique no botão “Run” da barra de ferramentas do simulador. O programa será executado até a linha onde está o Breakpoint, ou seja, na linha onde está a instrução BTFSS. Volte para a janela do “StopWatch”. Veja no campo “Time” que se passaram 665 milissegundos desde que o “StopWatch” foi zerado (quando clicamos em “Zero”): Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 34 Figura 23 Ou seja, está demorando 665 milissegundos para que a variável DELAY_2 chegue a 0, mas, nós queremos que demore 500 milissegundos. Vamos medir de quanto em quanto tempo a variável DELAY_2 é decrementada. Para isto, vamos inserir outro Breakpoint na linha onde está a instrução DECFSZ DELAY_2. Após inserir o Breakpoint, clique no botão “Reset” do simulador e vá clicando no botão “Step Into” até chegar à instrução CLRWDT. Vá para a janela do “StopWatch” e clique em “Zero”. Volte para a janela do programa e clique em “Run”. Quando o programa parar na linha onde está o Breakpoint vá para a janela do “StopWatch”. Repare que passaram 51 milissegundos, ou seja, a variável DELAY_2 é decrementada a cada 51 milissegundos. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 35 Figura 24 Estamos com um excesso de 125 milissegundos no tempo total. Se nós diminuirmos o valor de inicialização da variável DELAY_2 em 3 unidades, ou seja, diminuirmos para 10, o tempo total deverá cair para cerca de 512 milissegundos. Vamos verificar. Vá para a janela do programa e na parte “CONSTANTES”, altere a linha INI_DELAY_2 EQU .13 para INI_DELAY_1 EQU .10 Como alteramos o programa, precisamos compilar de novo e para isso, no menu “Project” clique em “Build All”. Retire o Breakpoint da linha onde está a instrução DECFSZ DELAY_2, dando um duplo clique nessa linha, e deixe o outro que está na linha com a instrução BTFSS LED. Clique no botão “Reset” do simulador e vá clicando em “Step Into” até chegar à linha com a instrução CLRWDT. Neste momento, vá para a janela “StopWatch” e clique em “Zero”. Volte para a janela do programa e clique no botão “Run” do simulador. Quando o programa parar no Breakpoint, abra a janela “StopWatch”. Repare que realmente o tempo total caiu para 512 milissegundos. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 36 Figura 25 Ainda temos um excesso de 12 milissegundos. Vamos experimentar diminuir o valor de inicialização de DELAY_1 para 49, da mesma forma que mudamos o valor de DELAY_2. Lembre-se de que temos que compilar de novo, clicando no menu “Project” e em “Build All”. Agora o tempo total é bem próximo de 500 milissegundos: Figura 26 Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 37 Vamos experimentar diminuir o valor da variável DELAY_0 para 254. Agora, o tempo é de praticamente 500 milissegundos. Figura 27 Ficamos, então com estes valores para as variáveis: DELAY_0 = 254, DELAY_1 = 49 e DELAY_2 = 10. Nosso programa está como queríamos e agora é hora de gravá-lo no microcontrolador. Você poderá comprar um gravador ou montar o seu próprio gravador. Há vários modelos à venda e também vários esquemas de gravadores na Internet para quem quiser montar o seu. Existem gravadores que são conectados na porta paralela, outros na porta serial e também os que são conectados na porta USB. Os melhores são os USB, pela praticidade. Alguns gravadores funcionam com o MPLAB, enquanto outros necessitam de outro software. A figura a seguir é de um esquema de gravador para ser conectado na porta serial do computador (conector DB9). Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 38 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. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 39 Figura 29 Na próxima janela também clique em OK, deixando como está, pois, este gravador é baseado no JDM. Figura 30 Se for exibida a mensagem vista na figura a seguir ou outras de mesmo teor clique em OK. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 40 Figura 31 A janela do IC-prog é vista na figura a seguir. Figura 32 No menu “Settings”, clique em “Options”. Na aba “Language” escolha “Portuguese”. No menu “Configuração” clique em “Opções”. Na aba “Diversos”, marque “Activar Driver NT/2000/XP” Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 41 Na janela que abre clique em “Yes” para reiniciar o IC-prog. Figura 33 Na janela que se abre, perguntando se deseja instalar o driver, clique em “Yes”. Figura 34 No menu “Configuração”, clique em “Opções” e na aba “Diversos”, em “Processo Prioritário”, selecione “Alto” e clique em “OK”. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 42 No menu “Configuração”, aponte para “Dispositivo” e depois para “Microchip PIC” e escolha o PIC16F628A. No menu “Arquivo”, clique em “Abrir”. Localize e selecione o arquivo Pisca LED.hex e clique em “Abrir”. Figura 35 Repare do lado direito da janela, que o tipo de oscilador e os “Fusíveis” já estão configurados, pois nós os configuramos no programa, com a diretiva CONFIG. Certifique-se de que o gravador está conectado na porta serial do computador. No menu “Comando”, clique em “Programar Tudo” e na janela de confirmação, clique em “Yes”. Será gravado o programa no microcontrolador e depois o programa gravado será lido e comparado com o arquivo. Se estiverem iguais, será apresentada a mensagem “Dispositivo verificado com sucesso”, conforme figura a seguir. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 1 – Pisca LED 43 Figura 36 Agora podemos montar o circuito da figura 2 e constatar o seu funcionamento. Aqui termina a primeira parte deste tutorial. Espero que você tenha gostado. Na próxima parte, vamos criar um programa para a mesma finalidade, porém, utilizando o TIMER 0 para obter o intervalo de meio segundo entre as piscadas do LED. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II 44 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. Dessa forma, o TMR0 será incrementado a cada 256 ciclos de instrução, ou seja, a cada 256 microssegundos. Assim, o TMR0 irá estourar a cada 256 x 256 microssegundos, isto é, a cada 65.536 microssegundos, o que equivale a 65,536 milissegundos. Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II 45 Ou seja, mesmo com o prescaler no máximo, serão necessários mais de 1 estouros do TMR0 para obtermos o tempo que desejamos e, portanto, teremos que contar esses estouros. Porém, a divisão de 500 milissegundos por 65,536 milissegundos não resulta em um número exato. Temos que, de alguma forma, obter um número exato de estouros que correspondam ao tempo de 500 milissegundos. Como vimos, 500 milissegundos correspondem a 500.000 ciclos de instrução. Dividindo 500.000 pelos valores de prescaler disponíveis, constatamos que o maior valor do prescaler que resulta numa divisão exata é 1:32 e este valor é 15.625. Por sua vez, 15.625 é igual ao produto de 125 por 125. Com o valor do prescaler definido em 1:32, o TMR0 será incrementado a cada 32 ciclos de instrução, ou seja, a cada 32 microssegundos. Se após todas as vezes que o TMR0 estourar, nós o reiniciarmos com o valor de 131 (escrevendo este valor nele), após 125 incrementos (256 – 131) ele irá estourar, ou seja, irá estourar a cada 32 x 125 microssegundos = 4.000 microssegundos = 4 milissegundos. Se contarmos 125 estouros do TMR0, teremos o tempo de 500 milissegundos. Vamos ao programa! O fluxograma é o mesmo e o programa é igual até este ponto: ;*********************************************************************************************** ; PROGRAMA: PISCA LED II ; VERSÃO 1.0 ; DESENVOLVIDO POR: MULDER_FOX ; DATA DE CONCLUSÃO: / / ;*********************************************************************************************** #INCLUDE <P16F628A.INC> ;ARQUIVO PADRAO MICROCHIP PARA O PIC16F628A ;*********************************************************************************************** ; 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 #DEFINE BANCO_0 BCF STATUS,RP0 ;SETA BANCO 0 DE MEMORIA #DEFINE BANCO_1 BSF STATUS,RP0 ;SETA BANCO 1 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 CBLOCK 0X20 ;ENDERECO INICIAL DA MEMORIA DO USUARIO Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II 46 CONT_EST_TMR0 ;USADO PARA CONTAR OS ESTOUROS DO TMR0 ENDC ;FIM DO BLOCO DE MEMORIA ;********************************************************************************************** O próximo passo é a definição das constantes. Iremos utilizar duas constantes, uma no valor de 131 que será usada para reinicializar o TMR0 e outra no valor de 125 para a variável que irá contar os estouros do TMR0. Vamos chamá-las de INI_TMR0 e INI_CONT_EST_TMR0. A partir daí, o programa é igual até a configuração dos registradores: ;********************************************************************************************** ; CONSTANTES INI_TMR0 EQU .131 ;VALOR QUE TMR0 INICIA INI_CONT_EST_TMR0 EQU .125 ;VALOR QUE CONT_EST_TMR0 INICIA ;*********************************************************************************************** ; SAÍDA #DEFINE LED PORTA,0 ;LED LIGADO EM RA0 ;*********************************************************************************************** ; VETOR DE RESET ORG 0X00 ;ENDERECO INICIAL DE PROCESSAMENTO GOTO INICIO ;DESVIA PARA INICIO ;*********************************************************************************************** ; ROTINA DE INTERRUPÇÃO ORG 0X04 ;VETOR DAS INTERRUPÇÕES RETFIE ;RETORNA ;*********************************************************************************************** Como iremos utilizar o Timer 0, precisamos configurar o registrador OPTION_REG, que está associado a ele. Esse registradorencontra-se no banco 1 de memória. Conforme consta no datasheet do PIC16F628A, o bit 5 desse registrador, é o que define se o TMR0 será incrementado pelo ciclo de instrução ou a partir de um sinal externo. Para que ele seja incrementado pelo ciclo de instrução, o valor desse bit deve ser igual a 0. 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: Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II 47 ;*********************************************************************************************** ; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO INICIO BANCO_1 ;SELECIONA BANCO 1 DE MEMORIA MOVLW B'11010100' ;W = B'11010100' MOVWF OPTION_REG ;TIMER 0 INCREMENTADO PELO CICLO DE INSTRUCAO, COM PRESCALER DE 1:32 MOVLW B'11111110' ;W = B'11111110' MOVWF TRISA ;CONFIGURA RA0 COMO SAÍDA E DEMAIS COMO ENTRADAS 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 ;*********************************************************************************************** ; INICIALIZACAO DA VARIAVEL MOVLW INI_CONT_EST_TMR0 ;W = INI_CONT_EST_TMR0 MOVWF CONT_EST_TMR0 ;INICIALIZA CONT_EST_TMR0 ;*********************************************************************************************** PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA A primeira instrução da rotina principal é CLRWDT para limpar o WDT. A seguir, iremos testar o bit T0IF do registrador INTCON para verificarmos se o TMR0 estourou: BTFSS INTCON,TOIF ;TMR0 ESTOUROU? Se o TMR0 não houver estourado, o valor desse bit será igual a 0 e a próxima linha do programa será executada. Portanto, nessa linha escreveremos a instrução GOTO PRINCIPAL, para que o bit seja testado novamente. GOTO PRINCIPAL ;NAO Se o TMR0 houver estourado, o valor do bit será igual a 1 e a linha com a instrução GOTO PRINCIPAL será pulada. Nesse caso, a primeira providência que iremos tomar é zerar o bit TOIF para que na próxima vez que o TMR0 estourar possamos detectar a mudança do seu valor para 1: BCF INTCON,T0IF ;SIM 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 Em seguida, decrementamos o valor da variável e ao mesmo tempo verificamos se o seu valor chegou a 0: DECFSZ CONT_EST_TMR0,F ;DECREMENTA CONT_EST_TMR0. CONT_EST_TMR0 = 0? 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: GOTO PRINCIPAL ;NAO Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II 48 Se o valor da variável houver chegado a 0, iremos reiniciá-la e, nesse caso, terão se passado cerca de 500 milissegundos. A partir daqui, o resto da rotina é igual ao do programa da parte I deste tutorial. Portanto, o programa ficou assim: ;*********************************************************************************************** ; PROGRAMA: PISCA LED II ; VERSÃO 1.0 ; DESENVOLVIDO POR: MULDER_FOX ; DATA DE CONCLUSÃO: / / ;*********************************************************************************************** #INCLUDE <P16F628A.INC> ;ARQUIVO PADRAO MICROCHIP PARA O PIC16F628A ;*********************************************************************************************** ; 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 #DEFINE BANCO_0 BCF STATUS,RP0 ;SETA BANCO 0 DE MEMORIA #DEFINE BANCO_1 BSF STATUS,RP0 ;SETA BANCO 1 DE MEMORIA ;********************************************************************************************** ; VARIÁVEIS CBLOCK 0X20 ;ENDERECO INICIAL DA MEMORIA DO USUARIO CONT_EST_TMR0 ;USADO PARA CONTAR OS ESTOUROS DO TMR0 ENDC ;FIM DO BLOCO DE MEMORIA ;********************************************************************************************** ; CONSTANTES INI_TMR0 EQU .131 ;VALOR QUE TMR0 INICIA INI_CONT_EST_TMR0 EQU .125 ;VALOR QUE CONT_EST_TMR0 INICIA ;*********************************************************************************************** ; SAÍDA #DEFINE LED PORTA,0 ;LED LIGADO EM RA0 ;*********************************************************************************************** ; VETOR DE RESET ORG 0X00 ;ENDERECO INICIAL DE PROCESSAMENTO GOTO INICIO ;DESVIA PARA INICIO ;*********************************************************************************************** ; ROTINA DE INTERRUPÇÃO ORG 0X04 ;VETOR DAS INTERRUPÇÕES RETFIE ;RETORNA Tutorial de Programação Assembly para Microcontroladores PIC - Parte 2 – Pisca LED II 49 ;*********************************************************************************************** ; CONFIGURACAO DOS REGISTRADORES DE USO ESPECÍFICO INICIO BANCO_1 ;SELECIONA BANCO 1 DE MEMORIA MOVLW B'11010100' ;W = B'11010100' MOVWF OPTION_REG ;TIMER 0 INCREMENTADO PELO CICLO DE INSTRUCAO , COM PRESCALER DE 1:32 MOVLW B'11111110' ;W = B'11111110' MOVWF TRISA ;CONFIGURA RA0 COMO SAÍDA E DEMAIS COMO ENTRADAS 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 ;*********************************************************************************************** ; INICIALIZACAO DA VARIAVEL MOVLW INI_CONT_EST_TMR0 ;W = INI_CONT_EST_TMR0 MOVWF CONT_EST_TMR0 ;INICIALIZA CONT_EST_TMR0 ;*********************************************************************************************** PRINCIPAL ;ROTINA PRINCIPAL DO PROGRAMA CLRWDT ;LIMPA O WDT BTFSS INTCON,T0IF ;TMR0 ESTOUROU? GOTO PRINCIPAL ;NAO BCF INTCON,T0IF ;SIM MOVLW INI_TMR0 ;W = INI_TMR0 MOVWF TMR0 ;REINICIA TMR0 DECFSZ CONT_EST_TMR0,F ;DECREMENTA CONT_EST_TMR0. CONT_EST_TMR0 = 0? GOTO PRINCIPAL ;NAO MOVLW INI_CONT_EST_TMR0 ;SIM, W = INI_CONT_EST_TMR0 MOVWF CONT_EST_TMR0 ;REINICIALIZA CONT_EST_TMR0 BTFSS LED
Compartilhar