Tutorial PIC - Dos registros às interrupções

Experimente Nosso Instrumento Para Eliminar Problemas





Antes de entrar nos mínimos detalhes da programação PIC, seria importante aprender alguns bons métodos de programação.

Noções básicas sobre registros

Para começar, suponha que você digite um (ponto-e-vírgula) em qualquer ponto do programa, todos os que vierem depois desse ponto-e-vírgula serão ignorados pelo compilador, até que, é claro, o carro volte para a posição.



O recurso acima nos permite adicionar comentários ou observações de forma que eles não se tornem parte do programa, mas nos facilita a identificar o programa com a ajuda dos comentários ao lado dele. Colocar comentários é uma prática recomendada ao programar qualquer IC.

A próxima coisa importante no curso é atribuir nomes às várias constantes (você aprenderia mais tarde). Este aso torna mais simples entender o que está sendo escrito, ou em relação aos valores envolvidos, em vez de se confundir com os números incluídos.



O acima deve ser feito na forma de nomes reais para reconhecimento instantâneo, por exemplo COUNT, seria importante notar que aqui todas as letras maiúsculas são empregadas para torná-lo distinto e também indicar que é um valor constante.


Como podemos ver, o acima é feito na forma de uma caixa feita de ponto-e-vírgula, o que apenas faz com que pareça mais limpo. Além disso, tente documentar o programa no papel também, esta prática ajudará a entender as coisas de uma maneira inteligente.

2. Os registros.

O registro dentro de um PIC é uma área que aceita detalhes escritos e também permite a leitura deles. Você pode compará-lo a uma folha de papel onde você pode visualizar o conteúdo e também adicionar escrevendo sobre ele.

A figura abaixo descreve um mapa de arquivo de registro típico embutido em um PIC16F84. O formato não é algo que é realmente definido dentro do PIC, é simplesmente para indicar como os bits podem ser organizados dentro do chip e para entender alguns dos comandos envolvidos.

Você pode ver que ele está basicamente dividido em Banco 0 e Banco 1. O Banco 1 é responsável por controlar o funcionamento real do PIC, por exemplo, ele informa ao PIC quais bits na Porta A são atribuídos como entradas e quais são como saídas.

O Banco 2 serve apenas para manipular as informações.

Vamos entender isso por meio do seguinte exemplo:

Suponha que desejamos atribuir um bit na porta A alta. Para isso, primeiro precisaríamos ir ao Banco 1 para definir o bit ou pino especificado na Porta A na forma de uma saída. Depois disso, retornamos ao Banco 0 e entregamos uma lógica 1 (bit 1) para aquele pino específico.

Os registros mais comuns que gostaríamos de usar no Banco 1 são STATUS, TRISA e TRISB.

STATUS nos ajuda a retornar ao Banco 0, TRISA nos permite escolher quais pinos na Porta A são saídas e quais podem ser entradas, enquanto TRISB facilita a seleção entre o pino de saída e entrada na Porta B. O registro SELECT no BANCO 0 permite ao usuário para passar para o Banco 1.

Vamos resumir todo o conceito com a seguinte descrição:

STATUS:

Para passar do Banco 0 para o Banco 1, comandamos o registrador STATUS. Isso é implementado definindo o bit # 5 do registro STATUS para 1. Para retornar ao banco 0, atribuímos o bit 5 do registro STATUS para 0. O registro STATUS está posicionado no endereço 03h, aqui h significa o número pode estar em hexadecimal.

TRISA e TRISB:

Eles estão localizados nos endereços 85h e 86h, respectivamente. Para programar um pino como uma saída ou entrada, nós apenas entregamos um zero ou um para o bit particular no registro. Agora, isso pode ser feito de duas maneiras, via binária ou hexadecimal. Caso não seja possível converter o parâmetro, pode-se recorrer a uma calculadora científica para a implementação dos valores.

Agora temos 5 pinos na porta A, o que corresponde a 5 pinos. Se pretendemos corrigir um dos pinos como entradas, entregamos um “1” para o bit específico.

Caso quiséssemos atribuir um dos pinos como saídas, definiríamos o pino específico para “0”. Os bits são auxiliares exatamente correspondentes aos bits, ou mais precisamente, o bit 0 é RA0, o bit 1 seria RA1, o bit 2 = RA2 e assim por diante. Vamos entender desta forma:

Suponha que você deseje corrigir RA0, RA3 e RA4 como saídas, enquanto RA1 / RA2 como i / ps, você faria isso enviando 00110 (06h). Verifique se o bit 0 está à direita, conforme indicado aqui:

Porta A Pino RA4 RA3 RA2 RA1 RA0

Número do bit 4 3 2 1 0

Binário 0 0 1 1 0

O mesmo vale para TRISB.

PORTA e PORTB

Para entregar um dos pinos de saída alto, nós apenas oferecemos um “1” para o respectivo bit em nosso registro PORTA ou PORTB. Um procedimento idêntico pode ser seguido para os registradores TRISA e TRISB também. Antes de acelerarmos em nosso primeiro exemplo de codificação, vamos apenas entender um coupe de mais registradores, viz: w e f.

W e F

O registro W é um registro comum que permite atribuir qualquer valor de sua escolha. Assim que atribuir uma magnitude a W, você pode prosseguir adicionando-o a outro valor ou simplesmente movê-lo. Com outro valor atribuído, os detalhes são simplesmente substituídos em W.

O registrador F encaminha seu material escrito para um registrador. Nós exigiríamos que este registrador F atribuísse um valor sobre um registrador, pode ser sobre o STATUS ou os registradores TRISA, uma vez que estes não nos permitem colocar os valores diretamente sobre eles. Um programa de exemplo

Vamos examinar o código de exemplo a seguir, que nos mostrará como a instrução acima é implementada e também testemunharia algumas das instruções do curso.

Vamos começar corrigindo a Porta A conforme discutido acima.

Para isso, precisamos mudar do Banco 0 para o Banco1, isso é feito configurando o registro STATUS situado no endereço 03h, bit 5 a 1.

BSF 03h, 5

O BSF significa o conjunto de bits F. Estamos usando dois números após esta instrução - 03h, que é o endereço do registrador STATUS, e o número 5 que corresponde ao número do bit.

Então, o que estamos dizendo é “Defina o bit 5 no endereço 03h para 1”.

Agora estamos no Banco 1.

MOVLW 00110b

Estamos colocando o valor binário 00110 (a letra b significa que o número está em binário) em nosso registrador de propósito geral W. Eu poderia, é claro, ter feito isso em hexadecimal, caso em que nossa instrução seria:

MOVLW 06h

Qualquer um funciona. O MOVLW significa 'Mover valor literal para W', que em inglês significa colocar o valor que segue diretamente no registro W.

Agora precisamos colocar este valor em nosso registro TRISA para configurar a porta:

MOVWF 85h

Esta instrução indica “Mova o conteúdo de W para o endereço de registro que segue”; neste caso, o endereço se refere a TRISA.

Nosso registro TRISA neste ponto carrega a figura 00110, ou apresentado graficamente:

Porta A Pino RA4 RA3 RA2 RA1 RA0

Binário 0 0 1 1 0

Entrada / Saída O O I I O

Portanto, agora que possuímos nossos pinos da Porta A, devemos retornar ao Banco 0 para ajustar uma das informações.

BCF 03h, 5

Esta instrução realiza o reverso do BSF. Implica “Bit Clear F”. O par de números que correspondem são o endereço do registrador, aqui o registrador STATUS, bem como a figura do bit, neste caso o bit cinco. O que exatamente concluímos no momento é definir o bit cinco em nosso

STATUS registra-se em 0

Neste ponto, retornamos no Banco 0.
A seguir está o código em um bloco:

BSF 03h, 5 Vá para Banco 1
MOVLW 06h Coloque 00110 em W
MOVWF 85h Mova 00110 para TRISA
BCF 03h, 5 Volte ao Banco 0

Na última instrução, confirmamos a maneira de estabelecer os pinos da porta IO no PIC para serem possivelmente de entrada ou saída.

Por meio deste curso, deixe-me ajudá-lo a enviar dados aos portos.

Envio de dados para portas

No tutorial subsequente, vamos concluir acendendo e apagando um LED que consiste em um detalhamento completo do programa e um diagrama de circuito simples para que você possa ver o PIC executando exatamente o que esperamos.

Não tente montar e programar seu PIC com os resultados abaixo, pois são apenas ilustrações. Inicialmente, estabeleceremos a porta A bit 2 como uma saída:

Isso pode ser reconhecível no ensino anterior. A única distinção poderia ser: corrigimos cada bit dos pinos em A como saída, entregando 0h ao registrador tri-state. Então o que ele deve fazer agora é acender um LED.

Conseguimos isso programando um dos pinos (aquele com o LED vinculado a ele) alto. Em outras palavras, aplicamos um '1' ao pino. É exatamente assim que é feito (observe os comentários para um esclarecimento a cada linha):

Portanto, o que agora conseguimos é ligar e desligar o LED uma vez. O que desejamos é que o LED se ligue subsequentemente e continuamente.

Conseguimos isso obtendo o programa para voltar ao início. Conseguimos isso estabelecendo inicialmente uma marca no início do nosso programa, depois informando o programa para continuar lá. Especificamos uma tag de forma bastante direta.

Digitamos um termo, digamos INICIAR, em seguida digite o código:

Como demonstrado, mencionamos inicialmente a expressão ‘Iniciar’ imediatamente no início do programa.

Em seguida, bem no final do programa, mencionamos claramente ‘goto Start’. A instrução ‘goto’ executa exatamente o que declara.

Este programa ligaria e desligaria consistentemente o LED sempre que ligássemos o circuito, tendendo a desligar assim que removêssemos a eletricidade. Talvez devêssemos verificar nosso programa mais uma vez:

Certamente omitimos os comentários, porém ainda podemos observar as instruções e os números.

Isso pode ser um pouco confuso mais tarde, caso você tente solucionar o programa e, ao escrever o código, memorize todos os endereços.

Embora os comentários possam ser colocados, eles podem ficar um pouco confusos. Isso exigirá nomear os números e pode ser realizado por uma instrução adicional: 'equ' A instrução 'equ' sugere que algumas coisas podem ser iguais a outras coisas.

Pode não ser uma instrução para PIC, mas sim para o montador. Esta instrução facilita a atribuição de nome a uma localização de endereço de registro ou uma constante a um termo de programação.

Vamos estabelecer algumas constantes para nosso programa e também testemunhar o quão simples é a leitura do programa.

Uma vez que fixamos os valores constantes, podemos prosseguir configurando-os em nosso programa. Os valores constantes precisam ser designados antes de usá-los.

portanto, certifique-se sempre de posicioná-los no início do programa. Vamos reescrever o programa, excluindo os comentários, mais uma vez, a fim de comparar a rotulagem anterior com a mais recente.

Pode ser que você esteja percebendo que as constantes estão facilitando um pouco o entendimento do programa, porém ainda estamos sem os comentários, não se preocupe, pois ainda não terminamos.

Pode haver uma pequena desvantagem em nosso programa de LED piscando.
Cada instrução precisa de 1 sequência de clock para terminar. No caso de estarmos utilizando um cristal de 4 MHz, todas as instruções exigem 1/4 MHz ou 1uS para terminar.

Como estamos empregando apenas cinco instruções, o LED seria ativado em 5µS. Isso pode ser rápido demais para que as pessoas percebam; além disso, parece que o LED está totalmente aceso.

O que devemos fazer é produzir uma inibição entre ligar e desligar o LED. A teoria da inibição é que contamos regressivamente a partir de uma quantidade anterior, portanto, quando chega a zero, paramos de contar.

O valor zero significa a conclusão do atraso, e continuamos trabalhando nosso processo ao longo do programa. Portanto, o primeiro que devemos fazer é determinar uma constante para usar como nosso contador.

Vamos chamar essa constante de CONTAGEM. Depois disso, devemos determinar o quão significativo é um número para começar a contar. Certamente, o maior número que poderíamos incluir é 255, ou FFh em hex., Como falei no tutorial anterior, a instrução equ atribui uma expressão a uma situação de registro.

Isso implica que, independentemente da quantidade que alocarmos em nossa CONTAGEM, ela corresponderá aos itens de um registro. Caso tentemos designar o valor FFh, iremos cometer um erro assim que conseguirmos compilar o programa.

A razão de ser o local FFh é, portanto, não podemos obter acesso a ele. Portanto, como devemos designar um número genuíno? Certamente, isso exigirá uma pequena quantidade de ponderação lateral.

Se talvez designássemos nosso COUNT para o endereço 08h, por exemplo, isso indicaria um destino de registro objetivo básico. Por padrão, as áreas intocadas são definidas como FFh. Conseqüentemente, se COUNT levar a 08h, você encontrará o valor de FFh enquanto ligamos pela primeira vez. No entanto, eu você, como podemos corrigir COUNT para outro número ?, tudo o que aplicamos é 'mover' uma avaliação para este destino primeiro.

A título de ilustração, suponha que desejamos que COUNT possua um valor de 85h, não podemos mencionar COUNT equ 85h, pois essa é a posição do registro Tri-State para a Porta A. o valor de 85h no registrador W movwf 08h

Agora mova para o nosso registro das 08h. Posteriormente, no caso de expressarmos COUNT igual a 08h, COUNT corresponderia ao valor 85h. Delicado, não é? Portanto, inicialmente determinamos nossa constante: COUNT equ 08h Em seguida, devemos reduzir esta COUNT em um até que se torne zero.

Simplesmente ocorre que existe uma instrução projetada para fazer isso para nós, fazendo uso de um ‘goto’ e uma tag.

A instrução que vamos aplicar é: DECFSZ COUNT, 1 Esta instrução declara ‘Decrementa o registrador (aqui é COUNT) pelo número que rastreia a vírgula. Se atingirmos zero, pule dois pontos à frente. 'Vamos encontrá-lo em ação primeiro, antes de colocá-lo em nosso curso.

O que fizemos foi estabelecer inicialmente nossa constante COUNT em 255. O segmento subsequente posiciona uma tag, chamada LABEL, perto de nossa instrução decfsz.

O decfsz COUNT, 1 reduz o valor de COUNT em um e retém o resultado final diretamente em COUNT. Além disso, verifica para verificar se COUNT possui o valor 0.

Se não o fizer, nesse caso aciona o programa para mudar para a linha subsequente. Agora temos uma declaração ‘goto’ que nos entrega de volta à nossa instrução decfsz.

No caso de o valor de COUNT ser igual, então a instrução decfsz resulta em nosso programa para saltar 2 pontos à frente e é enviada para onde reivindicamos ‘Continue aqui’.

Portanto, como você pode observar, nós criamos o programa para sentar em um lugar por um tempo predestinado antes de prosseguir. Isso poderia ser chamado de loop de atraso.

Compreendendo os Loops de Atraso

Caso necessitemos de um atraso mais substancial, poderíamos seguir um loop até o próximo. Os loops extras aumentam o atraso. Vamos pelo menos dois, supondo que queiramos observar o flash do LED. Colocaremos esses loops de atraso em nosso programa e realizaremos tornando-o um programa genuíno com a introdução de comentários:

É possível compilar este programa e depois programar o PIC. Obviamente, certifique-se de testar o circuito para verificar se ele realmente funciona. O seguinte é um diagrama de circuito que você deve construir assim que tiver programado o PIC.


Muito bem, você poderia realmente ter composto seu primeiro programa PIC, bem como construído um circuito para acender e apagar um LED. Até agora, caso você tenha feito estes cursos, você pode ter aprendido um total de sete instruções de 35, mas sem dúvida até agora você pode estar controlando as portas de E / S!

Você tentaria alterar os loops de atraso para tornar o flash do LED mais rápido - o que parece ser o valor mínimo de COUNT para essencialmente ver o flash do LED? Ou talvez você deseje incluir um terceiro loop ou loops de retardo suplementares após o inicial para estabilizar o LED. uma constante única para cada loop de atraso.

Você poderia, então, potencialmente mexer em seus loops de atraso para renderizar o flash do LED em uma velocidade específica, por exemplo, após um segundo. Na próxima instrução, vamos ver como podemos utilizar algo conhecido como sub-rotina para manter o programa compacto e básico. Uma sub-rotina é uma parte integrante do código, ou programa, que pode ser referida como e quando você precisar dela. As sub-rotinas são empregadas nos casos em que você realiza a mesma função com frequência.

O que são subrotinas

Os benefícios de empregar uma sub-rotina são que provavelmente será mais simples modificar o valor uma vez dentro de uma sub-rotina em vez de, digamos, dez vezes em todo o seu programa, bem como contribui muito para diminuir o nível de memória que seu programa consome dentro do FOTO. Verificaremos uma sub-rotina:

Inicialmente, precisamos fornecer uma designação à nossa sub-rotina e, nesta situação, selecionamos ROUTINE. Depois disso, digitamos o código que gostaríamos de conduzir normalmente. Por isso, selecionamos o atraso em nosso programa de led piscando. Por último, concluímos a sub-rotina digitando a instrução RETURN.

Para iniciar a sub-rotina de qualquer lugar em nosso programa, digitamos rapidamente a instrução CALL e, em seguida, a designação da sub-rotina.

Vamos considerar isso com um pouco mais de profundidade. Assim que chegarmos à seção de nosso programa que CALL xxx, em que xxx é o nome de nossa sub-rotina, o programa salta para qualquer lugar em que a sub-rotina xxx esteja instalada. As instruções dentro da sub-rotina são realizadas.

Sempre que a instrução RETURN é realizada, o programa salta retornando ao nosso programa principal para a instrução subseqüente à nossa instrução CALL xxx.

É possível chamar a sub-rotina semelhante várias vezes como você gostaria, o que explica porque a utilização de sub-rotinas diminui a duração geral do nosso programa.

No entanto, existem alguns fatores que você deve conhecer. Inicialmente, como no nosso programa principal, quaisquer constantes específicas precisam ser reconhecidas antes que você possa usá-las.

Isso pode ser reconhecido na própria sub-rotina ou diretamente no início do programa principal. Proponho que você reconheça tudo no início de seu programa principal, desde então você reconhece que as coisas estão em uma posição idêntica. Em seguida, deve-se ter certeza de que o programa principal pula a sub-rotina.

O que quero dizer com isso é que você deve colocar a sub-rotina diretamente na conclusão do seu programa principal, exceto se você utilizar uma declaração 'Goto' para saltar de onde a sub-rotina está, o programa continuará e implementará a sub-rotina, independentemente de você exigir ou não.

O PIC não faria distinção entre uma sub-rotina e o programa principal. Veremos nosso programa de led piscando, porém desta vez faremos uso de uma sub-rotina para o loop de retardo. Idealmente, você descobrirá o quanto o programa parece menos complicado, assim como poderá descobrir como a sub-rotina se aplica na prática.

Eventualmente, você pode observar que, utilizando uma sub-rotina para nosso loop de atraso, podemos ter reduzido as dimensões do programa.

Cada vez que desejamos um atraso, possivelmente quando o LED está ligado ou desligado, basicamente chamamos a sub-rotina de atraso. Na conclusão da sub-rotina, o programa leva de volta para a linha seguindo nossa instrução 'Call'. Na ilustração acima, ligamos o LED.

Em seguida, contatamos a sub-rotina. O programa volta então para que possamos desligar o LED. Chamamos a sub-rotina mais uma vez, apenas no caso de a sub-rotina ter sido concluída, o programa volta e a instrução subsequente que ele reconhece é ‘goto Start’. Para qualquer pessoa que possa estar intrigada, nosso primeiro programa tinha 120 bytes de comprimento.

Através do uso da sub-rotina, podemos reduzir o tamanho do nosso programa para 103 bytes. Isso pode não parecer tão fantástico, mas considerando o fato de que temos apenas 1024 bytes no total dentro do PIC, cada pequena quantidade se beneficia.

Na próxima instrução, vamos verificar a leitura das portas.

Até agora, estamos compondo a Porta A para podermos ligar e desligar um LED. Neste ponto, veremos como leremos os pinos de E / S nas portas.

Lendo portas de entrada / saída

Isso é exatamente para garantir que somos capazes de conectar um circuito externo e influenciar quaisquer saídas específicas que ele ofereça.

Se você se lembrar de nossos cursos anteriores, se quiser estabelecer as portas de E / S, precisamos pular do Banco 0 para o Banco 1. Vamos fazer isso inicialmente:

Neste ponto, fixamos o bit 0 da Porta A para a entrada. devemos agora examinar se o pino é alto ou baixo. Para fazer isso, pode-se utilizar apenas uma das duas instruções:

BTFSC e BTFSS.

A instrução BTFSC significa 'Faça um teste de bit no registrador, bem como o bit que designamos.

No caso de ser 0, nesse caso omitimos a instrução subsequente '. BTFSS implica 'Faça um teste de bit no registro e no bit que estabelecemos. No caso de ser definido como 1, ignoramos a instrução subsequente.

O que utilizamos é determinado precisamente por como desejamos que nosso programa responda enquanto estudamos a entrada. A título de ilustração, caso estejamos apenas aguardando que a entrada seja 1, podemos ser capazes de utilizar a instrução BTFSS da seguinte maneira:

Codifique aqui:

BTFSS PortA, 0Goto start Continue aqui:
:

O programa apenas mudaria para ‘Continue aqui’, desde que o bit 0 na PortA esteja programado para 1.

No momento, iremos escrever um programa que pode exibir um LED em uma taxa, no entanto, se um interruptor for confinado, o LED piscará duas vezes mais lentamente.

Talvez seja possível exercitar este programa por conta própria, mas de alguma forma incorporamos a listagem.

Você pode tentar e autorar o programa inteiro, a fim de verificar se você entendeu os princípios. Estaremos usando o circuito equivalente como antes, com a inclusão de um switch conectado RA0 do PIC e o trilho positivo de nossa fonte.

O que conseguimos aqui é ligar o LED. Posteriormente, determino se a chave está desligada.

Caso esteja confinado, em seguida conecto a nossa sub-rotina de delay. Isso nos fornece o atraso equivalente ao de antes, no entanto, neste ponto estamos entrando em contato com ele duas vezes.

A mesma coisa se aplica sempre que o LED está desligado. Caso a chave não esteja desligada, temos nossos períodos de ativação e desativação registrados anteriormente.

Você tem seguido essas lições desde o início, talvez esteja tentando compreender que atualmente descobriu dez das 35 instruções para o PIC 16F84! E cada detalhe disso pode ser aprendido simplesmente ligando e desligando um LED.

Até agora, temos composto o piscar do PIC um LED ligado e desligado.

Posteriormente, fomos capazes de com nosso PIC incluindo um switch, portanto, variando a velocidade do flash.

Usando o espaço de memória com eficiência

O único problema é que o programa é bastante longo e bastante ineficiente de espaço de memória. Parecia ok enquanto eu estava incluindo os comandos pela primeira vez, no entanto, deveria haver uma maneira mais fácil de executá-lo. Positivamente, analisaremos como estávamos literalmente ligando e desligando o LED.

movlw 02hmovwf PORTAmovlw 00hmovlw PORTA

A princípio enchemos nosso registro w com 02h, depois transferimos para nosso registro PortA para acender o LED. Para desligá-lo, empacotamos w com 00h e, em seguida, transferimos para nosso registro PortA.

Entre todas essas rotinas, éramos obrigados a entrar em contato com uma sub-rotina para garantir que poderíamos observar o LED piscando.

Portanto, precisamos transferir dois conjuntos de informações algumas vezes (uma vez para o registrador w e depois para PORTA), bem como chamar uma sub-rotina duas vezes (uma vez para on e outra para off). Portanto, como poderíamos conseguir isso com eficiência adicional? Muito simples.

Utilizamos uma instrução diferente conhecida como XORF. A instrução XORF opera uma função OU exclusiva no registro que estipulamos com as informações que fornecemos. Acho que tenho que esclarecer o que é uma sala de cirurgia exclusiva antes de continuarmos. No caso de termos duas entradas e uma saída, a entrada só pode ser 1 se, e enquanto, as duas entradas forem diferentes. Embora sejam iguais, a saída provavelmente será 0. A tabela a seguir é uma tabela de verdade, para indivíduos que optam por verificar:

A B F0 0 00 1 11 0 11 1 0

Vamos, neste ponto, verificar o que acontece se renderizarmos B da mesma forma que nossa saída anterior, e simplesmente alterar o valor de A:

A B F
0 0 0
0 0 0
1 0 1
1 1 0
1 0 1

Se mantivermos o valor de A igual a 1 e fizermos OR exclusivo com a saída, a saída será alternada. Caso você não consiga perceber isso na tabela verdade, abaixo dela pode ser testemunhado utilizando o binário:

0 Saída de corrente
EX-OR com 1 1 nova saída
EX-OR com 1 0 nova saída

Talvez você possa descobrir que, ao exclusivo OR da saída com 1, estaremos agora alternando a saída de 0 para 1 para 0.
Portanto, para ligar e desligar nosso LED, precisamos apenas de algumas frases:

MOVLW 02h
PORTA XORWF, 1

O que exatamente estaremos realizando é adicionar nosso registro w com 02h. Nesse caso, estamos utilizando o OR exclusivo deste número, independentemente do que esteja em nosso PortA. No caso do bit 1 ser 1, ele será alterado para 0. Caso o bit 1 seja 0, ele será alterado para 1. Vamos examinar este código uma ou duas vezes, para mostrar como ele está executando o binário:

PORTA
00010
xorwf 00000
xorwf 00010
xorwf 00000
xorwf 00010

Na verdade, não temos que carregar o valor idêntico em nosso registrador w todas as vezes, portanto, é possível fazer isso uma vez no início e simplesmente voltar ao nosso comando de alternância. Além disso, não devemos fixar um valor em nosso registro PortA. A razão? Certamente, visto que no caso de ligar é 1, podemos facilmente alterná-lo. Eu, alternativamente um 0 ao ligar, nós agora mesmo o alternaríamos.

Portanto, você gostaria de ver nosso código recém-formado. O primeiro representa nosso código de LED piscando, enquanto o segundo mostra aquele com a adição da chave:

Vamos desejar que você descubra que, simplesmente usando uma instrução fácil, agora reduzimos a escala de nosso programa. A verdade é que, para mostrar o quanto poderíamos reduzir nossos programas, demonstramos os dois programas, apenas o que foram compostos e suas dimensões na tabela abaixo:

Dimensões de alteração do programa (bytes)
Piscando LED Original 120
Subrotina de LED piscando adicionada 103
Função XOR LED piscando usada 91
LED com interruptor original 132
LED com função de interruptor XOR usada 124.

Portanto, não apenas descobrimos algumas novas instruções, mas certamente também diminuímos o tamanho do nosso script!

A seguir, analisaremos como você pode mexer em bits individuais, realizar certas aritméticas simples, bem como tabelas de dados.

Gestores Lógicos

No último tutorial, apresentei a operação OR exclusiva. A função ExOR é entendida como um operador lógico.

Neste tutorial, vou esclarecer os operadores lógicos adicionais que o PIC promove. Não haverá nenhum tipo de caso em programas pontuais, no entanto, aprenderemos métodos fáceis de usar os operadores aplicando pequenas áreas de código.

AND A função AND basicamente analisa dois bits e fornece um 1 se eles são iguais, e um 0 se eles forem distintos. Por exemplo, se mencionamos 1 E 1, o resultado é 1, enquanto no caso de declararmos 1 E 0 a consequência seria 0.

Nem é preciso dizer que também podemos avaliar palavras, assim como tudo o que a função AND realiza é revisar os dois termos aos poucos. A instância abaixo demonstra duas palavras de 8 bits tornando-se AND com o produto:

11001011
AND 10110011
É igual a 10000011

Espero que você concorde, o resultado simplesmente terá um 1 sempre que 2 1s de mãos dadas em um par de palavras. Podemos utilizar a função AND para verificar as portas, por exemplo.

No caso de estarmos verificando alguns pinos de I / O que estão ligados a um circuito, devemos ficar de olho em uma situação particular em que apenas alguns dos pinos estão altos, nesse caso, podemos praticamente ler o porta, após a qual AND o resultado com a condição que estivemos examinando, idêntica à instância acima.

O PIC nos fornece dois ingredientes para AND.
Eles são ANDLW e ANDWF. ANDLW nos permite realizar uma função AND com os detalhes do registro W e um valor que estipulamos.

A sintaxe é: ANDLW em que é exatamente o que vamos fazer com o conteúdo de W.

A consequência da função AND seria armazenada diretamente no registrador W.
ANDWF nos permite realizar uma função AND no registro W e um registro diferente, por exemplo, uma PORT. A sintaxe é: ANDWF, d em que é o registro que nos entusiasma, por ex. PORTA ed mostra o PIC onde você deve posicionar o resultado. Se d = 0, o resultado é colocado no registro W, e de d = 1 o resultado final é salvo no registro que estipulamos. As duas partes do código abaixo exibem um bom exemplo de cada função AND.

A inicial é examinar o status do PORTA, no qual precisamos verificar se as entradas são 1100. Podemos colocar o resultado de volta no registrador W

movlw 1100
ANDWF 05h, 0A segunda ilustração pode agora verificar o conteúdo do registro W:
ANDLW 1100

OU

Agora descobrimos uma função OR, para ser mais preciso, o XOR. Isso se transforma em 1 se dois bits não são iguais, mas são diferentes. Você pode encontrar outra função OR chamada IOR, que é o OR inclusivo. Esta função irá gerar 1 no caso de um dos bits ser 1, mas adicionalmente se cada um dos bits for 1. Abaixo está uma tabela de verdade bem definida para ilustrar isso:

A B O / P
0 0 0
0 1 1
1 0 1
1 1 1

O que são operadores aritméticos

ADICIONAR

Esta função realiza o que normalmente afirma. Contribui com duas figuras! Caso a consequência da adição das duas figuras ultrapasse 8 bits, nesse caso um flag CARRY provavelmente será definido. O sinalizador CARRY está situado no endereço 03h bit 0.

Quando esse bit é programado, os dois números ultrapassam os 8 bits. Quando é 0, a consequência está localizada dentro de 8 bits. Como antes, o PIC nos oferece dois estilos de ADD, especificamente ADDLW e ADDWF. Como você deve ter presumido, essa função é bastante semelhante à acima. ADDLW oferece o conteúdo do registro W conforme estipulamos. A sintaxe é: ADDLW ADDWF adiciona o conteúdo do registro W e algum outro registro que designamos.

A sintaxe é: ADDWF, d é onde

SUB

Neste ponto, eu acho que você não pode presumir o que esta função conduz! Na verdade, você suspeitou, esta função
subtrai um bit do outro. Mais uma vez, o PIC nos oferece 2 sabores: SUBLW e SUBWF. A sintaxe é precisamente semelhante à da função ADD, exceto, evidentemente, que você digita SUB no lugar de ADD!

Incremento No caso de desejarmos incluir 1 a um número no PIC, poderíamos absolutamente fazer uso da função ADD e utilizar o número um. ~ A dificuldade com isso é que devemos primeiro colocar a figura no registrador W e, posteriormente, usar o controle ADDLW 1 para incrementá-la. Caso desejemos incluir 1 em um cadastro, pode ser pior ainda. Devemos primeiro colocar o número 1 no registro W, depois usar ADDWF, 1. Portanto, por exemplo, para incluir 1 no local 0C, digamos, precisaríamos possuir a seguinte parte do script:

movlw 01
addwf 0c, 1

Existe um método mais fácil de fazer isso. Podemos exercer o comando INCF. A sintaxe é: INCF, d onde, é o registro, ou local, no qual estamos interessados, ed mostra o PIC onde você deve posicionar o resultado. No caso d = 0, o resultado está dentro do registrador W, e no caso d = 1, a consequência é colocada no registrador que estipulamos.

Utilizando esta instrução individual, somos capazes de realmente fazer cinquenta por cento da codificação. No caso de desejarmos o resultado restaurado no registro W, nesse caso, empregando a instância acima, poderíamos ter que incluir um comando adicional para deslocar os itens de 0C de volta para o registro W, após o qual colocar o registro 0C de volta para não importa o que seja.

Existe um comando de incremento. É INCFSZ. Este comando pode incrementar o registro que estipulamos, no entanto, se o registro for igual a 0 após o incremento (isso ocorrerá enquanto incluímos 1 a 127), depois disso o PIC provavelmente ignorará a instrução subsequente. A parte do código abaixo reflete isso:

Loop incfsz 0C
Goto Loop
:
:
Restante do programa.

Na parte do código acima, 0C será incrementado em 1. Em seguida, temos uma instrução que informa o PIC para retornar ao nosso tag denominado Loop e incrementar 0C em 1 novamente. Isso continua até que 0C seja igual a 127. Nesta circunstância, quando incrementamos 0C em 1, 0C vai agora corresponder a 0. Nossa instrução INCFSZ poderia muito bem informar o PIC para omitir a instrução subsequente, que neste caso é a declaração goto, portanto, o PIC irá avançar com o restante do programa.

Decrementar

Já discutimos a função de decremento no treinamento anterior, portanto, não a revisarei mais.

Complemento

A instrução final nesta discussão iria reverter cada bit no registrador que estipulamos. A sintaxe é: COMF, d em que

Compreendendo as operações de bits

Isso poderia ser utilizado, por exemplo, para trocar rapidamente os pinos de uma porta de saída para entrada e assim por diante. As funções de bits nos permitem moldar um único bit em uma expressão. Eles nos permitem prosseguir, definir e eliminar bits únicos em registros ou números que estipulamos.

Na conclusão deste curso, iremos divulgar um programa projetado para criar um conjunto de luzes de sequenciamento que avançam para a frente, depois o inverso. Observamos isso realizado anteriormente quando examinamos a função OR exclusiva, em que executamos o OR exclusivo das portas com uma expressão. Até agora notamos algumas funções de bits quando estabelecemos as portas no PIC, e

Deixe-me reiterar sua utilização aqui.

BCF

Esta instrução apagará um pouco o que estipulamos em um registrador que designamos. A sintaxe
é:
BCF,

Empregamos isso anteriormente para alterar da página 1 para a página 0 removendo um bit no registro STATUS. Também podemos usá-lo para fixar um bit em 0 em qualquer registro / localização diferente. Por exemplo, no caso de desejarmos definir o terceiro bit em 11001101 salvo na seção 0C para 0, podemos
inserir:

BCF 0C, 03

BSF

Esta instrução fixaria qualquer bit que estipulássemos como 1 em qualquer registro que indicássemos. Usamos isso anteriormente para prosseguir da Página 0 para a Página 1. A sintaxe é: BSF ,, e é utilizada precisamente no mesmo método do BCF acima.

BTFSCUp até agora podemos definir ou limpar um pouco em um registro. Porém, imagine se precisássemos verificar basicamente se um bit é 1 ou 0 em um registrador?

Certamente, é possível usar BTFSC. Ele indica Bit Test Register F e Skip If Is Clear. Esta instrução vai analisar o bit que designamos no registrador. Caso o bit seja 0, a instrução informaria ao PIC para ignorar a instrução subsequente.

Podemos utilizar esta instrução no caso de desejarmos verificar um sinalizador, por exemplo, o sinalizador de transporte. Isso nos poupa da necessidade de ler o registrador STATUS e de procurar os bits individuais para saber quais sinalizadores são fixos. 29 Por exemplo, no caso de desejarmos verificar se o sinalizador Carry foi definido como 1 após adicionarmos 2 algarismos, poderíamos digitar o seguinte:

BTFSC 03h, 0
continue aqui se definido como 1
ou aqui se definido como 0

No caso do status do bit ser 1, nesse caso a instrução subsequente ao BTFSC seria concluída. No caso de ser definido como 0, nesse caso a instrução subsequente é ignorada. A seguinte parte do código exibe em que pode ser empregado:

Laço :
:
:
BTFSC 03,0
Goto Loop

No código acima, o PIC simplesmente sairá do loop caso o bit 0 do registrador STATUS (ou do sinalizador Carry) seja definido como 0. Do contrário, o comando goto seria conduzido.

BTFSS

Esta instrução declara Bit Test Register F e Skip If Set. Isso pode ser comparável à instrução BTFSC, exceto que o PIC omitiria a instrução subsequente se o bit que estivemos avaliando fosse definido como 1, em vez de 0.

CLRF

Esta instrução fixaria todos os detalhes de um registro em 0. A sintaxe é:

CLRF
Empregamos isso anteriormente para definir a saída das portas como 0, aplicando CLRF 85h. Além disso, nós o empregamos para corrigir as portas para incluir todos os pinos de saída, utilizando CLRF
05h

CLRW

Isso poderia ser semelhante à instrução CLRF, exceto para limpar o registrador W. A sintaxe é muito simples:

CLRW

RLF e RRF

Essas direções transportariam um bit em um registrador um único slot à esquerda (RLF) ou à direita (RRF) em um registrador. Por exemplo, se precisássemos de 00000001 e empregássemos RLF, nesse caso poderíamos possuir 00000010. Nesse ponto, o que acontece caso haja 10000000 e aplicamos a instrução RLF? Certamente, o 1 seria posicionado na bandeira de transporte. Caso aplicássemos a instrução RLF mais uma vez, o 1 reapareceria no início. O mesmo ocorre, porém ao contrário, para a instrução RRF. O caso do ponto abaixo mostra isso para a instrução RLF, na qual podemos ver os 8 bits de um registrador, bem como o flag de transporte:

C 87654321
0 00000001
RLF 0 00000010
RLF 0 00000100
RLF 0 00001000
RLF 0 00010000
RLF 0 00100000
RLF 0 01000000
RLF 0 10000000
RLF 1 00000000
RLF 0 00000001

Programa Exemplo

Agora veremos um código de exemplo que pode ser compilado e dirigido. Isso geraria uma luz de sequenciamento começando na Porta A bit 0, indo para a Porta B bit 8 e
então voltando.
Conecte os LEDs a cada um dos pinos da porta. Teremos um pouco do pedaço
procedimentos apontados neste tutorial.

TIME EQU 9FH Variável para o loop de atraso.
PORTB EQU 06H Endereço da porta B.
TRISB EQU 86H Endereço de Tristate da Porta B.
PORTA EQU 05H Endereço da porta A.
TRISA EQU 85H Porta A Endereço de três estados.
STATUS EQU 03H Registro de seleção de página.
COUNT1 EQU 0CH Loop registrador.
COUNT2 EQU 0DH Loop registrador.

BSF STATUS, 5 Vá para a página 1
MOVLW 00H e configurar
MOVWF TRISB Portas A e B
MOVLW 00H para a saída,
MOVWF TRISA e depois voltar para
STATUS BCF, 5 página 0.
MOVLW 00H Limpar Porta A.
PORTA MOVWF

Início do programa principal

RUNMOVLW
01H Defina o primeiro bitMOVWF
PORTB na porta B.CALL
ATRASO Espere um poucoCALL
ATRASO
Mova a broca na porta B para a esquerda e pause.RLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1CALL
ATRASO
DELAYRLF
PORTB, 1 Isso move a broca para a bandeira de transporte
Agora vá para a porta A e mova a broca para a esquerda.RLF
PORTA, 1 Move o bit da bandeira zero para o PortACALL
DELAYCALL DELAYRLF
PORTA, 1 CHAMADA
ATRASO
DELAYRLF
PORTA, 1 CHAMADA
ATRASO
DELAYRLF
PORTA, 1 CHAMADA
ATRASO
ATRASO
Mova a broca de volta na porta ARRF
PORTA, 1 CHAMADA
ATRASO
DELAYRRF
PORTA, 1 CHAMADA
ATRASO
DELAYRRF
PORTA, 1 CHAMADA
ATRASO
DELAYRRF
PORTA, 1 Isso move o bit para a bandeira zero Agora mova o bit
de volta ao Porto BRRF
PORTB, 1CALL
ATRASO
DELAYRRF
PORTB, 1CALL
ATRASO
DELAYRRF
PORTB, 1CALL
ATRASO
DELAYRRF
PORTB, 1CALL
DELAYCALL DELAYRRF
PORTB, 1CALL
ATRASO
DELAYRRF
PORTB, 1CALL
ATRASO
DELAYRRF
PORTB, 1CALL
ATRASO
DELAY Agora estamos de volta onde começamos, GOTO
RUN vamos de novo.

Existe uma ótima opção no conjunto de treinamento que permite que você faça uso de uma tabela de dados.

Uma tabela de dados é apenas uma lista de cotações de dados, na qual tudo é examinado com base em algumas considerações.
Por exemplo, você poderia ter um circuito que utiliza um PIC que conta a quantidade de instâncias em que um pino de entrada torna-se alto em 1 segundo. Depois disso, você pode exibir o número em um display de 7 segmentos.

Assim que o cronômetro é lançado, o PIC começa a contar a quantidade de ocasiões em que o pino fica alto. Após 1 segundo ele visita a mesa e dá uma olhada nos dados, ele deve exibir o número no display que simboliza a quantidade de situações em que o pino ficou alto. Isso pode ser benéfico, uma vez que não determinamos qual poderia ser o valor até que o PIC tenha realizado sua estimativa.

Ao utilizar uma tabela, podemos permitir que o PIC determine qual figura retratar. Neste ponto, antes de continuar a mostrar a você como a tabela de dados funciona, devo dizer que o PIC mantém o caminho do paradeiro no programa enquanto o programa está operando.

Facilita para aqueles que realizaram certa programação em BASIC. Caso contrário, não fique ansioso, você pode querer continuar a aprender sobre a teoria. Imagine que existe um programa BASIC semelhante ao apresentado abaixo:

10 ANOS K = 0
11 K = K + 1
12 SE K> 10 ENTÃO GOTO 20 OUTRO GOTO 11
20 IMPRIMIR K
21 END

O programa começa na linha 10. Assim que K é programado para 0, ele avança para a linha 11. Depois de incluir 1 em K, prosseguimos para a linha 12.

Neste ponto, podemos estar curiosos para saber se K é maior que 10. Caso seja, em seguida vamos para a linha 20, ou então voltamos para a linha 11.

A linha 20 documenta o K e a linha 21 conclui o programa. O BASIC emprega estatísticas de linha para ajudar o programador a manter um registro de onde estão os problemas, já que os rótulos não são autorizados. O PIC emprega rótulos para escapar entre destinos - ou pode mesmo?

Utilizamos as etiquetas para garantir que estamos cientes de onde estão os problemas, bem como para garantir que podemos informar ao PIC de uma forma simples onde pesquisar.

O que ocorre exatamente é que o PIC tira proveito de um contador de linha interna chamado Contador de Programa. A trilha do contador de programa (abreviado para PC) do destino da memória de onde está a instrução atual.

Sempre que informamos o PIC para visitar uma etiqueta selecionada, ele entende o ponto de memória e, portanto, aumenta o PC até que veja esse destino de memória. Este é precisamente o mesmo método que verificamos o programa BASIC acima. Abaixo está um segmento de código, com os espaços de memória, ou os itens do PC, ao lado de cada instrução:

Instrução PC0000 movlw 03
0001 movwf 0C
0002 Loop decfsc 0C
0003 goto Loop
Fim 0004

Na demonstração acima, fixamos o PC em 0000. Nela temos a instrução movlw 03. Quando o PIC implementa esses dados, ele incrementa o PC para que a instrução subsequente seja digitalizada. Neste ponto, o PIC visualiza movwf 0C. O PC é incrementado novamente.

Agora, o PIC estuda o decfsc 0C. Caso os detalhes de 0C não sejam 0, nesse caso o PC é incrementado em 1, assim como a seguinte instrução, goto Loop, informa o PC para retornar à posição 0003, onde existe o referido Loop. Caso os detalhes de 0C sejam 0, então o PC é aconselhado a incrementar em 2, ou simplesmente omitir a instrução subsequente.

Noções básicas sobre tabelas de dados

Isso coloca o PC na posição 0004, onde o programa termina. Os destinos são fixados pelo montador, e geralmente não devemos nos preocupar com o que o PC está realizando. Até que, encontramos a necessidade de trazê-lo sob controle, assim como fazemos ao utilizar tabelas de dados. A maneira mais conveniente de descrever como uma tabela de dados funciona é começar com uma ilustração.

PC equ. 02
movlw 03
mesa de chamadas
:
mesa addwf PC
retlw 01
retlw 02
retlw 03
retlw 04
retlw 05
retlw 06
retlw 07
Retorna

A instrução inicial é alocar o label PC com o endereço do Program Counter (02h). Logo estaremos colocando o valor 03h no registrador w. Depois disso, comunicamos à mesa. A primeira linha na tabela de sub-rotina aumenta os detalhes do registro W (03h) para o contador do programa.

Isso faz com que o contador do programa aumente em 3 ou, dito de outra forma, estimula o contador do programa a descer 3 linhas. Enquanto o contador chega 3 linhas abaixo, o PIC reconhece a instrução retlw. Este comando envia o valor seguinte para o registrador W, após o qual retorna da sub-rotina. RETLW significa basicamente Retorno, Literal para W.

Veja, coloquei uma vírgula após a palavra Return. Como estamos em uma sub-rotina, exigimos uma instrução Return para superá-la. Portanto, o RET na instrução. Após a instrução RETLW vem um número, e é exatamente isso que é colocado no registrador W.

Neste caso, é a figura 3. Poderíamos designar qualquer quantidade ao registrador W, desde que esta figura seja combinada com o Contador de Programa na sub-rotina da tabela, vamos descobrir uma instrução retlw. Na ilustração acima, isso significa que podemos possuir qualquer número de 1 a 7. Caso prossigamos além da sub-rotina, talvez possamos terminar de executar uma seção adicional do programa. Por esta razão, geralmente é uma jogada inteligente colocar a tabela de dados exatamente no final do programa PIC, portanto, se fizermos o overshoot nesse caso, chegaremos à conclusão do programa de qualquer maneira.

O tópico de interrupções pode muito bem ser o mais longo e difícil de abordar.

Você não pode encontrar nenhum método descomplicado para detalhar as interrupções, no entanto, com um pouco de sorte no final desta parte, você poderá aplicar interrupções em seus próprios programas.
Separamos a seção em 2 fases. Isso permite separar o tópico em seções, também para fornecer a você uma divisão útil para fácil compreensão.

O que exatamente é uma interrupção? Certamente, como o termo indica, uma interrupção é uma técnica ou um sinal que impede um microprocessador / microcontrolador de qualquer coisa que esteja realizando para que algo diferente possa acontecer.

Permita-me apresentar uma ilustração diária. Pense que está relaxando em sua própria casa, conversando com outra pessoa. De repente, o telefone toca.

Você para de falar e pega o telefone para falar com o chamador. Depois de ter sua interação por telefone, você decide voltar a conversar com a pessoa antes que o telefone toque. É possível considerar a rotina principal enquanto você conversa com alguém, o toque do telefone atrapalha sua conversa e a quebra da rotina é o método de falar ao telefone.

Quando a conversa por telefone chega ao fim, você volta à sua rotina principal de bate-papo. Esta ilustração é exatamente como um processador interrompe uma ação.

O programa principal está operando, realizando certa função em um circuito, no entanto, quando ocorre uma interrupção, o programa principal é interrompido enquanto uma rotina diferente é executada. Quando a rotina termina, o processador volta para a rotina principal como antes.

Compreendendo as interrupções

O PIC possui 4 fontes de interrupção. Eles podem ser divididos em dois grupos. Duas são fontes de interrupções que podem ser utilizadas externamente para o PIC, enquanto as outras duas são processos internos. Deixe-me esclarecer os dois tipos externos aqui. Os outros dois serão descritos em diferentes tutoriais assim que chegarmos aos cronômetros e ao armazenamento de dados.

Se você verificar a pinagem do PIC, notará que o pino 6 é RB0 / INT. Neste ponto, RB0 é claramente a porta B bit 0. O INT representa que ele também poderia ser configurado como um pino de interrupção externa. Além disso, os pinos 4 a 7 da porta B (pinos 10 a 13) também podem ser utilizados para interrupções. Antes de podermos empregar o INT ou outro pino da Porta B, devemos realizar duas tarefas. Em primeiro lugar, devemos informar o PIC que utilizaremos interrupções.

Em seguida, devemos designar qual pino da porta B usaremos como uma interrupção em vez de como um pino de E / S. Dentro do PIC você encontra um registro conhecido como INTCON, e está no endereço 0Bh. Neste registro você descobrirá 8 bits que podem estar habilitados ou desabilitados. O bit 7 do INTCON é conhecido como GIE. Este é o Global Interrngupt Enable. Fixar isso em 1 informa ao PIC que usaremos uma interrupção.

O bit 4 de INTCON é conhecido como INTE, INTerrupt Enable. Colocar este bit em 1 transmite ao PIC que RB0 será um pino de interrupção. Configurando o bit 3, chamado RBIE, informa ao PIc que iremos utilizar os bits 4 a 7 da Porta B. Neste ponto o PIC entende quando este pino pode ser alto ou baixo, tem que parar o que está executando e prosseguir com uma interrupção rotina. Neste ponto, devemos informar ao PIC se a interrupção será ou não na transformação da borda ascendente (0V a + 5V) ou na borda descendente (+ 5V a 0V) do sinal.

Simplificando, desejamos que o PIC interrompa cada vez que o sinal muda de baixo para alto ou de alto para baixo. Por delinqüência, isso pode ser estabelecido para ser colocado na borda ascendente.

O 'triggering' de borda é programado em um registro adicional denominado registro OPTION, no endereço 81h. A parte que nos entusiasma é a parte 6, geralmente conhecida como INTEDG.

Definir como 1 ativa o PIC para interromper na borda de montagem (estado padrão) e defini-lo como 0 estimula o PIC para interromper na borda deslizante. Se você deseja que o PIC seja ativado na borda ascendente, certamente não precisa fazer nada com este bit.

Neste ponto, infelizmente, o registro de opções está no Banco 1, o que significa que gostamos de modificar do banco 0 para o banco 1, definir o bit no registro de opções e, em seguida, retornar ao banco 0. A chave aqui é realizar cada bit do Banco 1 registra em um único strike, por exemplo estabelecendo os pinos da porta, depois voltando para o Banco 0 se estiver pronto.

Tudo bem, conseqüentemente notificamos o PIC qual pino provavelmente será a interrupção, e onde a borda disparar, o que acontece no programa e no PIC sempre que a interrupção acontecer? Algumas coisas acontecem. Primeiro, uma 'bandeira' é programada.

Isso informa ao processador interno do PIC que ocorreu uma interrupção. Em seguida, o contador do programa (sobre o qual falei no tutorial anterior) aponta para um endereço específico dentro do PIC. Vamos verificar rapidamente tudo isso individualmente. Sinalizador de interrupção Em nosso registro INTCON, o bit 1 é o sinalizador de interrupção, denominado INTF. Nesse ponto, sempre que ocorrer qualquer interrupção, esse sinalizador provavelmente será fixado em 1.

Quando não há uma interrupção, o sinalizador é colocado em 0. Além disso, é praticamente tudo o que acontece. Neste ponto, você pode estar se perguntando 'qual é o ponto?' Certamente, embora este sinalizador esteja programado para 1, o PIC não é capaz de, e não irá, reagir a outra interrupção. Portanto, vamos expressar que provocamos uma interrupção. O sinalizador provavelmente será fixado em 1, e o PIC pode ir para a nossa rotina para trabalhar a interrupção.

Quando este sinalizador não foi fixado em 1, e o PIC foi autorizado a continuar respondendo à interrupção, então pulsar continuamente o pino poderia manter o PIC retornando ao início de nossa rotina de interrupção, e de forma alguma completá-la. Voltando à minha ilustração do telefone, é semelhante a levantar o telefone e, imediatamente, depois de começar a discutir, ele começa a tocar novamente porque outra pessoa deseja falar com você.

É aconselhável concluir um diálogo e, em seguida, pegar o telefone novamente para falar com a pessoa subsequente. Você pode encontrar um pequeno problema com este sinalizador. Mesmo que o PIC defina rapidamente este sinalizador para 1, ele não o define novamente como 0! Essa atividade deve ser exercida pelo programador - ou seja, você. Isso pode ser realizado sem esforço, uma vez que estou certo de que presumo, e precisa ser alcançado após o PIC realizar a rotina de interrupção.

Localização da Memória Sempre que você liga o PIC pela primeira vez, ou no caso de haver um reset, o Contador de Programas dica para endereçar 0000h, que pode estar imediatamente no início da memória do programa. Porém, caso haja uma interrupção, o Contador de Programa indicaria o endereço 0004h.

Portanto, enquanto estamos compondo nosso programa que terá interrupções, devemos primeiramente informar o PIC para saltar o endereço 0004h, e manter a rotina de interrupção que começa no endereço 0004h discreta do restante do programa.

Isso pode ser fácil de realizar. Inicialmente, iniciamos nosso programa com um comando conhecido como ORG. Este comando indica Origem ou início. Nós o mantemos com um endereço. Como o PIC começa no endereço 0000h, digitamos ORG 0000h. Depois disso, devemos ignorar o endereço 0004h. Conseguimos isso colocando uma instrução GOTO, acompanhada por um rótulo que aponta para o nosso programa principal.

A seguir aderimos a este comando GOTO com mais um ORG, neste momento com o endereço 0004h. Será após este comando que inseriremos nossa rotina de interrupção. Neste ponto, podemos possivelmente digitar nossa rotina de interrupção diretamente após o segundo comando ORG, ou podemos posicionar uma instrução GOTO que aponta para a rotina de interrupção.

Ele realmente está relacionado à opção de sua parte. Para informar ao PIC que ele oferece chegou a conclusão da rotina de interrupção, devemos posicionar o comando RTFIE próximo ao final da rotina. Este comando significa retorno da rotina de interrupção. Enquanto o PIC percebe isso, o contador do programa indica a posição final em que o PIC estava antes de ocorrer a interrupção. Estabelecemos abaixo uma breve seção de código para exibir o acima:

Existem alguns itens que você deve ser informado ao utilizar interrupções. A inicial tende a ser que, se você estiver utilizando o registro idêntico em seu programa principal e a rotina de interrupção, lembre-se de que os detalhes do registro provavelmente serão alterados quando a interrupção ocorrer.

Por exemplo, vamos utilizar o registro w para encaminhar dados para o programa principal da Porta A, portanto, você pode utilizar adicionalmente o registro w na rotina de interrupção para transferir dados de um destino para outro.

Caso você não seja cauteloso, o registro w incluiria o último valor recebido enquanto estava na rotina de interrupção, então quando você retornar da interrupção esta informação será entregue na Porta A ao invés do valor que você possuía antes a interrupção ocorreu.

O meio para contornar isso é salvar momentaneamente os detalhes do registro w antes de utilizá-lo novamente na rotina de interrupção. O segundo é o fato de que você pode encontrar um atraso entre o momento em que uma interrupção ocorre e quando a subsequente pode surgir. Enquanto você entende, o PIC possui um relógio externo, que poderia ser um cristal ou uma combinação resistor-capacitor.

Não importa a frequência deste relógio, o PIC o divide por 4, após o que o emprega para seu tempo interno. Por exemplo, no caso de você ter um cristal de 4 MHz vinculado ao seu PIC, nesse caso o PIC executaria as instruções a 1 MHz. Este tempo interior é conhecido como Ciclo de Instrução. Nesse ponto, a planilha de dados afirma (sem dúvida em uma impressão diminuta) que você precisa habilitar de 3 a 4 rodadas de instrução entre as interrupções.

Meu seria permitir 4 rodadas. A razão por trás do atraso é que o PIC requer tempo para saltar para o endereço de interrupção, o sinalizador, e voltar para longe da rotina de interrupção. Portanto, mantenha isso em mente se você trabalhar com um circuito alternativo para ativar uma interrupção para o PIC.

Neste ponto, um ponto importante é o fato de você utilizar os bits 4 a 7 da Porta B como uma interrupção. Você não consegue escolher pinos específicos na porta B para funcionar como uma interrupção.

Portanto, caso você permita esses pinos, é provável que todos possam ser obtidos. Portanto, por exemplo, você não pode simplesmente ter os bits 4 e 5 - os bits 6 e 7 provavelmente serão habilitados ao mesmo tempo. Qual é exatamente o propósito de fazer com que quatro bits representem uma interrupção? Certamente, você pode ter um circuito conectado ao PIC, no caso de qualquer uma das quatro linhas ficar alta; nesse caso, pode ser um problema que você precisa que o PIC influencie instantaneamente.

Uma ilustração disso poderia ser um alarme de segurança residencial, no qual quatro sensores estão ligados aos pinos 4 a 7 da Porta B. Qualquer sensor específico pode solicitar que o PIC acione um alarme, e a rotina de sinalização de alarme é a rotina de interrupção. Isso poupa a verificação das portas constantemente e permite que o PIC continue com diferentes assuntos. No próximo tutorial, iremos compor um programa para gerenciar uma interrupção.

Tratamos de muitos aspectos básicos no último tutorial, portanto, acho que chegou a hora de compor nosso primeiro programa.

O programa que escreveremos contará a quantidade de ocasiões em que ligamos uma chave e, em seguida, exibirá o número.

O programa contaria de 0 a 9, visível em 4 LEDs em forma binária, junto com a entrada ou interrupção provavelmente em RB0.

A primeira coisa que devemos fazer é informar o PIC para pular o endereço para o qual o contador de programa aponta sempre que ocorrer uma interrupção.

Você observará que estamos empregando um método único de exibição de números hexadecimais. Antes de acontecer aplique F9h em que h indicava hexadecimal. Poderíamos escrever como 0xF9, que é a estrutura que vamos empregar a partir de agora.

Agora precisamos dizer ao PIC que vamos usar interrupções, e estamos usando RB0 pino 6 como um pino de interrupção:

bsf INTCON, 7GIE - Habilitar interrupção global (1 = habilitar)
bsf INTCON, 4INTE - habilitação de interrupção RB0 (1 = habilitar)
Vou limpar o sinalizador de interrupção para o caso (eu nunca confio em nada!)
bcf INTCON, 1INTF - Limpa o bit de sinalização apenas no caso

Atualmente devemos estabelecer nossas 2 portas. Lembre-se de que, como agora estamos utilizando RB0 como um pino de interrupção, isso precisa ser estabelecido como uma entrada:

Vamos usar uma variável chamada COUNT para armazenar o número de contagens de switch. Poderíamos simplesmente incrementar o valor na Porta A, mas você verá por que estou usando uma variável quando escrevemos nossa rotina de interrupção.

Portanto, nosso programa principal é composto, e neste momento devemos informar ao PIC como proceder sempre que ocorrer uma interrupção. Dentro deste exemplo, nossa interrupção provavelmente será a troca. O que gostaríamos que fosse o PIC é um para o COUNT ajustável toda vez que a chave fosse confinada.

No entanto, queremos apenas mostrar quantas vezes o switch desliga de 0 a 9. Acima, afirmei que poderíamos simplesmente aumentar o valor na Porta A toda vez que houver uma interrupção. No entanto, a porta A tem 5 bits, caso simplesmente tenhamos incrementado a porta, teremos a contagem mais alta de 31. Existem algumas explicações porque optei por não mover para 31.

Inicialmente, vamos empregar uma tela de 7 segmentos, que no máximo poderia ir de 0 a 15 (0 a F em hexadecimal). A seguir, desejo também mostrar alguns dos comandos aritméticos que você encontrou nas últimas lições.

Portanto, continuaremos com nossa rotina de interrupção. Atualmente a primeira coisa que devemos realizar é armazenar brevemente os detalhes de nosso registro w, já que estamos aplicando isso para mudar o conteúdo de COUNT para PORTA. Caso não o salvemos, nesse caso podemos ser capazes de entregar um número totalmente diferente por causa de nossa aritmética. Portanto, vamos fazer isso primeiro:

Neste ponto, entendemos se o valor de COUNT é 9 ou mais. O que precisamos fazer agora é se COUNT for maior que 9, coloque-o de volta em 0 ou então retorne ao programa principal para garantir que podemos entregá-lo à Porta A. O comando BTFSS, desde que você entenda, seria o seguinte
instrução no caso do sinalizador de transporte estar programado, ou seja, COUNT = 10:

A única coisa que falta fazer agora é inserir coletivamente, bem como determinar valores para nossas constantes, que podemos executar logo no início de nosso programa.

Cada vez que você ativar a chave, os LEDs farão uma contagem regressiva em binário de 0000 a 1010 e retornarão a 0000.

A figura a seguir mostra o diagrama de circuito compatível com o código explicado acima. Curiosamente, você verá que o capacitor de temporização foi incluído no projeto. Este é um pequeno estratagema agradável, através do qual você obtém a liberdade de evitar a inclusão do capacitor no caso de você não ter nenhum com você durante esse tempo.

Aqui, a capacitância entra em ação por meio da capacitância parasita no pino do oscilador e no aterramento.
Claro que pode não parecer uma maneira muito inteligente de evitar um capacitor praticamente, uma vez que o valor de dispersão pode variar com diferentes condições.

Outra seção que pode ser observada no circuito é a rede denunciante no switch. Isso evita a interferência durante a comutação mecânica e evita que o PIC fique confuso se a comutação for uma única alternância ou várias alternâncias.




Anterior: Circuito de temporizador de motor bidirecional programável Próximo: Como funcionam os circuitos Buck-Boost