LusoRobótica - Robótica em Português

Sistemas específicos => PIC => Tópico iniciado por: vicardosof em 16 de Outubro de 2010, 04:02

Título: Conseguir tempos exactos pic16f628a
Enviado por: vicardosof em 16 de Outubro de 2010, 04:02
Boas!
Estou a estudar os pics. Surgiu-me uma dúvida: como consigo tempos exactos, como um segundo ou um minuto para fazer um relógio, por exemplo?

obs: Estou a programar em assembly
Título: Re: Conseguir tempos exactos pic16f628a
Enviado por: Sérgio_Sena em 16 de Outubro de 2010, 10:41
Olá,
boa iniciativa estar a estudar PIC em Assembler.

Para termos tempos exactos, temos que fazer as nossas funções de acordo com o que queremos. E se estamos a trabalhar com um oscilador de 4.0MHz, então temos que encadear CALLs de funções temporizadoras, para ter o que queremos.
E não esquecer que como o barramento de dados é só de 8-bits, só podemos contar até 0xFF ou 255.

Por exemplo, uma função que faz 500us, pode ser feita da seguinte maneira ::

Código: [Seleccione]

list p=16f628A ;configura o tipo de CPU usado
radix hex ;pre-definicao do tipo de valores numericos usados

include "p16f628a.inc" ;

;---------------------------
temp equ 0x20 ;define endereco 0x20 com o nome de TEMP
;---------------------------

inicio

call atraso_500u ;chama rotina de atraso
call atraso_500u ;chama rotina de atraso

goto inicio ;faz temporizacao de novo

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

atraso_500u
movlw 0xA5 ;carrega W com o valor 0xA5
movwf temp ;move valor em W para TEMP

decfsz temp, f ;decrementa TEMP em uma unidade, coloca resultado em TEMP
;e salta a instrucao seguinte, se o resultado for zero
goto $-1

return ;sai fora da rotina de ATRASO

;---------------------------
end


De cada que chama a função de 500us, entre a chamada/execução/saída passam exactamente 500us estando a usar oscilador 4.0MHz.



A função a seguir faz exactamente 100ms entre a chamada/execução/saída com oscilador de 4MHz.

Código: [Seleccione]

    list    p=16f628A        ;configura o tipo de CPU usado
    radix    hex                ;pre-definicao do tipo de valores numericos usados
   
    include    "p16f628a.inc"    ;

    __config    _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _INTOSC_OSC_NOCLKOUT & _PWRTE_ON & _WDT_OFF

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

temp    equ        0x20        ;define endereco 0x20 com o nome de TEMP
temp2    equ        0x21        ;define endereco 0x21 com o nome de TEMP2

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

inicio

    ;configura toda a porta A como entrada/saida DIGITAL
    movlw    0x07        ;carrega W como valor de 0x07
    movwf    CMCON        ;move de W para CMCON

    ;configura portas A e B como entradas/saidas
    bsf        STATUS,5    ;activa bit 5 do registo STATUS

    movlw    0x00        ;carrega W como 0x00, todos pinos porta A como saida
    movwf    TRISA        ;move de W para TRISA
    movlw    0x00        ;carrega W como 0x00, todos pinos porta A como saida
    movwf    TRISB        ;move de W para TRISB

    bcf        STATUS,5    ;desactiva bit 5 do registo STATUS
   
repete
   
    movlw    0xFF            ;carrega W com valor de 0xFF
    xorwf    PORTB, f        ;inverte porta B (XOR, OU Exclusivo com o W)
   
    call    atraso_100m        ;chama rotina de atraso

    goto    repete            ;faz temporizacao de novo


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

atraso_100m
    movlw    0xC9        ;carrega W
    movwf    temp2        ;move valor em W para TEMP

    movlw    0xA4        ;carrega W
    movwf    temp        ;move valor em W para TEMP
    decfsz    temp, f        ;decrementa TEMP em uma unidade, coloca resultado em TEMP
     goto    $-1            ;salta para uma instrucao anterior
   
    nop
    decfsz    temp2, f    ;decrementa TEMP em uma unidade, coloca resultado em TEMP
     goto    $-6            ; salta para duas instrucoes anteriores

    movlw    0x20        ;carrega W
    movwf    temp        ;move valor em W para TEMP
    decfsz    temp, f        ;decrementa TEMP em uma unidade, coloca resultado em TEMP
     goto    $-1            ;salta para uma instrucao anterior

    nop

    return                ;sai fora da rotina de ATRASO


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

    end




Como pode ver, há muitas maneiras de o fazer. Cada programador pode fazer da sua, e todas funcionam. É preciso é encontrar um método que funcione para si, e manter-se nele.

Eu, pessoalmente, faço temporizadores sempre com os TMRx e interrupções.
Criei algoritmos que me dão TICKs a cada 1ms/10ms/100ms/1s, assim posso ficar descansado com o programar principal e não tenho o CPU ocupado a "contar tempo". É +- como nos PLCs.


Para poder contar o tempo certo, tem uma ferramenta que é o STOPWATCH, no menú DEBUGGER, depois de activar o MPLAB SIM.
E para configurar o oscilador da simulação: DEBUGGER-SETTINGS.


bom trabalho! espero que tenha ajudado :)
Título: Re: Conseguir tempos exactos pic16f628a
Enviado por: vicardosof em 16 de Outubro de 2010, 15:40
Era isto que queria, obrigado!

Estou há apenas dois dias a programar em assembly, isso foi de grande ajuda.
Tinha visto um outro atraso, que chamaram de atraso por software. O único problema é que não fornece tempos exactos e sempre está em +- meio segundo.