Ir ao conteúdo
  • Cadastre-se

Tutorial de PIC - Programação em Assembly


Posts recomendados

Oi pessoal.

Estou criando um programa que ficou muito extenso, e estou a usar todas paginas, repetindo algumas subrotinas. A questão é, será possivel chamar uma subrotina em uma certa pagina a partir de mais de uma pagina diferente. por exemplo criei um pseudo-codigo


ROTINA_A ;pag. 0

BSF PCLATH,3
BSF PCLATH,4
CALL ROTINA_X ;pag. 3



ROTINA_B ;pag. 1

BSF PCLATH,3
BSF PCLATH,4
CALL ROTINA_X ;pag. 3



ROTINA_C ;pag. 2

BSF PCLATH,3
BSF PCLATH,4
CALL ROTINA_X ;pag. 3



ROTINA_X ;pag. 3

??PCLATH??
RETURN


A ideia é essa aí, eu gostaria de saber se isso é possivel, e qual seria o estado do PCLATH antes do RETURN. Agradeço qualquer ajuda.

Link para o comentário
Compartilhar em outros sites

Sim, você pode fazer isso. E é assim mesmo que se faz. Antes da instrução RETURN, não precisa, pois o endereço completo do retorno consta na pilha.

Aconselho você a fazer assim:

MOVLW HIGH ROTINA_X

MOVWF PCLATH

CALL ROTINA_X

Dessa forma, se você fizer uma alteração no programa (aumento ou diminuição) e a posição inicial da rotina mude de página, o PCLATH será configurado corretamente.

Link para o comentário
Compartilhar em outros sites

Compilando como Relocatable,o linker decide os enderços na memória.

A estrutura de programação é assim.

Exemplo:

BANK0		UDATA	     ;OS DADOS VÃO SER GUARDADOS NA ÁREA DE DADOS (USER DATA )
Variavel_01 RES 4 ;RESERVA 4 LOCALIZAÇÕES DE MEMÓRIA (LINKER VAI USAR)

................
STARTUP CODE 0X0000 ;voce PODE DEFINIR O INICIO DO CÓDIGO OU NÃO

................
Inicio CODE ;CASO NÂO DEFINA ENDEREÇO LINKER DEFINIRÀ

.............
APPLICATION CODE ;O LINKER DEFINE O ENDEREÇO AUTMATICAMENTE
MAIN


........
END

Use Relocatable quando se tem arquivos de include.

Link para o comentário
Compartilhar em outros sites

é assim mesmo que se faz. Antes da instrução RETURN, não precisa, pois o endereço completo do retorno consta na pilha.

Ja tentei fazer isso antes e não deu certo a solução foi repetir varias subrotinas e o programa agora ocupa mais 6k (o programa envolvia escrita de caracteres no LCD atraves de um teclado). Criei um pequeno programa e depois de alguma luta funcionou :confused: . Talves tenha cometido algum erro.

;------------------------------------------------------------------------------------

;###########TESTANDO PAGINAS################

MAIN

BCF PCLATH,3

BCF PCLATH,4

BTFSS PORTB,0

CALL ACEND0

BTFSC PORTB,1

GOTO $+2

PAGESEL ACEND1

CALL ACEND1

BTFSC PORTB,2

GOTO $+2

PAGESEL ACEND2

CALL ACEND2

GOTO MAIN

ACEND0

BSF PORTC,0

CALL PAUSA0

BCF PORTC,0

CALL PAUSA0

BSF PCLATH,3

BSF PCLATH,4

CALL ACENDE

BSF PORTC,0

CALL PAUSA0

BCF PORTC,0

CALL PAUSA0

RETURN

ORG 0X0800

ACEND1

BSF PORTC,1

CALL PAUSA1

BCF PORTC,1

CALL PAUSA1

BSF PCLATH,3

BSF PCLATH,4

CALL ACENDE

BSF PORTC,1

CALL PAUSA1

BCF PORTC,1

CALL PAUSA1

RETURN

ORG 0X1000

ACEND2

BSF PORTC,2

CALL PAUSA2

BCF PORTC,2

CALL PAUSA2

BSF PCLATH,3

BSF PCLATH,4

CALL ACENDE

BSF PORTC,2

CALL PAUSA2

BCF PORTC,2

CALL PAUSA2

RETURN

ORG 1800

ACENDE

BSF PORTC,0

CALL PAUSA

BSF PORTC,1

CALL PAUSA

BSF PORTC,2

CALL PAUSA

BCF PORTC,0

CALL PAUSA

BCF PORTC,1

CALL PAUSA

BCF PORTC,2

RETURN

Compilando como Relocatable,o linker decide os enderços na memória.

Não percebi ao certo o seu uso. Como assim decide os endereços de memoria?

Link para o comentário
Compartilhar em outros sites

Por exemplo:

APPLICATION	CODE         ;O LINKER DEFINE O ENDEREÇO AUTMATICAMENTE
MAIN

Veja que não definí onde começa o 'MAIN',apenas coloquei o LABEL 'CODE'.

O linker ,na hora de compilar,vai decidir automáticamente o melhor lugar para 'MAIN" começar.

Quando se copilar em modo 'ABSOLUTE',o Linker não é usado.

Link para o comentário
Compartilhar em outros sites

  • mês depois...

Realmente dá pra ver que foi algo que lhe dispendeu muito tempo, parabéns! Eu sou iniciante neste mundo dos microcontroladores. Como programador, sempre tive uma grande curiosidade em aprender linguagem Assembly. Decidi que eu a aprenderia fazendo pequenos projetos com microcontroladores.

Enfim, sou iniciante, e decidi usar o PIC SIMULATOR IDE para começar a ter uma noção das coisas antes de investir dinheiro mesmo. Só que esse seu código assembly não compila no assembler do IDE, você me saberia dizer o porque? Eu simplesmente ainda to meio perdido, tentando achar na net alguns livros/tutoriais que possam começar a me esclarecer as coisas.

Link para o comentário
Compartilhar em outros sites

XVirtusX.

Futebol = Brasil.

ASM,C(PIC) = Microchip.

Use o MPLAB para ASM e C18 pra cima para C.

Tá certo, vtrx, valeu pelo toque, já baixei aqui o MPLAB e vou testar. Ao Mulder, pude agora de noite olhar com mais calma o seu "livro" e realmente está muito bom, parabéns mesmo cara. Um excelente manual.

Link para o comentário
Compartilhar em outros sites

Mais uma vez obrigado XVirtusX.

Para os próximos dias estarei adicionando a 8ª parte, que é um frequencímetro simples para medir frequências de até 10 kHz. Nela explico como fazer adição, subtração, multiplicação e divisão de números de até 32 bits (4 registradores de 8 bits), além do uso das instruções RLF e RRF.

Link para o comentário
Compartilhar em outros sites

Só uma coisa besta.

não é DELAY_O com Ó mas DELAY_0 com zero.

não seria esse o problema?

Abs.

é verdade, Felipe, foi um erro estúpido, hehe. Mas, me diga uma coisa. Procurei aqui no fórum e vi que você conhece o PIC SIMULATOR IDE. Esse primeiro código que o Mulder colocou nesse tutorial, eu compilei normalmente pelo MPLAB (nao compila pelo assembler do SIMULATOR) e não tá acontecendo nada com os leds.

Já passei a tarde inteira revisando esse código e não consegui muita coisa. Se você tiver o SIMULATOR no seu PC, por favor, teste esse código e me diga se aí tá funcionando ou não.

Dando uma fuçada no código junto com um outro tutorial para PIC16F84 que achei na net, consegui fazer com que o LED acenda, mas ele nao apaga mais. E pelo que eu vi, ele nao tá decrementando na instrução DECFSZ, por isso que não tá apagando. Dêem uma olhada nesse código maluco que eu fiz por favor....

#INCLUDE<P16F84.INC>

STATUS EQU 0X03
TRISA EQU 0X85
PORTA EQU 0X05
COUNT1 EQU .255
COUNT2 EQU .50

;***********SETANDO A PORTA*****************
bsf STATUS,RP0
MOVLW 0X00
MOVWF TRISA
BCF STATUS,RP0

START
MOVLW 02h
MOVWF PORTA

LOOP1
DECFSZ COUNT1,F
GOTO LOOP1
DECFSZ COUNT2,F
GOTO LOOP1

MOVLW B'0000000'
MOVWF PORTA

LOOP2
DECFSZ COUNT1,F
GOTO LOOP2
DECFSZ COUNT2,F
GOTO LOOP2

GOTO START

END

Também tentei com a instrução DECFSZ COUNT1,1

mas nao funcionou... se alguém puder ajudar fico agradecido!

Link para o comentário
Compartilhar em outros sites

é verdade, Felipe, foi um erro estúpido, hehe. Mas, me diga uma coisa. Procurei aqui no fórum e vi que você conhece o PIC SIMULATOR IDE. Esse primeiro código que o Mulder colocou nesse tutorial, eu compilei normalmente pelo MPLAB (nao compila pelo assembler do SIMULATOR) e não tá acontecendo nada com os leds.

Já passei a tarde inteira revisando esse código e não consegui muita coisa. Se você tiver o SIMULATOR no seu PC, por favor, teste esse código e me diga se aí tá funcionando ou não.

Dando uma fuçada no código junto com um outro tutorial para PIC16F84 que achei na net, consegui fazer com que o LED acenda, mas ele nao apaga mais. E pelo que eu vi, ele nao tá decrementando na instrução DECFSZ, por isso que não tá apagando. Dêem uma olhada nesse código maluco que eu fiz por favor....

Também tentei com a instrução DECFSZ COUNT1,1

mas nao funcionou... se alguém puder ajudar fico agradecido!

tente usar instruções a bit, será mais simples


START

BSF PORTA,1
CALL DELAY
BCF PORTA,1
CALL DELAY

Se voce inclui a bibilioteca creio que não seja necessario definir a posição dos TRIS e dos PORTs.

Link para o comentário
Compartilhar em outros sites

Tenta assim;

#INCLUDE<P16F84.INC>

STATUS EQU 0X03
TRISA EQU 0X85
PORTA EQU 0X05
COUNT1 EQU .255
COUNT2 EQU .50

;***********SETANDO A PORTA*****************
bsf STATUS,RP0
MOVLW 0X00
MOVWF TRISA
BCF STATUS,RP0

START
MOVLW 02h
MOVWF PORTA

LOOP1
DECFSZ COUNT1,F
GOTO LOOP1
DECFSZ COUNT2,F
GOTO $-1

MOVLW B'0000000'
MOVWF PORTA
CALL RECARREGA

LOOP2
DECFSZ COUNT1,F
GOTO LOOP2
DECFSZ COUNT2,F
GOTO $-1
CALL RECARREGA
GOTO START
RECARREGA
MOVLW .255
MOVWF COUNT1
MOVLW .50
MOVWF COUNT2
RETURN

END

Ou mais simplificado;

#INCLUDE<P16F84.INC>

STATUS EQU 0X03
TRISA EQU 0X85
PORTA EQU 0X05
COUNT1 EQU .255
COUNT2 EQU .50

;***********SETANDO A PORTA*****************
bsf STATUS,RP0
MOVLW 0X00
MOVWF TRISA
BCF STATUS,RP0

START
MOVLW 02h
MOVWF PORTA

CALL ATRASO
MOVLW B'0000000'
MOVWF PORTA
CALL ATRASO
GOTO START

ATRASO
MOVLW .255
MOVWF COUNT1
MOVLW .50
MOVWF COUNT2
DECFSZ COUNT1,F
GOTO $-1
DECFSZ COUNT2,F
GOTO $-1
RETURN

END

Link para o comentário
Compartilhar em outros sites

Realmente só pode ser problema do PIC SIMULATOR, uma pena, pois achei a interface dele amigável, mas tá bugado, eu tentei a tarde inteira fazer código assembly de tudo que é jeito. Tentei agora também os códigos do vtrx e do LEOPUENA e compila normalmente mas ele simplesmente nao reconhece nenhum comando para decrementar.... e fica num loop infinito no primeiro GOTO que ele chega.

Mas valeu pelas dicas ae!

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...
  • 2 meses depois...
... participo de um site de compartilhamento de apostilas...

Perdoem o [off], mas sendo um compartilhamente mister, poderia indicar o "endereço" aos amigos membros deste forum, pois deve haver muita informação que será de grande valia/auxilio para todos. É só uma dica.

Abç.

Link para o comentário
Compartilhar em outros sites

Perdoem o [off], mas sendo um compartilhamente mister, poderia indicar o "endereço" aos amigos membros deste forum, pois deve haver muita informação que será de grande valia/auxilio para todos. É só uma dica.

Abç.

http://downtronica.blogspot.com/

amigo esse site é bom mesmo só apostila nota 10 as melhores coisas escritas aqui no brasil estão la sobre eletronica sobre pic eletricidade (o que é uma categoria diferente de eletronica fala de campo magnetico algumas leis etc) e muito muito mais

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

amigo esse site é bom mesmo só apostila nota 10 as melhores coisas escritas aqui no brasil estão la sobre eletronica sobre pic eletricidade (o que é uma categoria diferente de eletronica fala de campo magnetico algumas leis etc) e muito muito mais

Gostei muito do site, realmente é bastante interessante. Tem esse aqui que também é muito bom, um pouco parecido com o outro.

Link para o comentário
Compartilhar em outros sites

oi tudo bem eu so novo aqui e queria q vocês me ajudassem estou tentando programar um pic 16f628a com codigo mais sempre aparece o erro(de verificação no endereço 0x000000 verificando:0x3ff lendo:0x0000 o que fazer?gostaria muito se vocês podesem me ajudar !obrigado pela atenção o codigo é o seguinte:

#use delay (clock=4000000)

#fuses INTRC_IO, NOWDT, PUT, NOBROWNOUT, NOLVP, NOMCLR

#include <lcd_flex.C>

#define C1 PIN_A6

#define C2 PIN_A7

#define C3 PIN_A0

#define L1 PIN_A1

#define L2 PIN_A2

#define L3 PIN_A3

#define L4 PIN_A4

#define B PIN_B3

#define T PIN_B2

int i = 0;

int j = 0;

//******************************************************************************

void scan1(){ // Faz primeira varredura

int aux=100; // Tempo de varredura

while(aux != 0) // Laço para varredura

{

output_low(L1); // Joga 0 na coluna a ser varrida e 1 nas demais

output_high(L2);

output_high(L3);

output_high(L4);

if(input(C1) == 0) // Testa primeira coluna

{

i = 1;

j ++;

delay_ms(20); // Tempo para soltar tecla

// Chama a sub-rotina correspondente a tecla

}

if(input(C2) == 0) // Testa segunda coluna

{

i = 2;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

if(input(C3) == 0) // Testa terceira coluna

{

i = 3;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

aux--; // Decrementa 1 de aux

delay_us(aux); // Tempo de atraso da varredura é igual a aux

}

output_high(L1);

output_high(L2);

output_high(L3);

output_high(L4);

return; // Retorna

} // Fim da sub-rotina

//******************************************************************************

void scan2(){ // Faz primeira varredura

int aux=100; // Tempo de varredura

while(aux != 0) // Laço para varredura

{

output_high(L1); // Joga 0 na coluna a ser varrida e 1 nas demais

output_low(L2);

output_high(L3);

output_high(L4);

if(input(C1) == 0) // Testa primeira coluna

{

i = 4;

j ++;

delay_ms(20); // Tempo para soltar tecla

// Chama a sub-rotina correspondente a tecla

}

if(input(C2) == 0) // Testa segunda coluna

{

i = 5;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

if(input(C3) == 0) // Testa terceira coluna

{

i = 6;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

aux--; // Decrementa 1 de aux

delay_us(aux); // Tempo de atraso da varredura é igual a aux

}

output_high(L1);

output_high(L2);

output_high(L3);

output_high(L4);

return; // Retorna

} // Fim da sub-rotina

//******************************************************************************

void scan3(){ // Faz primeira varredura

int aux=100; // Tempo de varredura

while(aux != 0) // Laço para varredura

{

output_high(L1); // Joga 0 na coluna a ser varrida e 1 nas demais

output_high(L2);

output_low(L3);

output_high(L4);

if(input(C1) == 0) // Testa primeira coluna

{

i = 7;

j ++;

delay_ms(20); // Tempo para soltar tecla

// Chama a sub-rotina correspondente a tecla

}

if(input(C2) == 0) // Testa segunda coluna

{

i = 8;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

if(input(C3) == 0) // Testa terceira coluna

{

i = 9;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

aux--; // Decrementa 1 de aux

delay_us(aux); // Tempo de atraso da varredura é igual a aux

}

output_high(L1);

output_high(L2);

output_high(L3);

output_high(L4);

return; // Retorna

} // Fim da sub-rotina

//******************************************************************************

void scan4(){ // Faz primeira varredura

int aux=100; // Tempo de varredura

while(aux != 0) // Laço para varredura

{

output_high(L1); // Joga 0 na coluna a ser varrida e 1 nas demais

output_high(L2);

output_high(L3);

output_low(L4);

if(input(C1) == 0) // Testa primeira coluna

{

i = 10;

j = 10;

delay_ms(20); // Tempo para soltar tecla

// Chama a sub-rotina correspondente a tecla

}

if(input(C2) == 0) // Testa segunda coluna

{

i = 11;

j ++;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

if(input(C3) == 0) // Testa terceira coluna

{

i = 12;

j = 12;

delay_ms(20); // Tempo para soltar a tecla

// Chama a sub-rotina corresponde a tecla

}

aux--; // Decrementa 1 de aux

delay_us(aux); // Tempo de atraso da varredura é igual a aux

}

output_high(L1);

output_high(L2);

output_high(L3);

output_high(L4);

return; // Retorna

} // Fim da sub-rotina

//******************************************************************************

void BIP(){

output_high(B);

delay_ms(100);

output_low(B);

}

//******************************************************************************

void ABRIR(){

output_high(T);

output_high(B);

delay_ms(2000);

output_low(T);

output_low(B);

}

//******************************************************************************

void main()

{

int d_1 = 0;

int d_2 = 0;

int d_3 = 0;

int d_4 = 0;

int d_5 = 0;

set_tris_a(0b11100001); //Define as entradas e saidas da porta "a"

set_tris_b(0b00000000); //Define as entradas e saidas da porta "b"

output_a(0); //Coloca todas as portas de "a" em nivel logico baixo

output_b(0); //Coloca todas as portas de "b" em nivel logico baixo

lcd_init();

while(TRUE) //Começo do programa

{

while(j == 0)

{

printf (lcd_putc, "\p\f..REP AREA 51.." );

printf (lcd_putc, "\n DIGITE A SENHA " );

scan1();

scan2();

scan3();

scan4();

}

BIP();

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n *");

d_1 = i;

delay_ms(500);

j = 1;

while(j == 1)

{

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n *");

scan1();

scan2();

scan3();

scan4();

}

BIP();

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n **");

d_2 = i;

delay_ms(500);

j = 2;

while(j == 2)

{

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n **");

scan1();

scan2();

scan3();

scan4();

}

BIP();

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n ***");

d_3 = i;

delay_ms(500);

j = 3;

while(j == 3)

{

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n ***");

scan1();

scan2();

scan3();

scan4();

}

BIP();

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n ****");

d_4 = i;

delay_ms(500);

j = 4;

while(j == 4)

{

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n ****");

scan1();

scan2();

scan3();

scan4();

}

BIP();

printf (lcd_putc, "\f SENHA ");

printf (lcd_putc, "\n *****");

d_5 = i;

delay_ms(500);

j = 5;

if( j == 5 )

{

if(d_1 == 2 && d_2 == 5 && d_3 == 6 && d_4 == 3 && d_5 == 8 )

{

printf (lcd_putc, "\fBem vindo "antonio" ");

printf (lcd_putc, "\n Senha correta ");

ABRIR();

delay_ms(3000);

i = 0;

j = 0;

}

else

{

printf (lcd_putc, "\fSenha incorreta");

printf (lcd_putc, "\nTente novamente");

BIP();

delay_ms(100);

BIP();

delay_ms(100);

BIP();

delay_ms(100);

BIP();

delay_ms(100);

BIP();

delay_ms(100);

BIP();

delay_ms(3000);

i = 0;

j = 0;

}

d_1 = 0;

d_2 = 0;

d_3 = 0;

d_4 = 0;

d_5 = 0;

}

}

#include <16F628.h>

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...