Eletronica‎ > ‎

PIC - Assembly - Criando um programa


COMENTÁRIOS
Para comentar basta usar o ponto-e-vírgula ;
Exemplo:
;Isto é um comentário.

INCLUDES
Este comando chama um arquivo que contém várias definições que iremos usar em nosso programa. Geralmente estes arquivos possuem a extensão .INC e contém definições  de nomes e endereços dos registradores especiais (SFRs). Quando você estiver em um nível mais avançado também poderá criar seus próprios arquivos de definições.

Exemplo:
#INCLUDE    <nome_arquivo.inc>

ou podemos indicar o local onde se encontra o arquivo: C:\diretorio\arquivo.inc (no Windows) ou /diretorio/arquivo.inc (no Linux)


REPRESENTAÇÃO DE NÚMERO:

DECIMAL (n representa o número neste exemplo)
D'nn'    ou    .nn

HEXADECIMAL
H'nn'    ou    0Xnn

BINÁRIO
B'nnnnnnnn'

ASCII
A'n'


EQU
Usamos para definirmos constantes ou associarmos uma palavra a um endereço de memória que está nossa variável.

Sintaxe para usar EQU:
nome_da_variável EQU endereço_da_memória

ou
nome_da_constante EQU valor_da_constante

Exemplos usando a sintaxe EQU para associar uma palavra a um endereço de memória:
STATUS   EQU    H'003'
FSR      EQU    H'0004'
PORTA    EQU    H'0005'
PORTB    EQU    H'0006'

Assim, quando aparecer a palavra PORTB, será substituída pelo número 06 (em hexadecimal) que corresponde ao endereço de memória do PORTB.


#DEFINE
Permite substituir expressões por texto.

Exemplo:
#DEFINE    LED    PORTB,2


ORG ou CODE
ORG É usado para direcionar para posição de memória de programação. Usamos no vetor de reset, vetor de interrupção, e em alguns PICs para paginação da área de programa. Nos novos compiladores pode usar o CODE. (Exemplo: RES_VECT  CODE    0x0000).
No PIC 16F628A, o vetor de reset encontra-se no endereço 0x00 então temos que usar esta diretriz ORG 0x00 antes da escrita da primeira instrução do programa.


END
Usada para encerrar o programa.


CBLOCK e ENDC
Usado para definirmos vários EQUs. Informamos o endereço apenas da primeira variável e as demais serão definidas na sequência.

Exemplo:
CBLOCK 0x20        ;Endereço inicial da memória de usuário
    W_TEMP         ;Variável
    STATUS_TEMP    ;Variável
ENDC


W
O registrador de trabalho W (work) é o mais utilizado durante o programa. É um registrador utilizado nas operações da ULA. Não faz parte da memória RAM do sistema. É um registrador temporário que através dele é possível ler ou escrever na memória.


Bancos de Memória
O PIC16F682A possui quatro bancos de memória onde ficam os registradores especiais (SFRs) e a memória de variáveis do sistema. Para acessar algum registrador que está no banco 1, por exemplo, temos que primeiramente dizer ao sistema que queremos mudar de banco. Assim, devemos alterar os bits RP0 e RP1 do registrador STATUS. Na tabela abaixo temos as combinações para acessar cada banco:

Banco    RP1    RP0
    0          0        0
    1          0        1
    2          1        0
    3          1        1

Como iremos usar apenas os bancos 0 e banco 1, precisamos alterar apenas o RP0. Para facilitar podemos fazer a seguinte definição:
#DEFINE  bank0  bcf  STATUS,RP0   ;Muda para banco 0
#DEFINE  bank1  bsf  STATUS,RP0   ;Muda para banco 1

Lembrando que sempre que acessarmos o banco 1 devemos retornar para o banco 0.

Observação: Existe uma diretriz do compilador chamada BANKSEL. Com ela podemos fazer a mudança de banco em qualquer modelo de PIC mantendo um padrão. O único problema é que consome mais memória de programa em relação a proposta anterior porque ela sempre atualiza os valores de RP0 e RP1. Veja abaixo um exemplo para o PIC16F628A. Observe que ele associa a palavra BANK ao endereço inicial de memória respectivo de cada banco.
BANK0    EQU 0X00    ;Muda para o banco 0
BANK1    EQU 0X80    ;Muda para o banco 0
BANK2    EQU 0X100   ;Muda para o banco 0
BANK3    EQU 0X180   ;Muda para o banco 0

Obs.: Neste casa, para mudar de banco ao longo do código temos que usar o comando banksel. (Exemplo: banksel BANK0).

MOVLW
Este comando move um número (um literal) para o registrador word (W).
Sintaxe:
MOVLW   k   ;k é o número que será movido para W.

Exemplo:
MOVLW  .10  ;Move o número decimal 10 para W.


MOVWF
Este comando move o valor que encontra-se no registrador W para outro registrador (f) que pode ser um nome pré-definido no arquivo include ou o endereço de memória do qual se encontra. Também move para uma variável.
Sintaxe:
MOVWF  f  ;Move o valor de W para f, onde f é um endereço de memória de um registrador ou uma variável

Exemplo:
MOVWF  OPTION_REG  ;Move o valor de W para o registrador OPTION_REG


MOVF
Este comando move o valor de um registrador (f) para o destino d (d pode ser o registrador W ou outro registrador)
Sintaxe:
MOVF  f,d  ;f é o registrador que será movido para d

Exemplo:
MOVF  Tempo,w  ;Move o valor da variável Tempo para o registrador W


CLRF
Limpa um registrador.
Sintaxe:
CLRF  f  ;f pode ser o nome do registrador ou o seu endereço de memória.

Exemplo:
CLRF  TRISB  ;Escreve zero no registrador TRISB (Define PORTB como saída).


GOTO
Executa um desvio do programa.
Sintaxe:
GOTO  local  ;Onde "local" é uma palavra que encontra-se no código para onde queremos desviar.

Neste caso, a palavra "local" pode ser substituída por outra que melhor desejar (como INICIO, BOTAO, etc). Ela servirá como uma identificação para onde o programa deve ser desviado. Utilize "_" no lugar de espaços.
Podemos usar o GOTO para dar saltos mais curtos utilizado o caracter $. Veja o exemplo:
GOTO  $+2  ;Salta 2 linhas para baixo.
GOTO  $-3  ;Salta 3 linhas para cima.


Dando nome a 1 bit de um byte
Podemos dar um nome a um bit de um byte, chamamos isso de Flags. Dessa forma podemos criar até oito flags em um byte. Para isso, criamos uma variável com qualquernome, pode chamar flag, depois damos nome para cada bit dessa variável. Veja o exemplo:
CBLOC 0x0C    ;Endereço de memória onde será salvo nossa variável chamada flag.
    FLAG      ;Nome da nossa variável
ENDC          ;Fim do bloco de memória

#DEFINE  Primeiro  FLAG,0  ;Associamos a palavra "Primeiro" ao bit zero da nossa variável FLAG.
#DEFINE  Segundo   FLAG,0  ;Associamos a palavra "Segundo" ao bit zero da nossa variável FLAG.

Também podemos definir nomes para cada pino do PIC. Exemplo:
#DEFINE   LED    PORTB,1   ;Associamos a palavra "LED" ao pino RB1.
#DEFINE   Botao  PORTA,0   ;Associamos a palavra "Botao" ao pino RA0.


BTFSC
Esta instrução testa um bit de uma porta, de uma variável ou de um flags. Para entender melhor a o comando podemos ler assim: Testa T o Bit B do registrador F e Salta S a próxima linha se a resporta for zero C.
Sintaxe:
BTFSC   f,b   ;f é o registrador ou variável e b é o bit deste a ser testado.
linhaA        ;Passa por esta linha se a resposta for falsa.
linhaB        ;Salta para esta linha se a resposta for verdadeira

Podemos definir um bit de um registrador ou uma variável para facilitar a programação.
Exemplo:
#DEFINE  BOTAO  PORTB,3    ;Palavra BOTAO agora está associada ao pino RB3. (1=Liberado; 0=pressionado)
BTFSC    BOTAO             ;Se o botão estiver pressionado...
GOTO     Botao_Liberado    ;Não, vai para Botao_Liberado
GOTO     Botao_Pressionado ;Sim, vai para Botao_Pressionado


BTFSS
Esta instrução é o inverso da BTFSC. Pode ser lida da seguinta maneira: Testa T o Bit B do registrador F e Salta S a próxima linha se a resporta for 1 S.
Sintaxe:
BTFSS   f,b   ;f é o registrador ou variável e b é o bit deste a ser testado.
linhaA        ;Passa por esta linha se a resposta for falsa.
linhaB        ;Salta para esta linha se a resposta for verdadeira

Exemplo:
#DEFINE  BOTAO  PORTB,3    ;Palavra BOTAO agora está associada ao pino RB3. (0=Liberado; 1=pressionado)
BTFSS    BOTAO             ;Se o botão estiver pressionado...
GOTO     Botao_Liberado    ;Não, vai para Botao_Liberado
GOTO     Botao_Pressionado ;Sim, vai para Botao_Pressionado


BSF
Esta instrução é usada para alterar um bit. O BSF seta o bit (muda para 1).
Sintexe:
BSF  f,b  ;f é o registrador ou variável e b é o bit que será setado

Exemplo:
#DEFINE  LED  PORTB,2   ;Palavra LED agora está associada ao pino RB2.
BSF      LED            ;Seta o LED com 1


BCF
Esta instrução é usada para alterar um bit. O BCF zera o bit (muda para 0).
Sintexe:
BCF  f,b  ;f é o registrador ou variável e b é o bit que será zerado

Exemplo:
BCF      PORTB,2            ;Torna o RB2 como zero.


Constantes
Podemos substituir um número por uma palavra para facilitar alterações futuras em nosso código ou memo facilitar a leitura.
Exemplo:
MeiaDuzia EQU .6 ;Agora, quando referimos a palavra "MeiaDuzia" sera o mesmo que o número 6.


Vetor de Reset
O vetor de reset é um endereço na memória para qual o programa é desviado quando ocorre um reset. No PIC 16F628A esse endereço é 0x00. O reset ocorre quando o PIC é energizado. Também pode ocorrer pelo Master Clear externo (MCLR) ou pelo estouro de WDT.
Exemplo para compiladores antigos:
ORG  0x00     ;Endereço onde o reset é desviado
GOTO  INICIO  ;Desvia para as configurações iniciais (como as de entrada/saída, etc).

Exemplo para os novos compiladores:
RES_VECT  CODE  0x0000  ;Endereço onde o reset é desviado
GOTO  INICIO            ;Desvia para as configurações iniciais (como as de entrada/saída, etc).

Início do Programa
No início, temos que fazer as configurações principais do nosso programa, como, definir as portas de entrada e saída (TRISA e TRISB), opções de operações (OPTION_REG), opções de interrupções (INTCON). Obs.: Dê uma olhada nos bits dos registradores OPTION_REG e do INTCON para ver mais informações.
Exemplo de um início de programa:
INICIO
 BANK1               ;Muda para o Banco 1.
 CLRF   TRISB        ;Escreve zero em TRISB (Então PORTB está definido como saída)
 MOVLW  B'00000001'  ;Move o número 1 para W
 MOVWF  TRISA        ;Move W para TRISA (Define o RA0 como entrada e o restante como saída)
 MOVLW  B'10000100'  ;Move o número para W.
 MOVWF  OPTION_REG   ;Configura Prescaler de 1:32 no TMR0 e pull-ups desabilitados.
 BANK0               ;Volta para o banco 0.

;Inicialização das variáveis (Devemos iniciar as variáveis mesmo que o valor seja zero)
 CLRF   PORTA          ;Desliga todas as saídas do PORTA
 CLRF   PORTB          ;Desliga todas as saídas do PORTA
 MOVLW  .50            ;Move o número 50 para W.
 MOVWF  MinhaVariavel  ;Move o número 50 MinhaVariavel.


Rotinas de chamada
A rotina pode ser usado como uma função que será chamada a qualquer momento no programa.
Sintaxe:
CALL  MinhaRotina  ;Este comando chama o trecho do codigo onde está definido a "MinhaRotina"

A rotina CALL parece com a instrução GOTO, porém, ela tem uma vantagem de retornar a linha seguinte do trecho do código que foi chamada. Quando a rotina CALL é chamada, é armazenado na pilha (Stack) o endereço seguinte ao ponto chamado. No final da rotina devemos inserir a instrução RETURN ou RETLW para o sistema voltar ao endereço armazenado na pilha.
Sintaxe para retornar:
RETURN      ;Volta na linha seguinte onde foi chamado a rotina (último endereço da pilha)
RETLW   k   ;Volta na linha seguinte onde foi chamado a rotina com o valor do literal k em W.



Exemplo 1 - Pisca LED
Neste primeiro exemplo iremos escrever um programa que pisque um LED que está conectado ao pino RB1 sempre que o botão em RA2 for pressionado.

Figura 1 - Esquema elétrico do primeiro exemplo Pisca Led.


Código:
;PROGRAMA: PISCA-LED AO PRESSIONAR UM BOTÃO

;Definicoes:
#INCLUDE <p16f628a.inc>
    __CONFIG _BODEN_ON & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_ON & _XT_OSC

;Definicoes dos banco de memoria
BANK0    EQU 0X00    ;Muda para o banco 0
BANK1    EQU 0X80    ;Muda para o banco 0
BANK2    EQU 0X100   ;Muda para o banco 0
BANK3    EQU 0X180   ;Muda para o banco 0

;Definições de variaveis, constantes ou flags:
    CBLOCK 0x20    ;Endereço inicial da memória de usuário
    d1         ;Variável para Delay
    d2         ;Variável para Delay
    d3         ;Variável para Delay
    ENDC

;Definicoes de entradas
#DEFINE    Botao    PORTA,2    ;Botao: 1=Solto, 0=Pressionado.

;Definicoes de saida
#DEFINE    LED    PORTB,1    ;LED ligado ao pino RB1

;Vetor de Reset
    ORG    0x00        ;Endereco que inicia o processamento.
    GOTO    INICIO    ;Salta para as configuracoes de inicio do programa.

;Interrupções
;Nao utilizaremos interrupcoes neste programa
    ORG    0x04    ;Endereco onde o programa eh desviado quando ha uma interrupcao.
    RETFIE    ;Retorna da interrupcao.

;Configuracoes de inicio do programa
INICIO
    CLRF    PORTA        ;Limpa o PORTA
    CLRF    PORTB        ;Limpa o PORTB
    banksel    BANK1        ;Muda para o banco1
    MOVLW    B'00000100'    ;Move o numero para W
    MOVWF    TRISA        ;Move w p/ TRISA que configura RA2 como entrada e o resto como saída.
    MOVLW    B'00000000'    ;Move o numero para W
    MOVWF    TRISB        ;Move w p/ TRISB que configura todos os pinos do PORTB como saida.
    MOVLW    B'10000000'    ;Move o numero para W
    MOVWF    OPTION_REG    ;Configura: Prescaler 1:2 no TMR0; PULL-UPS desabilitados.
    MOVLW    B'00000000'    ;Move o numero para W
    MOVWF    INTCON        ;Move w p/ INTCON onde desabilita todas as interrupcoes.
    banksel    BANK0        ;Volta para o banco 0.
    MOVLW    B'00000111'    ;Move o numero para W
    MOVWF    CMCON        ;Move w p/ CMCON onde define o modo de operacoes do comparador.

;Rotina principal
MAIN
    BTFSC    Botao            ;Testa se o Botao esta pressionado.
    GOTO    Botao_solto        ;Salta para o trecho que trata o botao solto.
    GOTO    Botao_pressionado    ;Salta para o trecho que trata o botao pressionado.

Botao_solto
    BCF    LED        ;Apaga o LED
    GOTO MAIN        ;Salta para MAIN

Botao_pressionado
    BSF    LED        ;Acende o LED
    Call    Delay_500ms    ;Aguarda 500ms
    BCF    LED        ;Apaga o LED
    Call    Delay_500ms    ;Aguarda 500ms
    GOTO MAIN        ;Salta para MAIN

   
Delay_500ms:
;Clock frequency = 4 MHz
;Fonte: http://www.piclist.com/techref/piclist/codegen/delay.htm
   
    movlw    0x03
    movwf    d1
    movlw    0x18
    movwf    d2
    movlw    0x02
    movwf    d3
Delay_500ms_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    $+2
    decfsz    d3, f
    goto    Delay_500ms_0
            ;6 cycles
    goto    $+1
    goto    $+1
    goto    $+1
    return
   
    END        ;Fim do programa





































Comments