collapse

* Posts Recentes

Amplificador - Rockboard HA 1 In-Ear por almamater
[Ontem às 19:13]


O que é isto ? por KammutierSpule
[26 de Março de 2024, 19:35]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Emulador NES em ESP32 por dropes
[13 de Março de 2024, 21:19]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]


Meu novo robô por josecarlos
[06 de Janeiro de 2024, 16:46]


Laser Engraver - Alguém tem? por almamater
[16 de Dezembro de 2023, 14:23]

Autor Tópico: Conseguir tempos exactos pic16f628a  (Lida 2834 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline vicardosof

  • Mini Robot
  • *
  • Mensagens: 223
Conseguir tempos exactos pic16f628a
« 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

Offline Sérgio_Sena

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.649
    • Electronic Gear for Musicians
Re: Conseguir tempos exactos pic16f628a
« Responder #1 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 :)

Offline vicardosof

  • Mini Robot
  • *
  • Mensagens: 223
Re: Conseguir tempos exactos pic16f628a
« Responder #2 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.